Get your current location / 取得GPS位置

取得GPS位置

因為要取得目前位置是  Google Play services APIs ,為了使用它,
需要先準備好使用環境。
1. 先打開 Gradle 的 build.gradle (Module: app) ,添加他的相依函式庫 :

dependencies {
 implementation "com.google.android.gms:play-services-location:$googlePlayServiceVersion"
 ...
}
$googlePlayServiceVersion 可以選擇正在使用的 或 最新的版號


2. 因此需要確認使用者是有提供 Google Play Service 的

GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this)


3. 接著需要向使用者要求權限

在 AndroidManifest.xml 加上要求位址的權限,這邊 google 提供兩種權限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
這個權限是要求大約的位置,大約程度以城市區塊來計算。取得方式是由網路或 wi-fi 的基地台為基準。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
這個權限是要求精準的位置,可以真的定位到現在的位置。取得方式可以是由網路或 wi-fi 的基地台為基準,這樣也會取得粗略的位置,也可以用GPS,就是定位的位置,接著我們會選用這個方向。


4. 然後要在需要用到經緯度的功能,都需要先檢查是否有權限:

Android sdk 23 (M 棉花糖) 以後變成要求使用者權限,不再能在安裝 APK 時,就直接取得,所以這邊會先檢查使用者的運行版本。

Build.VERSION.SDK_INT < Build.VERSION_CODES.M

接著在 Activity 內呼叫該函式,來檢查該有的權限是否已授權:

checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)  == 
PackageManager.PERMISSION_GRANTED

5. 重新要權限

在版本 ≥ M 的情況下我們需要先呼叫

shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)

特別注意:關於這個權限要求,會需要裝置端允許定位為精確度模式。
這邊需要小心的是使用者可能會因為系統的這個詢問選擇不同意而把模式改動鎖死。


鎖死的狀態我還不太清楚為什麼會發生,但是會造成設定怎麼調整都還是拿不到定位
這時候只能重新開機,藉由狀態重置才有辦法恢復為可以用高定位精確度的狀態。
(鎖死狀態下 GoogleMap 也是會發生藍點定位失效!)

6. 拿到設定裡的定位模式:

/**
     * Location mode:
     * High Accuracy: Wi-Fi/Network + GPS
     * Device only: GPS
     * Save Battery: Wi-Fi/Network
     * @param context
     */
    private void checkLocationMode(Context context) {
        LocationManager manager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        boolean isGpsEnabled = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean isNetworkEnabled = manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

7. 在授權視窗後,onRequestPermissionsResult 可以收到來自使用者的選項回應。

@CallSuper
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == REQUEST_LOCATION_PERMISSIONS) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getLocation()
            } else
                getLocationActionFail()
        }
    }

8. 正式用 LocationService 取得定位

/**
     * Get Location with new api client. {@link FusedLocationProviderClient}<br>
     * @param activity
     * @param getLocationCallback
     */
    @SuppressWarnings("MissingPermission")
    public void getLastLocation(Activity activity, final GetLocationCallback getLocationCallback) {
        LocationServices.getFusedLocationProviderClient(activity).getLastLocation()
                .addOnCompleteListener(activity, new OnCompleteListener<Location>() {
                    @Override
                    public void onComplete(@NonNull Task<Location> task) {
                        if (task.isSuccessful()) {
                            if(task.getResult() != null) {
                                latestLocation = task.getResult();
                                getLocationCallback.onGetLocation(
                                        latestLocation.getLatitude(),
                                        latestLocation.getLongitude());
                            } else {
                                //show gps mode is not high accuracy in version higher than android M
                                getLocationCallback.onGetLocationNull();
                            }
                        } else {
                            if(latestLocation != null)
                                getLocationCallback.onLocationIsNotChanged(
                                        latestLocation.getLatitude(),
                                        latestLocation.getLongitude());
                        }
                    }
                });
    }

9. 接上自定義的 GetLocationCallback 就可以取的最後的經緯度了。
各位可以在使用上調整成自己需要的回調,像是失敗回調的部分。

10. 如果是需要持續更新位置的功能(比較強調機動性的功能)可以參考使用 FusedLocationProviderClient.requestLocationUpdates
需要注意的部分就是在不使用時要記得釋放掉 Callback!

@Override
    public void release() {
        /* remove location update */
        if(mFusedLocationClient != null)
            mFusedLocationClient.removeLocationUpdates(locationCallback);
    }


留言

熱門文章