天天看點

App切換到背景後如何保持持續定位?

為了保護使用者隐私,大多數應用隻會在前台運作時擷取使用者位置,當應用在背景運作時,定位功能會被禁止。這就導緻APP在背景或者鎖屏時無法正常記錄GPS軌迹,這對打車、共享出行、跑步等需要實時記錄使用者軌迹的應用影響非常大,甚至影響了應用核心功能的使用體驗。那對于這些應用的開發者來說,如何在使用者主動授權位置資訊後,讓應用在背景運作時長時間保持持續定位呢?

HMS Core​​定位服務​​提供背景持續定位的能力,在擷取使用者主動授權的情況下可持久記錄位置資訊,适用于記軌迹錄場景。

一、融合定位-背景定位實作方法

  1. 應用運作裝置為非華為手機
  2. 使用LocationCallback開啟定位之後,當應用切到背景之後,定位将會很快停止。
  3. 為了讓應用切到背景之後,定位能力依舊有效,是以可以使用enableBackgroundLocation方法建立一個前台服務,用以提高應用在背景的位置更新頻率。
  4. 背景定位本身不具備定位能力,背景定位需要和LocationCallback開啟的定位一起使用。定位擷取的資料需要在 LocationCallback對象中的onLocationResult(LocationResult locationResult) 方法中擷取。

二、注意事項:

  1. 支援的裝置為非華為手機
  2. 應用需要獲得定位權限,且必須為“始終允許”
  3. 應用不可被裝置中的省電精靈等控電應用當機,以vivo手機為例:打開i管家-背景耗電管理-找到應用-把智能控電改成允許背景高耗電。

三、測試Demo時的注意事項:

  1. 測試時裝置最好不要是充電狀态,充電狀态下應用可能不會被控電。
  2. 可以通過狀态欄是否有 定位圖表判斷 裝置目前是否在進行定位。以vivo手機為例:vivo手機定位開啟時狀态欄會展示一個定位圖示,如果不開啟背景定位的話應用切背景 定位圖示會消失。開啟背景定位能力之後,應用切背景定位圖示還是存在的。

四、實作背景定位功能內建步驟

  1. 在AndroidManifest.xml中添加背景定位服務
<service
    android:name="com.huawei.location.service.BackGroundService"
    android:foregroundServiceType="location" />      
  1. (可選)在Android 9及以上版本中,為保證背景定位權限的正常使用,需要在“AndroidManifest.xml”檔案中配置FOREGROUND_SERVICE權限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />      
  1. 建立Notification對象
public class NotificationUtil {
    public static final int NOTIFICATION_ID = 1;

    public static Notification getNotification(Context context) {
        Notification.Builder builder;
        Notification notification;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager =
                (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
            String channelId = context.getPackageName();
            NotificationChannel notificationChannel =
                new NotificationChannel(channelId, "LOCATION", NotificationManager.IMPORTANCE_LOW);
            notificationManager.createNotificationChannel(notificationChannel);
            builder = new Notification.Builder(context, channelId);
        } else {
            builder = new Notification.Builder(context);
        }
        builder.setSmallIcon(R.drawable.ic_launcher)
            .setContentTitle("Location SDK")
            .setContentText("Running in the background ")
            .setWhen(System.currentTimeMillis());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            notification = builder.build();
        } else {
            notification = builder.getNotification();
        }
        return notification;
    }
}      
  1. 初始化FusedLocationProviderClient對象
FusedLocationProviderClient mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);      
  1. 開啟背景定位
private void enableBackgroundLocation() {
    mFusedLocationProviderClient
            .enableBackgroundLocation(NotificationUtil.NOTIFICATION_ID, NotificationUtil.getNotification(this))
            .addOnSuccessListener(new OnSuccessListener<Void>() {
                @Override
                public void onSuccess(Void aVoid) {
                    LocationLog.i(TAG, "enableBackgroundLocation onSuccess");
                }
            })
            .addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(Exception e) {
                    LocationLog.e(TAG, "enableBackgroundLocation onFailure:" + e.getMessage());
                }
            });
}