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

OPPO与MI手机中Android后台定位服务停止问题求助

解决ColorOS(OPPO)和MIUI(小米)后台定位服务自动停止的问题

我之前帮不少开发者排查过这类问题——ColorOS和MIUI的后台进程管控机制确实严格,尤其是当你finish主Activity后,系统会判定应用无前台交互,很容易把后台定位服务清理掉。下面是几个亲测有效的解决方案:

1. 申请后台定位权限(Android 10+)

从Android Q开始,后台定位需要单独的ACCESS_BACKGROUND_LOCATION权限,ColorOS和MIUI会根据这个权限的授予情况调整管控策略,一定要记得声明并动态申请,还要向用户说明权限用途。

在Manifest中添加权限:

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

代码中动态申请(Java示例):

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    ActivityCompat.requestPermissions(
        MainActivity.this,
        new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
        1001
    );
}

2. 将定位服务转为前台服务

前台服务绑定了持续通知,系统对这类服务的容忍度高很多,不会轻易终止。

步骤1:声明前台服务权限

在Manifest中添加:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <!-- Android 12+ 需添加 -->

步骤2:在Service中启动前台通知

在你的定位Service的onStartCommand方法中调用以下逻辑:

private void startForegroundNotify() {
    // 创建通知渠道(Android O+ 必需)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(
            "LOCATION_CHANNEL",
            "后台定位服务",
            NotificationManager.IMPORTANCE_LOW
        );
        NotificationManager manager = getSystemService(NotificationManager.class);
        manager.createNotificationChannel(channel);
    }

    // 构建通知
    Notification notification = new NotificationCompat.Builder(this, "LOCATION_CHANNEL")
        .setContentTitle("正在后台定位")
        .setContentText("为您提供持续定位服务")
        .setSmallIcon(R.drawable.ic_location)
        .setPriority(NotificationCompat.PRIORITY_LOW)
        .build();

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

注意:Android 12+必须使用FOREGROUND_SERVICE_LOCATION权限,且通知不能设置为隐藏,要让用户明确感知应用在后台运行。

3. 引导用户将应用加入后台白名单

这是最关键的一步——哪怕做了前面的操作,极端情况下系统还是可能杀进程,必须引导用户手动添加白名单。

你可以在应用内增加引导提示,告诉用户操作路径,同时提供一键跳转设置的功能:

Intent intent = new Intent();
String manufacturer = Build.MANUFACTURER.toLowerCase();
if (manufacturer.contains("xiaomi")) {
    // 跳转到MIUI应用省电设置
    intent.setAction("miui.intent.action.APP_PERM_EDITOR");
    intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity");
    intent.putExtra("extra_pkgname", getPackageName());
} else if (manufacturer.contains("oppo")) {
    // 跳转到ColorOS后台权限设置
    intent.setAction("com.coloros.safecenter.startupapp.activity.StartupAppListActivity");
    intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.activity.StartupAppListActivity");
}

// 检查Intent是否可跳转,否则跳转到通用应用设置页面
if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
    startActivity(intent);
} else {
    intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    Uri uri = Uri.fromParts("package", getPackageName(), null);
    intent.setData(uri);
    startActivity(intent);
}

对应的手动操作路径:

  • MIUI:设置 → 应用设置 → 应用管理 → 你的应用 → 省电策略 → 选择「无限制」
  • ColorOS:设置 → 电池 → 应用耗电管理 → 你的应用 → 开启「允许后台活动」

4. 用WorkManager实现周期性定位(可选)

如果你的定位需求是周期性而非实时持续,可以改用WorkManager——这是Google推荐的后台任务组件,能更好适配各定制系统的管控逻辑,确保任务在合适时机执行。

示例代码:

// 创建周期性任务请求,每15分钟执行一次
PeriodicWorkRequest locationWork = new PeriodicWorkRequest.Builder(
        LocationWorker.class,
        15, TimeUnit.MINUTES
    )
    .setConstraints(new Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED) // 可选:要求联网时执行
        .build())
    .build();

// 加入任务队列
WorkManager.getInstance(this).enqueue(locationWork);

然后在LocationWorkerdoWork方法中实现具体的定位逻辑即可。


最后提醒:ColorOS和MIUI的管控逻辑会随系统版本更新变化,建议多在不同版本的机型上测试;同时一定要向用户解释清楚权限和设置的必要性,避免用户产生反感。

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

火山引擎 最新活动