前言
最近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; }
参考文章
© 版权声明
有问题不要看