Android 定位結果的 `Location.getTime()` 不一定是衛星時間

Photo by SpaceX on Unsplash 前言 最近的專案需要取定位的時間,並用該時間判斷使用者是否有在指定時間完成任務,而業主就提出希望以定位所取得的時間做為判斷依據。 然後,就發現事情沒有想像中的那麼單純。 原來目前在 Android 的定位結果中所取得的時間,只有在定位來源為純 GPS 的情況下才會是衛星所回傳的時間。 來看看究竟是怎麼一回事吧… 先認識 Location 型別 不論是使用 Android 官方推薦的 Fused Location Provider 或是 LocationManager ,定位結果所回傳的型別都是 Location。這個型別除了基本的經緯度與海拔等資訊,其中也包含定位的時間。 通常開發上指的定位時間,我們會使用 Location.getTime() 取得 Unix epoch time,再將這串數字轉成人類可閱讀的時間格式。 Unix epoch time:從 UTC 1970 年 1 月 1 日 0 時 0 分 0 秒起至現在的總秒數,不考慮閏秒。 – Wikipedia Location.getTime() 會跟定位來源有關 從 Android Doc: Location.getTime() 的說明會發現,不同的定位結果所取得的時間來源不見得相同。 ...

May 27, 2023 · 2 min · 257 words · Daniel Huang

Android 取得即時定位 LocationManager

📢 除非有特殊需求,官方建議使用 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,支援的系統版本比較廣。 ...

May 24, 2023 · 2 min · 271 words · Daniel Huang