前回の記事では国土地理院地図を表示しましたが、最初に表示される地図のセンター位置は固定(東京タワー)としていました。
今回は地図の中心をGPSで測位した位置にするよう改修を加えます。
FusedLocationProviderClientを利用した現在位置の取得
FusedLocationProviderClientでGPS測位位置を取得します。GPS測位位置の取得にあたりユーザからロケーション利用のパーミッションを得る必要があります。
build.gradle
dependencies { implementation 'com.google.android.gms:play-services-location:17.0.0' //追加 }
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> //追加
MainActivity.kt
GPS測位のたびに中心を変えていっても構わないのですが、地図で移動先を確認している際に中心が動いてしまうとわずらわしいので、位置取得初回のみセンターを設定するようにします。
今後の応用を考えてGPS測位位置は常時取得し、チェックフラグでセンターを設定するかどうかを決めています。初回に1回だけ取得するならば、lastLocation
の取得ではなくrequestLocationUpdates
を実装したほうが無難です。
import android.Manifest import android.content.pm.PackageManager import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.preference.PreferenceManager import androidx.appcompat.app.AlertDialog import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback import com.google.android.gms.location.LocationRequest import com.google.android.gms.location.LocationResult import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.XYTileSource import org.osmdroid.util.GeoPoint import org.osmdroid.views.MapView import org.osmdroid.views.overlay.ScaleBarOverlay class MainActivity : AppCompatActivity() { private val PERMISSION_REQUEST_CODE = 1000 private var centerTrigger = true private lateinit var mapView: MapView private lateinit var fusedLocationClient : FusedLocationProviderClient private lateinit var locationCallback: LocationCallback override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Configuration.getInstance().load(applicationContext, PreferenceManager.getDefaultSharedPreferences(applicationContext)) fusedLocationClient = FusedLocationProviderClient(this) setContentView(R.layout.activity_main) mapView = findViewById(R.id.mapview) val tileSource = XYTileSource("GSI", 5, 18, 256, ".png", arrayOf("https://cyberjapandata.gsi.go.jp/xyz/std/")) mapView.setTileSource(tileSource) mapView.setMultiTouchControls(true) // パーミッションチェック if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // パーミッション未許可 if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { AlertDialog.Builder(this) .setMessage("need location permission") .setPositiveButton("OK", ({_, _ -> ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_CODE) })).show() } else { ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_CODE) } } else { // パーミッション許可済 trackLocation() } } // パーミッション可否に対するアクション override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { when(requestCode) { PERMISSION_REQUEST_CODE -> { if((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) { trackLocation() } else { finish() } } else -> { super.onRequestPermissionsResult(requestCode, permissions, grantResults) } } } // GPS位置測位結果の取得 private fun trackLocation() { val locationRequest = LocationRequest().apply { interval = 10000 fastestInterval = 5000 priority = LocationRequest.PRIORITY_HIGH_ACCURACY } locationCallback = object:LocationCallback() { override fun onLocationResult(locationResult: LocationResult?) { super.onLocationResult(locationResult) val location = locationResult?.lastLocation if(location != null && centerTrigger) { showMapCenter(location.latitude, location.longitude) centerTrigger = false } } } fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, mainLooper) } // 地図センター設定 private fun showMapCenter(latitude: Double, longitude: Double) { val mapController = mapView.controller mapController.setZoom(15.0) mapController.setCenter(GeoPoint(latitude, longitude)) } override fun onPause() { super.onPause() mapView.onPause() } override fun onResume() { super.onResume() mapView.onResume() } override fun onStop() { super.onStop() fusedLocationClient.removeLocationUpdates(locationCallback) } }