Unable to launch com.* for service Intent { cmp=com.*/.* }: process is bad



Unable to launch com.* for service Intent { cmp=com.*/.* }: process is bad

最近的项目需要用到服务端收集客户端崩溃的详细异常log数据:

之前也做过,感觉很轻松,没想到遇到问题了,还纠结了半天:
以下是关键log日志
Java代码 收藏代码
<span style=”color: #ff0000; font-family: ‘Microsoft YaHei’, 微软雅黑, SimHei, tahoma, arial, helvetica, sans-serif;”>05-04 20:28:42.409: W/ActivityManager(374): Process com.example.service has crashed too many times: killing!
05-04 20:28:42.409: I/ActivityManager(374): Killing proc 20556:com.example.service/u0a10080: crash
05-04 20:28:43.323: W/ActivityManager(374): Unable to launch app com.example.service/10080 for service Intent { cmp=com.example.service/.service.TestService }: process is bad
</span>

问题介绍:
a、带界面的应用,当应用拥有当前界面时发生RuntimeException,可以被alarm和BroadcastReceiver唤醒;
b、统计器后台运行:产生RuntimeException之后再也起不来了(不可以被alarm和BroadcastReceiver再次唤醒);

问题查找过程:
推荐一个在线查看源码的网站,很方便

http://grepcode.com/project/repository.grepcode.com/java/ext/com.google.android/android/

1、 关键词搜索:process is bad
2、发现出处
Java代码 收藏代码
<span style=”font-family: ‘Microsoft YaHei’, 微软雅黑, SimHei, tahoma, arial, helvetica, sans-serif;”> class: com.android.server.am.ActivityManagerService
method: private final ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, boolean stable, int userId);</span>
具体位置:

Java代码 收藏代码
<span style=”font-family: ‘Microsoft YaHei’, 微软雅黑, SimHei, tahoma, arial, helvetica, sans-serif;”>ProcessRecord proc = startProcessLocked(cpi.processName,
cpr.appInfo, false, 0, “content provider”,
new ComponentName(cpi.applicationInfo.packageName,
cpi.name), false, false);
if (proc == null) {
Slog.w(TAG, “Unable to launch app ”
+ cpi.applicationInfo.packageName + “/”
+ cpi.applicationInfo.uid + ” for provider ”
+ name + “: process is bad”);
return null;
}</span>


3、继续跟踪 com.android.server.am.ActivityManagerService 的 startProcessLocked ,原因就在里头;

原因:
参考:

Java代码 收藏代码
<span style=”font-family: ‘Microsoft YaHei’, 微软雅黑, SimHei, tahoma, arial, helvetica, sans-serif;”> class : com.android.server.am.ActivityManagerService
method: final ProcessRecordstartProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated) {}</span>

程序发生RuntimeException,被crash掉,如果被重新起来,这个时候判断是否是后台应用,如果是后台应用则silently fail.

关键代码:红色标记注释

Java代码 收藏代码
<span style=”font-family: ‘Microsoft YaHei’, 微软雅黑, SimHei, tahoma, arial, helvetica, sans-serif;”> if (!isolated) {
if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {
<span style=”color: #ff0000;”> // If we are in the background, then check to see if this process
// is bad. If so, we will just silently fail.</span>
if (mBadProcesses.get(info.processName, info.uid) != null) {
if (DEBUG_PROCESSES) Slog.v(TAG, “Bad process: ” + info.uid
+ “/” + info.processName);
return null;
}
} else {
<span style=”color: #ff0000;”>// When the user is explicitly starting a process, then clear its
// crash count so that we won’t make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.</span>
if (DEBUG_PROCESSES) Slog.v(TAG, “Clearing bad process: ” + info.uid
+ “/” + info.processName);
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mBadProcesses.remove(info.processName, info.uid);
if (app != null) {
app.bad = false;
}
}
}</span>