因为项目之前对保活做了单独处理,故在极光推送的Receiver中添加一下Filter:
<!-- User defined. 用户自定义的广播接收器-->
<receiver
android:name=".receiver.PushReceiver"
android:enabled="true">
<intent-filter>
<!--Required 用户注册SDK的intent-->
<action android:name="cn.jpush.android.intent.REGISTRATION" />
<!--Required 用户接收SDK消息的intent-->
<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />
<!--Required 用户接收SDK通知栏信息的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />
<!--Required 用户打开自定义通知栏的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />
<!-- 接收网络变化 连接/断开 since 1.6.3 -->
<action android:name="cn.jpush.android.intent.CONNECTION" />
<action android:name="android.intent.action.BOOT_COMPLETED" /><!--开机广播-->
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" /><!--网络状态改变广播-->
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
PushReceiver:
public class PushReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, PushService.class);
context.startService(intent);
.........
}
代码之前一直正常,直到前几天在Bugly中看到一次Service启动崩溃:
百度查阅资料之后发现是Android 8.0系统对后台服务的限制导致异常情况出现,官网描述为:
后台服务限制
在后台中运行的服务会消耗设备资源,这可能降低用户体验。 为了缓解这一> 问题,系统对这些服务施加了一些限制。
系统可以区分 前台 和 后台 应用。 (用于服务限制目的的后台定义与内存管理使用的定义不同;一个应用按照内存管理的定义可能处于后台,但按照能够启动服务的定义又处于前台。)如果满足以下任意条件,应用将被视为处于前台:
具有可见 Activity(不管该 Activity 已启动还是已暂停)。
具有前台服务。
另一个前台应用已关联到该应用(不管是通过绑定到其中一个服务,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的服务,那么该应用处于前台:
- IME
- 壁纸服务
- 通知侦听器
- 语音或文本服务
如果以上条件均不满足,应用将被视为处于后台。
绑定服务不受影响
这些规则不会对绑定服务产生任何影响。 如果您的应用定义了绑定服务,则 不管应用是否处于前台,其他组件都可以绑定到该服务。
处于前台时,应用可以自由创建和运行前台服务与后台服务。 进入后台时,在一个持续数分钟的时间窗内,应用仍可以创建和使用服务。
在该时间窗结束后,应用将被视为处于 空闲 状态。 此时,系统将停止应用的后台服务,就像应用已经调用服务的“
[Service.stopSelf()](https://developer.android.com/reference/android/app/Service.html#stopSelf())
”方法。在这些情况下,后台应用将被置于一个临时白名单中并持续数分钟。 位于白名单中时,应用可以无限制地启动服务,并且其后台服务也可以运行。
处理对用户可见的任务时,应用将被置于白名单中,例如:
处理一条高优先级 Firebase 云消息传递 (FCM) 消息。
接收广播,例如短信/彩信消息。
从通知执行
[PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html)
。在很多情况下,您的应用都可以使用
[JobScheduler](https://developer.android.com/reference/android/app/job/JobScheduler.html)
作业替换后台服务。 例如,CoolPhotoApp 需要检查用户是否已经从朋友那里收到共享的照片,即使该应用未在前台运行。之前,应用使用一种会检查其云存储的后台服务。 为了迁移到 Android 8.0,开发者使用一个计划作业替换了这种后台服务,该作业将按一定周期启动,查询服务器,然后退出。
在 Android 8.0 之前,创建前台服务的方式通常是先创建一个后台服务,然后将该服务推到前台。
Android 8.0 有一项复杂功能;系统不允许后台应用创建后台服务。 因此,Android 8.0 引入了一种全新的方法,即
Context.startForegroundService()
,以在前台启动新服务。在系统创建服务后,应用有五秒的时间来调用该服务的
[startForeground()](https://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification))
方法以显示新服务的用户可见通知。如果应用在此时间限制内未调用
[startForeground()](https://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification))
,则系统将停止服务并声明此应用为 ANR。
(;´д`)ゞ,,,
8.0真的好严格。。。
极光代码没法改啊。。。
最后只能在Receiver中去掉手动启动Service的代码,。。使用极光原生的保活机制。。。
其实在大于6.0的系统上可以使用忽略电池优化来加强App推送保活率,具体代码实现为:
* 忽略电池优化
*/
public void ignoreBatteryOptimization(Activity activity) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
boolean hasIgnored = powerManager.isIgnoringBatteryOptimizations(activity.getPackageName());
// 判断当前APP是否有加入电池优化的白名单,如果没有,弹出加入电池优化的白名单的设置对话框。
if(!hasIgnored) {
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:"+activity.getPackageName()));
startActivity(intent);
}
}
记得在manifest文件中配置权限:
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>