在我们的应用中,我们以这种方式定义服务
<service
android:name="ServiceName"
android:exported="false" />
当调用活动的onCreate()
时,应用启动此服务。一切都很好,直到它被移动到背景很长一段时间。将应用程序移动到前台后,再次调用 onCreate(),并且应用程序尝试启动服务但收到错误:
引起:java.lang.SecurityException:不允许在未经uid 10156导出的情况下启动服务Intent {act = action_name cmp = app_bundle / service_name}
应用程序崩溃,重启后一切正常。我真的无法解决出错的问题。看起来 Activity 是以新的uid
启动的,但是尝试与另一个进程中的 Service 与另一个uid
(????)进行交互。
崩溃仅在华硕手机, Android 6.0.0上重现。
答案 0 :(得分:1)
看起来 Activity 以新的
uid
启动,但尝试与另一个进程中的 Service 进行交互uid
(??? ?)
我相信你已经回答了自己的问题。
一切都很好,直到它被移动到背景很长一段时间。
在“很长时间”期间,您的应用程序(分配了uid
10XXX)在第一个位置启动服务可能已被系统杀死。您的服务可能会从其onStartCommand()
返回 START_STICKY 或类似的标记,因此当应用程序进程被终止时,服务在新流程,由系统指定了另一个uid
。
然后,当您将应用程序带回前台时,它会在一个全新的过程中运行(意味着系统分配了另一个uid
)。在其中一个活动的onCreate()
中,您启动了具有android:exported="false"
的服务,并且此时它是从另一个{{1}内调用的抛出uid
(这样的行为可能只是你的华硕电话专用 - 我建议用其他供应商的手机查看行为)。
答案 1 :(得分:0)
如果服务已经在onCreate()中运行,您应该添加一项检查,这样您就不会为您的服务提供双重条目。我想这个异常是由它造成的。
检查的方法之一
I use the following from inside an activity:
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
我用它来称呼它:
isMyServiceRunning(MyService.class)