Not allowed to start service Int
2020-12-31 本文已影响0人
程序员Android1
一、Crash Log
FATAL EXCEPTION: Thread-13
Process: xxxx , PID: 12962
java.lang.IllegalStateException: Not allowed to start service Intent { flg=0x20 cmp=com.***/***android.service.DaemonService }: app is in background uid null
at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1701)
at android.app.ContextImpl.startService(ContextImpl.java:1657)
at android.content.ContextWrapper.startService(ContextWrapper.java:644)
at cn.jpush.android.service.l.run(Unknown Source:108)
at java.lang.Thread.run(Thread.java:784)
二、问题原因:
App targetSdkVersion>= 26的情况下,用户允许App开机自启动,App被杀死或者系统重启后,系统直接将App后台启动起来,App在后台启动的过程中有使用startService()方法。
Google在Android 8.0之后对于处于后台的App启动Service进行了严格的限制,不再允许后台App启动后台Service,如果使用会直接抛出异常。
三、 解决方案
1. app端
使用startForegroundService,此方法会在状态栏显示通知
// 启动服务的地方
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context, MyService.class));
} else {
context.startService(new Intent(context, MyService.class));
}
// 在MyService中
@Override
public void onCreate() {
super.onCreate();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = null;
channel = new NotificationChannel(CHANNEL_ID_STRING, getString(R.string.app_name), NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(channel);
Notification notification = new Notification.Builder(getApplicationContext(), CHANNEL_ID_STRING).build();
startForeground(1, notification);
}
}
2.源码白名单
可以在E:\AOSP\android_10_0_0_r40\frameworks\base\services\core\java\com\android\server\am\ActiveServices.java
中添加白名单。
public final class ActiveServices {
... ...
ComponentName startServiceLocked(...)
throws TransactionTooLargeException {
...
// If this isn't a direct-to-foreground start, check our ability to kick off an
// arbitrary service
if (forcedStandby || (!r.startRequested && !fgRequired)) {
// Before going further -- if this app is not allowed to start services in the
// background, then at this point we aren't going to let it period.
final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
//add Background start service white list
boolean isBackgroundStartServiceWhiteList="com.xxx.xxx".equals(callingPackage);
//add Background start service white list
if (allowed != ActivityManager.APP_START_MODE_NORMAL && !isBackgroundStartServiceWhiteList ) {
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.shortInstanceName
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage + " startFg?=" + fgRequired);
if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {
// In this case we are silently disabling the app, to disrupt as
// little as possible existing apps.
return null;
}
}
...
}
... ...
}