LoginSignup
3
5

More than 3 years have passed since last update.

【Kotlin】GPSで位置情報GNSSで衛星情報を取得

Posted at

はじめに

GPSで緯度と経度をGNSSで受信した衛星の情報を取得します。
API Level 24 (Android 7.0)以降が対象です。

準備

build.gradle(app)に下記の1行を追加します。

build.gradle
implementation 'com.google.android.gms:play-services-location:15.0.1'

マニフェストファイルには以下のパーミッションを追加します。

Manifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

ユーザーに許可をもらう

GPSやGNSSの情報を取得するにはユーザーに取得する旨を通知して許可をもらう必要があります。
ユーザーへの許可は

permissions.kt
val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
ActivityCompat.requestPermissions(this,permissions,1000)

という処理を行うと許可をもらう画面になります。
ただしこのとき、処理が止まっているわけではありません。
許可された場合(されない場合も)はMainActivityのoverride fun onRequestPermissionsResultリスナーに処理が渡されるので、これを元に適切に処理します。
なお1000という数値はonRequestPermissionsResult内で他の処理と区別するために使います。

MainActivity.kt
    override fun onRequestPermissionsResult(requestCode : Int,permissions : Array<String>,grantResults: IntArray){
        if (requestCode == 1000 && grantResults[0] == PackageManager.PERMISSION_GRANTED){

        }
    }

さっきの1000がここで出てきます。
PERMISSION_GRANTEDは許可が取れたことを示しています。

ソースの説明

MainActivityのソースは極力減らしています。
LocationManagerが相当古いSDKなのかLocationManager::class.kotlinJvmJavaという見たことも無い変換で渡すことになりました。

位置情報が得られた場合はonLocationリスナーが、衛星情報が得られた場合はonSatellitリスナーが処理されます。
onLocationはlocationResult.lastLocation.latitudeに経度、locationResult.lastLocation.longitudeに緯度が入っています。

onSatellitはstatus.satelliteCountに得られた衛星の数が入ります。
status,get_xxxのメソッドの引数は衛星のインデックス 0..status.satelliteCount-1 までの数値を渡して情報を取得します。

メソッド名 意味
getSvid(idx) 衛星の識別番号を取得します。ただしこちらは使われていない様子です。
getConstellationType(idx) こちらが使われている方の識別番号 GPSの場合は1..32の値になります
getAzimuthDegrees(idx) 衛星の方位(角度)が0.0..359.9の値で取得出来ます
getElevationDegrees(idx) 衛星の高さを取得出来ます。単位は・・・何でしょ?
getCn0DbHz(idx) 衛星からの電波の強さを取得します。強さはC/N0比で単位はdBHz です
usedInFix 位置情報の取得に使われている衛星の場合trueが返されます
getCarrierFrequencyHz(idx) おそらく使われていません

ソース

gps.kt
class MainActivity : AppCompatActivity() {
    private val gpsService = GpsService(this,this)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        gpsService.setListener(gpsListener)
        gpsService.permissioRequestCode = 1000
        gpsService.start()

    }

    private val gpsListener = object : GpsServiceInterface{
        override fun onLocation(locationResult: LocationResult) {
            Toast.makeText(this@MainActivity,
                    "緯度:${locationResult.lastLocation.latitude}, 経度:${locationResult.lastLocation.longitude}", Toast.LENGTH_LONG).show()
        }

        override fun onSatellit(status: GnssStatus) {
            for (i in 0..status.satelliteCount-1){
                Log.d("Sample", status.getSvid(i).toString())
            }
        }
    }

    override fun onRequestPermissionsResult(requestCode : Int,permissions : Array<String>,grantResults: IntArray){
        if (requestCode == gpsService.permissioRequestCode && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            if (gpsService.isGPSPermission()){
                gpsService.start()
            }
        }
    }
}
interface GpsServiceInterface : GpsService.Listener {
    fun onLocation(locationResult: LocationResult)       // 受信イベント
    fun onSatellit(status: GnssStatus)
}

class GpsService(private var context: Context,private var activity: MainActivity) {
    private var _latitude = 0.0
    private var _longitude = 0.0
    private lateinit var fusedLocation : FusedLocationProviderClient
    private lateinit var locationManager: LocationManager

    var permissioRequestCode : Int = 1000
    private lateinit var locationCallback: LocationCallback
    private lateinit var gnssCallback : GnssStatus.Callback

    private var listener: GpsServiceInterface? = null
    interface Listener {}

    private var enable : Boolean = false

    fun setListener(listener: GpsService.Listener?) {
        if (listener is GpsServiceInterface) {
            this.listener = listener as GpsServiceInterface
        }
    }
    fun start(){
        if (enable) return
        if (isGPSPermission() == false){
            val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
            ActivityCompat.requestPermissions(activity,permissions,permissioRequestCode)
            return
        }
        locationManager = getSystemService<LocationManager>(context, LocationManager::class.kotlinJvmJava) as LocationManager
        fusedLocation = FusedLocationProviderClient(context)
        val locationRequest = LocationRequest().apply {
            interval = 10000
            fastestInterval = 5000
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
        locationCallback = object : LocationCallback() {
            override fun onLocationResult(locationResult: LocationResult?) {
                if (locationResult == null) return
                listener?.onLocation(locationResult)
            }
        }
        gnssCallback = object: GnssStatus.Callback() {
            override fun onSatelliteStatusChanged(status: GnssStatus?) {
                super.onSatelliteStatusChanged(status)
                if (status == null) return
                listener?.onSatellit(status)
            }
        }
        if (ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            fusedLocation.requestLocationUpdates(locationRequest,locationCallback,Looper.myLooper())
            locationManager.registerGnssStatusCallback(gnssCallback)
        }
        enable = true
    }
    fun stop(){
        if (!enable) return
        fusedLocation.removeLocationUpdates(locationCallback)
        locationManager.unregisterGnssStatusCallback(gnssCallback)
        enable = false
    }

    fun isGps() : Boolean{
        return isGPSPermission() and isGPSEnabled()
    }
    fun isGPSPermission() : Boolean{
        return  ActivityCompat.checkSelfPermission(context,Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
    }

    fun isGPSEnabled(): Boolean {
        val locationManager =
            context.getSystemService(LOCATION_SERVICE) as LocationManager
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
    }
}
3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5