Приложение А – примеры программного кода

Отчёт по курсовой работе

по дисциплине

«Разработка информационно - управляющих систем»

на тему:

«Разработка приложения для Android «Track tracking»»

ПОЯСНИТЕЛЬНАЯ ЗАПИСКА

 

Студент группы ПИМ-19                                                          Головкин Д. М.

Студент группы ПИМ-19                                                           Соколов Д. С.

Руководитель                                                                                    Ломанов А.Н.

Рыбинск 2020



Содержание

 

1   Постановка задачи. 3

2   Используемые инструменты и технологии. 4

3   Назначение приложения и функциональные требования. 5

4   Заключение. 6

5   Литература. 7

Приложения. 8

Приложение А – примеры программного кода. 8

Приложение Б - Интерфейс программы……………………………………………………....14

 

 



Постановка задачи

 

 

Целью курсовой работы является написание программы, способной обрабатывать потом данных и на его основе давать результат. Входными данным являются GPS координаты устройства, с которого выполняется программа. Координаты приходят несколько раз в секунду, что позволяет на их основе строить карту маршрутов и определять местонахождение пользователя.

 



Используемые инструменты и технологии

 

 

В качестве языка разработки программного продукта, был выбран Kotlin, так как он предоставляет все необходимые компоненты и библиотеки для создания и стабильной работы в Android.

Kotlin – статически типизированный, объектно-ориентированный язык программирования, работающий поверх Java Virtual Machine и разрабатываемый компанией JetBrains. Благодаря его преимуществам, он был выбран приоритетным языком для создания Android-приложения компанией Google. Вот некоторые из плюсов языка:

1) Простые функции и структуры можно объявить одной строкой.

2) Геттеры и сеттеры задаются за кулисами для интероперабельности с Java-кодом.

3)  Kotlin не допускает возникновения NullPointerException, выдавая ошибку компиляции.

4) В Kotlin содержатся специальные классы, предназначенные специально для хранения данных. Они генерируют различные шаблоны: equals(), hashCode(), toString(), геттеры и сеттеры и т.д.

5) Так же Kotlin позволяет расширять функциональность существующих классов, не прибегая к наследованию. Это делается при помощи функций-расширений. Для объявления такой функции к её имени нужно приписать префикс в виде расширяемого типа.

6) Kotlin — это следующий этап развития Java, с которой он полностью совместим. Это делает его отличным инструментом для мобильных и энтерпрайз-приложений.

 

 



Назначение приложения и функциональные требования

 

 

Мобильные устройства часто используются для решения различных задач связанных с определением географических координат. Транспорт, строительство, путешественники, так или иначе, нуждаются в определении своего местоположения или других объектов. Реализация данного приложения поможет людям избегать плутания на местности и возвращаться в точку начала движения.

 

Функциональные требования

· Определения сторон света

· Отображение компаса на экране устройства

· Отображение карты на экране устройства

· Установка на карте отметок пройденного пути


 


Этапы реализации

 

Задачу реализации программы можно разбить на 3 этапа:

1. получение GPS координат и их обработка

2. симуляция компаса на экране

3. отображение данных на карте

 

 

1. Получение gps координат и их обработка:

 

В Android SDK весь функционал по работе с навигационными системами объединён в пакет android.location. Ключевые компоненты данного пакета:

· LocationManager – (класс) обеспечивает доступ к системной службе определения местоположения Android;

· LocationListener — (интерфейс) регламентирует обработку приложение событий службы определения местоположения Android;

· Location – (класс) представляет географические координаты полученные от навигационной системы.

Первым делом необходимо предоставить приложению необходимые разрешения в файле манифеста. Определяем поставщика данных о местоположении. В данном случае используется GPS. Определяется минимальный интервал обновления данных о местоположения в миллисекундах (Значение «0» соответствует использованию минимально возможного интервала времени для данного устройства). Определяется м инимальное расстояние для обновления данных о местоположении в метрах ( Значение «0» соответствует использованию минимально возможного расстояния для данного устройства). Полученные координаты за 5 метров или за 30 секунд усредняются и впоследствии будут добавлены на карту.

2. Симуляция компаса на экране:

 

Для определения направления компаса необходимо рассчитать азимут из полученных координат и получить угол направления движения. После этого загружаем картинку и поворачиваем ее ориентируясь на север.

        

3. Отображение данных на карте:

 

Полученные и обработанные координаты отмечаются на карте устройства. Так пользователь сможет определить свой путь, тем самым вернувшись в исходную точку не заблудившись.

 



Заключение

 

 

В ходе выполнения курсовой работы был получен опыт в обработке большого потока данных поступающих на устройство. Обработка GPS координат (вычисление средних значений, полученных за определенный интервал времени) и отображение их на Google карте. Также получен опыт в разработке программ под устройства Android с помощью языка программирования Kotlin.



Литература

 

 

1. STARTANDROID. [Электронный ресурс] URL: https://startandroid.ru/ru/uroki/vse-uroki-spiskom/132-urok-69-peredaem-parcelable-obekty-s-pomoschju-intent.

2. Хабр. Пишем на Kotlin под Android. [Электронный ресурс] URL: https://habr.com/ru/company/JetBrains/blog/231525/

3. Developers. Location. [Электронный ресурс] URL: https://developer.android.com/reference/kotlin/android/location/Location 4. Официальное руководство по Kotlin. [Электронный ресурс] URL: https://kotlinlang.org/.



Приложения

Приложение А – примеры программного кода

 

Класс MainActivity:

 

class MainActivity: AppCompatActivity(), LocationListener, SensorEventListener {

 

private val REQUEST_LOCATION = 2

private var sensorManager: SensorManager? = null

 

/***************/

 lateinit var mapFragment: SupportMapFragment

lateinit var googleMap: GoogleMap

/***************/

 

override fun onCreate(savedInstanceState: Bundle?) {

   super.onCreate(savedInstanceState)

   setContentView(R.layout.main_activity)

      setLocation()

   sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager

   startCompass()

}

 

private fun setLocation() {

if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)

!= PackageManager.PERMISSION_GRANTED

     && ActivityCompat.checkSelfPermission(this,

android.Manifest.permission.ACCESS_COARSE_LOCATION)

!= PackageManager.PERMISSION_GRANTED){

     ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION),

    REQUEST_LOCATION)

}else{

 

     var locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager

     val criteria = Criteria()

     val provider = locationManager.getProviders(criteria, false)

     val location = locationManager.getLastKnownLocation(provider[1])

 

 

     locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,1000,0f, this)

     if (location!= null) {

         text_view_location.text = convertLocationToString(location.latitude, location.longitude)

         /***************/

         mapFragment = supportFragmentManager.findFragmentById(R.id.mapView) as SupportMapFragment

         mapFragment.getMapAsync(OnMapReadyCallback {

             googleMap = it

 

             val location1 = LatLng(location.latitude, location.longitude)

             googleMap.addMarker(MarkerOptions().position(location1).title("Это Я."))

             googleMap!!.addPolyline(PolylineOptions().add(LatLng(location.latitude, location.longitude)).color(Color.RED))

             /*googleMap.addPolyline(PolylineOptions()

                .add(LatLng(location.latitude, location.longitude))

            .width(0f)

            .color(Color.RED))*/

             googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(location1, 10f))

         })

         /***************/

     }else{

           Toast.makeText(this,"Location not available!",Toast.LENGTH_SHORT).show()

     }

}

}

 

override fun onRequestPermissionsResult(

   requestCode: Int,

   permissions: Array<out String>,

   grantResults: IntArray

) {

      if(requestCode == REQUEST_LOCATION) setLocation()

}

 

private fun convertLocationToString(latitude: Double, longitude: Double): String {

 

   val builder = StringBuilder()

   if (latitude < 0) builder.append("S ") else builder.append("N ")

 

   val latitudeDegrees = Location.convert(Math.abs(latitude), Location.FORMAT_SECONDS)

   val latitudeSplit = latitudeDegrees.split((":").toRegex()).dropLastWhile({it.isEmpty()}).toTypedArray()

   builder.append(latitudeSplit[0])

    builder.append("*")

   builder.append(latitudeSplit[1])

   builder.append("'")

   builder.append(latitudeSplit[2])

   builder.append("\"")

   builder.append("\n")

 

   if (longitude < 0) builder.append("W ") else builder.append("E ")

   val longlatitudeDegrees = Location.convert(Math.abs(longitude),Location.FORMAT_SECONDS)

   val longitudeSplit = longlatitudeDegrees.split((":")).dropLastWhile({it.isEmpty()}).toTypedArray()

   builder.append(longitudeSplit[0])

   builder.append("*")

   builder.append(longitudeSplit[1])

   builder.append("'")

   builder.append(longitudeSplit[2])

   builder.append("\"")

   return builder.toString()

}

 

override fun onLocationChanged(location: Location?) {

   setLocation()

}

 

override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {

 

}

 

override fun onProviderEnabled(provider: String?) {

 

}

 

override fun onProviderDisabled(provider: String?) {

 

}

 

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {

 

}

 

private var rotationMatrix = FloatArray(9)

private var orientation = FloatArray(3)

private var azimuth:Int = 0

private var lastAccelerometer = FloatArray(3)

private var lastAccelerometerSet = false

private var lastMagnetometer = FloatArray(3)

private var lastMagnetometerSet = false

 

   override fun onSensorChanged(event: SensorEvent?) {

       if (event!!.sensor.type == Sensor.TYPE_ROTATION_VECTOR){

           SensorManager.getRotationMatrixFromVector(rotationMatrix, event!!.values)

           azimuth = (Math.toDegrees(SensorManager.getOrientation(rotationMatrix, orientation)[0].toDouble())+360).toInt()%360

       }

 

       if (event!!.sensor.type == Sensor.TYPE_ACCELEROMETER){

           System.arraycopy(event!!.values, 0, lastAccelerometer,0,event.values.size)

           lastAccelerometerSet = true

       }else if(event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD){

           System.arraycopy(event.values,0, lastMagnetometer,0,event.values.size)

           lastMagnetometerSet = true

       }

       if (lastAccelerometerSet && lastMagnetometerSet) {

           SensorManager.getRotationMatrix(rotationMatrix,null,lastAccelerometer, lastMagnetometer)

           SensorManager.getOrientation(rotationMatrix, orientation)

           azimuth = (Math.toDegrees(SensorManager.getOrientation(rotationMatrix,orientation)[0].toDouble())+360).toInt()%360

       }

       azimuth = Math.round(azimuth.toFloat())

       compass_image.rotation = (-azimuth).toFloat()

       val where = when(azimuth){

           in 281..349 -> "NW"

           in 261..280 -> "W"

            in 191..260 -> "SW"

           in 171..190 -> "S"

           in 101..170 -> "SE"

           in 81..100 -> "E"

           in 11..80 -> "NE"

           else -> "N"

       }

       text_view_degree.text = "$azimuth*$where"

}

 

private var accelerometer: Sensor? = null

private var magnetometer: Sensor? = null

private var haveSensorAccelerometer = false

private var haveSensorMagnetometer = false

private var rotationVector: Sensor? = null

private var haveSensorRotationVector = false

 

private fun startCompass(){

   if (sensorManager!!.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) == null) {

       if (sensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) == null ||

           sensorManager!!.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)==null){

           noSensorAlert()

       } else {

           accelerometer = sensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

           magnetometer = sensorManager!!.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)

 

           haveSensorAccelerometer = sensorManager!!.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI)

           haveSensorMagnetometer = sensorManager!!.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI)

       }

   }else {

       rotationVector = sensorManager!!.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)

       haveSensorRotationVector = sensorManager!!.registerListener(this, rotationVector, SensorManager.SENSOR_DELAY_UI)

   }

}

 

private fun stopCompass(){

   if (haveSensorRotationVector) sensorManager!!.unregisterListener(this, rotationVector)

   if (haveSensorAccelerometer) sensorManager!!.unregisterListener(this, accelerometer)

   if (haveSensorMagnetometer) sensorManager!!.unregisterListener(this, magnetometer)

}

 

private fun noSensorAlert() {

   val alertDialog = AlertDialog.Builder(this)

   alertDialog.setMessage("Not support a compass!").setCancelable(false).setNegativeButton("Close"){_,_->finish()}

   alertDialog.show()

}

 

override fun onResume() {

   super.onResume()

   startCompass()

}

override fun onPause() {

   super.onPause()

   stopCompass()

}

}


 

 

     

Приложение Б


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: