You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于Google Play Services的后台位置更新如何在设备重启后持续运行?

实现设备重启后持续后台位置更新的方案

没问题,完全可以让你的后台位置更新在设备重启后继续运行!核心思路是借助广播接收器监听系统的开机完成事件,然后在开机后重新启动你的位置服务。结合你的GPSTracker服务,下面给你一步步拆解具体实现方法:

1. 创建开机广播接收器

先写一个广播接收器,专门监听设备开机完成的事件,收到事件后就启动你的GPSTracker服务:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;

public class BootCompletedReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 判断是否是开机完成的广播
        if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
            Intent serviceIntent = new Intent(context, GPSTracker.class);
            // 适配Android 8.0+的后台服务限制,用startForegroundService
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(serviceIntent);
            } else {
                context.startService(serviceIntent);
            }
        }
    }
}

2. 添加必要权限到Manifest

AndroidManifest.xml里添加开机监听权限,还有位置相关的权限(别忘了后台位置权限,Android 10+必须要):

<!-- 监听开机完成的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- 位置基础权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Android 10+ 后台位置权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

3. 在Manifest中注册广播接收器和服务

把刚才的广播接收器注册到application标签下,同时更新你的GPSTracker服务配置(适配Android 12+的前台服务类型):

<application ...>
    <!-- 注册开机广播接收器 -->
    <receiver
        android:name=".BootCompletedReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <!-- 适配部分设备的快速重启事件 -->
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

    <!-- 配置你的位置服务 -->
    <service
        android:name=".GPSTracker"
        android:foregroundServiceType="location" /> <!-- Android 12+ 需要指定前台服务类型 -->
</application>

4. 优化你的GPSTracker服务

调整服务的逻辑,确保开机启动后能重新初始化位置更新,同时提高服务的存活概率:

(1)设置服务重启策略

onStartCommand方法里返回START_STICKY,这样如果服务被系统意外杀死,系统会尝试重启它:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // 初始化GoogleApiClient并恢复位置更新
    initGoogleApiClient();
    // 返回START_STICKY,让系统在服务被杀死后尝试重启
    return START_STICKY;
}

(2)初始化GoogleApiClient并请求位置更新

补全你的位置初始化逻辑(结合你已有的代码):

private GoogleApiClient mGoogleApiClient;

private void initGoogleApiClient() {
    if (mGoogleApiClient == null) {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        mGoogleApiClient.connect();
    }
}

// 在GoogleApiClient连接成功后请求位置更新
@Override
public void onConnected(Bundle bundle) {
    LocationRequest locationRequest = LocationRequest.create()
            .setInterval(300000) // 5分钟,单位毫秒
            .setFastestInterval(300000)
            .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

    // 先检查权限
    if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
    }
}

(3)适配Android 8.0+的前台服务限制

Android 8.0之后后台服务会被系统限制,所以你的GPSTracker需要启动为前台服务,显示一个低优先级通知:

@Override
public void onCreate() {
    super.onCreate();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // 创建通知渠道
        NotificationChannel channel = new NotificationChannel(
                "location_update_channel",
                "后台位置更新",
                NotificationManager.IMPORTANCE_LOW
        );
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);

        // 构建前台通知
        Notification notification = new NotificationCompat.Builder(this, "location_update_channel")
                .setContentTitle("位置更新中")
                .setContentText("后台持续获取位置信息")
                .setSmallIcon(R.drawable.ic_launcher_foreground) // 替换成你的应用图标
                .build();

        // 启动前台服务
        startForeground(1, notification);
    }
}

最后注意事项

  • 确保用户已经授予了所有必要的权限(包括位置权限和后台位置权限),否则开机后服务无法正常获取位置。
  • 如果应用被用户强制停止,开机广播可能无法被接收,这种情况需要用户手动打开应用一次。
  • 尽量使用低功耗的位置更新策略(比如PRIORITY_BALANCED_POWER_ACCURACY),避免过度消耗电量。

内容的提问来源于stack exchange,提问作者Nethra

火山引擎 最新活动