📢 除非有特殊需求,官方建議使用 Google Fused Location Provider API。

權限請求

AndroidManifest.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!--  宣告定位權限  -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application>
        <!-- 略 -->
    </application>

</manifest>

請求動態權限

因為定位屬於危險權限需要動態向使用者請求。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import android.Manifest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts

class MainActivity : AppCompatActivity() {

    // -----------------------Request Location Permission------------------------------
    private val resultLauncherPermission =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) {
            if (it) {
                initLocationManager()
            } else {
                Toast.makeText(this, "請允許權限以開啟定位", Toast.LENGTH_SHORT).show()
                finish()
            }
        }

    // -----------------------------LifeCycle Event-------------------------------------

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 啟動時請求權限
        resultLauncherPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION)
    }

    // --------------------------------------------------------------------------------

    private fun initLocationManager() {
        Toast.makeText(this, "定位權限請求成功,準備初始化 LocationManager", Toast.LENGTH_SHORT).show()
    }
}

LocationManager 實例化

1
2
3
import android.location.LocationManager

val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager

請求定位

Android S 以上支援 FUSED_PROVIDER,不過建議直接用 Android Fused Location Provider API,支援的系統版本比較廣。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@SuppressLint("MissingPermission")
private fun requestLocationUpdates() {
    val minTimeMs = 500L
    val minDistanceM = 0.0f
    val provider = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        LocationManager.FUSED_PROVIDER
    } else {
        LocationManager.GPS_PROVIDER
    }
    locationManager?.requestLocationUpdates(
        provider,
        minTimeMs,
        minDistanceM,
        locationListener
    )
}

輸出 LocationListener.onLocationChanged()

📢 注意 除了 LocationManager.GPS_PROVIDER 外,其餘在 Location.getTime() 拿到的都不是 GPS 時間

1
2
3
4
5
6
private val locationListener = object : LocationListener {
    override fun onLocationChanged(location: Location) {
        val output = "${location.provider}: ${location.longitude}, ${location.latitude}, ${location.altitude}"
        Log.d(TAG, "onLocationChanged: $output")
    }
}

停止定位更新

1
2
3
private fun stopLocationUpdates(){
    locationManager?.removeUpdates(locationListener)
}

參考資料