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;
                }
}
  ...

}
... ...
}
上一篇下一篇

猜你喜欢

热点阅读