前言

最近Android设备中出现android.process.media的crash,异常日志如下:

--------- beginning of crash
AndroidRuntime: FATAL EXCEPTION: main
AndroidRuntime: Process: android.process.media, PID: 2999
AndroidRuntime: java.lang.RuntimeException: Unable to start receiver com.android.mtp.UsbIntentReceiver: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=com.android.mtp.UPDATE_NOTIFICATION cmp=com.android.mtp/.MtpDocumentsService }: app is in background uid UidRecord{54363a5 u0a19 RCVR bg:+3m12s621ms idle change:uncachedprocstateprocadj procs:0 seq(4819,3863)}
AndroidRuntime:     at android.app.ActivityThread.handleReceiver(ActivityThread.java:4443)
AndroidRuntime:     at android.app.ActivityThread.-$$Nest$mhandleReceiver(Unknown Source:0)
AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2239)
AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:106)
AndroidRuntime:     at android.os.Looper.loopOnce(Looper.java:201)
AndroidRuntime:     at android.os.Looper.loop(Looper.java:288)
AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:8061)
AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
AndroidRuntime:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:703)
AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
AndroidRuntime: Caused by: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=com.android.mtp.UPDATE_NOTIFICATION cmp=com.android.mtp/.MtpDocumentsService }: app is in background uid UidRecord{54363a5 u0a19 RCVR bg:+3m12s621ms idle change:uncachedprocstateprocadj procs:0 seq(4819,3863)}
AndroidRuntime:     at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1908)
AndroidRuntime:     at android.app.ContextImpl.startService(ContextImpl.java:1864)
AndroidRuntime:     at com.android.mtp.ServiceIntentSender.sendUpdateNotificationIntent(ServiceIntentSender.java:74)
AndroidRuntime:     at com.android.mtp.MtpDocumentsProvider.closeDevice(MtpDocumentsProvider.java:609)
AndroidRuntime:     at com.android.mtp.UsbIntentReceiver.onReceive(UsbIntentReceiver.java:38)
AndroidRuntime:     at android.app.ActivityThread.handleReceiver(ActivityThread.java:4433)

记录一下,方便自己查阅。

正文

下面分析一下

原因

Caused by: android.app.BackgroundServiceStartNotAllowedException: Not allowed to start service Intent { act=com.android.mtp.UPDATE_NOTIFICATION cmp=com.android.mtp/.MtpDocumentsService }: app is in background uid UidRecord{54363a5 u0a19 RCVR bg:+3m12s621ms idle change:uncachedprocstateprocadj procs:0 seq(4819,3863)}

大致原因:

应用没有在前台运行,并且没有正在运行的前台服务,尝试启动后台服务将触发此异常

ContextImpl.java
\frameworks\base\core\java\android\app\ContextImpl.java

中的startServiceCommon()

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
        UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess(this);
        ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                getOpPackageName(), getAttributionTag(), user.getIdentifier());
        Log.d(TAG, "startServiceCommon cn : "+ cn);
        if (cn != null) {
            if (cn.getPackageName().equals("!")) {
                throw new SecurityException(
                        "Not allowed to start service " + service
                        + " without permission " + cn.getClassName());
            } else if (cn.getPackageName().equals("!!")) {
                throw new SecurityException(
                        "Unable to start service " + service
                        + ": " + cn.getClassName());
            } else if (cn.getPackageName().equals("?")) {
                throw ServiceStartNotAllowedException.newInstance(requireForeground,
                        "Not allowed to start service " + service + ": " + cn.getClassName());
            }
        }
        // If we started a foreground service in the same package, remember the stack trace.
        if (cn != null && requireForeground) {
            if (cn.getPackageName().equals(getOpPackageName())) {
                Service.setStartForegroundServiceStackTrace(cn.getClassName(),
                        new StackTrace("Last startServiceCommon() call for this service was "
                                + "made here"));
            }
        }
        return cn;
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

定位

根据上面打印信息

at com.android.mtp.ServiceIntentSender.sendUpdateNotificationIntent(ServiceIntentSender.java:74)

确定出现问题的代码位置是在ServiceIntentSender.java中,而且这个类在Android源码的如下位置

\packages\services\Mtp

优化

--- a/packages/services/Mtp/src/com/android/mtp/ServiceIntentSender.java
+++ b/packages/services/Mtp/src/com/android/mtp/ServiceIntentSender.java
@@ -71,7 +71,7 @@ class ServiceIntentSender {
             intent.putExtra(MtpDocumentsService.EXTRA_DEVICE_NOTIFICATIONS, notifications);
             mContext.startForegroundService(intent);
         } else {
-            mContext.startService(intent);
+            mContext.startForegroundService(intent);
         }
     }
--- a/packages/services/Mtp/src/com/android/mtp/UsbIntentReceiver.java
+++ b/packages/services/Mtp/src/com/android/mtp/UsbIntentReceiver.java
@@ -36,7 +36,7 @@ public class UsbIntentReceiver extends BroadcastReceiver {
             case UsbManager.ACTION_USB_DEVICE_DETACHED:
                 try {
                     MtpDocumentsProvider.getInstance().closeDevice(device.getDeviceId());
-                } catch (IOException | InterruptedException e) {
+                } catch (Exception e) {
                     Log.e(MtpDocumentsProvider.TAG, "Failed to close device", e);
                 }
                 break;
 --- a/packages/services/Mtp/src/com/android/mtp/MtpDocumentsService.java
+++ b/packages/services/Mtp/src/com/android/mtp/MtpDocumentsService.java
@@ -51,20 +52,27 @@ public class MtpDocumentsService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // If intent is null, the service was restarted.
    if (intent == null || ACTION_UPDATE_NOTIFICATION.equals(intent.getAction())) {
        final int[] ids = intent.hasExtra(EXTRA_DEVICE_IDS) ?
                intent.getExtras().getIntArray(EXTRA_DEVICE_IDS) : null;
        final Notification[] notifications = intent.hasExtra(EXTRA_DEVICE_NOTIFICATIONS) ?
                castToNotifications(intent.getExtras().getParcelableArray(
                        EXTRA_DEVICE_NOTIFICATIONS)) : null;
        return updateForegroundState(ids, notifications) ? START_STICKY : START_NOT_STICKY;
-   }
+   }else{
+              startForeground(1, new Notification());
+        }
    return START_NOT_STICKY;
}

参考文章

相关文章

1 条评论

  • 城堡大人
    城堡大人 管理员

    有问题不要看

    广东深圳市
    回复