如何绕过 Android 8.0 startService 限制

     

应用在后台运行时,会消耗一部分有限的设备资源,例如 RAM。这可能会影响用户体验,如果用户正在使用占用大量资源的应用(例如玩游戏或观看视频),影响会尤为明显。为了提升用户体验,Android 8.0(API 级别 26)对应用在后台运行时可以执行的操作施加了限制。

限制了什么?

1. 后台应用对后台服务的访问受到限制

在不与用户直接交互的后台应用中,运行 Service 会消耗系统资源,这可能会影响前台应用的正常运行。Android 8.0 及更高版本「不允许后台应用运行后台服务」,需要通过 startForegroundService() 指定为前台服务运行,或者使用 JobScheduler 替代。

2. 注册隐式广播接收器受到限制

对于一些系统隐式广播(非全部),系统不允许应用在 AndroidManifest 中注册对应的广播接收器,从而避免系统广播导致诸多应用快速、连续消耗系统资源,从而影响用户体验,需要通过 Context.registerReceiver() 动态注册或 JobScheduler 代替。

3. 降低了后台应用接收位置更新的频率

为节约电池电量、保持良好的用户体验和确保系统健康运行,在运行 Android 8.0 的设备上使用后台应用时,降低了后台应用接收位置更新的频率。

什么是前台应用?

系统可以区分前台和后台应用。如果满足以下任意条件,应用将被视为处于前台:

  1. 具有可见 Activity

  2. 具有前台 Service

  3. 另一个前台应用已关联到该应用(绑定 Service 或使用 content providers)

如果以上条件均不满足,应用将被视为处于后台。

正确理解后台服务限制

「不允许后台应用运行后台服务」

官网的这句描述很简单,但你真的明白它的含义吗?顺着这句话推导一下:

后台应用无法启动后台服务

-> 前台应用可以启动后台服务

-> A 为前台应用,则 A 就能启动后台服务

基于这个结论,再结合后台服务的种类,对以下三种场景实践验证,结果如下:

  1. 若后台服务属于 A 应用进程,则能正常启动

  2. 若后台服务属于 B 应用进程,且 B 是前台应用,则能正常启动

  3. 若后台服务属于 B 应用进程,且 B 是后台应用,则无法启动!

通过第三种场景的验证结果,可以知道 不允许后台应用运行后台服务 这个描述是不准确、有歧义的,更精准的描述应该是:

「不允许启动属于后台应用的后台服务」

后台服务限制源码分析

若在 Android 8.0 设备上通过 startService 启动一个属于后台应用的后台服务,会直接崩溃:

Caused by: java.lang
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 8.0 及以上版本,为了增强应用程序的安全性,Android 引入了后台限制,禁止未在前台运行的应用程序启动服务。如果您想在后台启动服务,需要使用 `startForegroundService()` 方法。这个方法会启动一个前台服务,然后你可以在服务启动后在通知栏显示一个通知,以此来告知用户服务正在运行。 以下是一个使用 `startForegroundService()` 的示例代码: ``` if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 创建一个 NotificationChannel NotificationChannel channel = new NotificationChannel("channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT); // 向系统注册 NotificationChannel NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } // 创建一个 Intent,启动你的服务 Intent serviceIntent = new Intent(this, YourService.class); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 在 Android 8.0 及以上版本上,需要调用 startForegroundService() 方法启动服务。 startForegroundService(serviceIntent); } else { // 在 Android 8.0 以下版本上,可以直接调用 startService() 方法启动服务。 startService(serviceIntent); } ``` 注意:如果你使用的是 `startForeground()` 方法,会在 Android 8.0 及以上版本上抛出 `IllegalStateException` 异常,因为 Android 8.0 及以上版本禁止在后台启动服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值