Google APK Crash 解决方案
阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android
本篇文章主要介绍开发中我们没有源码的GMS Crash
崩溃后的解决方案,通过阅读本篇文章,您将收获以下内容:
一、gms.ui Service not registered Crash
二、gms.ui BadTokenException Crash
三、setupwizard ConcurrentModificationException Crash
四、setupwizard ActivityNotFoundException Crash
五、setupwizard On-body ActivityNotFoundException
六、Google play Service NullPointerException Crash
七、恢复出厂设置或者第一次开机,先闪壁纸再显示开机向导
GMS(GoogleMobile Service)
包是出口国外手机中 Google
限制必须要预制的,如果不预置无法过Google CTS
认证,会导致手机无法正常使用,并且Google
会对手机厂商进行罚款。
只要是代码写出来的东西,都会有报错的概率存在,Google
大牛写的代码也不理我,那么,当我们遇到Google apk Crash
时候我们改如何处理呢?由于没有Google
源码,我们不能从根本上解决 Google apk Crash
的问题,只能在Android
原生的代码上规避 一下Google
代码低概率复现问题。
一、gms.ui Service not registered Crash
1.Crash Log如下:
--------- beginning of crash
01-01 00:00:16.892 2210 2473 E AndroidRuntime: FATAL EXCEPTION: IPreferenceServiceThread
01-01 00:00:16.892 2210 2473 E AndroidRuntime: Process: com.google.android.gms.ui, PID: 2210
01-01 00:00:16.892 2210 2473 E AndroidRuntime: java.lang.IllegalArgumentException: Service not registered: wfg@202e22a
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:1329)
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at android.app.ContextImpl.unbindService(ContextImpl.java:1495)
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at android.content.ContextWrapper.unbindService(ContextWrapper.java:648)
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at android.content.ContextWrapper.unbindService(ContextWrapper.java:648)
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at android.content.ContextWrapper.unbindService(ContextWrapper.java:648)
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at android.content.ContextWrapper.unbindService(ContextWrapper.java:648)
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at msl.a(:com.google.android.gms@11951440:39)
01-01 00:00:16.892 2210 2473 E AndroidRuntime: at wfh.run(:com.google.android.gms@11951440:5)
--------- beginning of system
2.Crash 原因:
当绑定服务已经解除绑定,再次解除绑定,会出现此异常。
当绑定服务已经解除绑定,再次解除绑定,会出现此异常
3.解决方案:
由于没有GMS
源码,我们不能从根源上处理问题,只能尝试修改Framework
代码规避此问题。
解决此问题需要修改一下两个类:
frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/content/ContextWrapper.java
1.修改1:
ContextWrapper.java
在ContextWrapper
的unbindService
方法中try-catch
住代码中抛出的异常IllegalArgumentException
,抓住异常,不让异常抛出。
修改方法如下:
public class ContextWrapper extends Context {
... ...
@Override
public void unbindService(ServiceConnection conn) {
try {
mBase.unbindService(conn);
} catch (IllegalArgumentException e) {
//com.google.android.gms.ui Service not registered Crash
android.util.Log.e("wjwj","---ContextWrapper GMS Crash---");
e.printStackTrace();
}
}
... ...
}
在ContextWrapper的 unbindService 方法中try-catch IllegalArgumentException
2.修改2:
ContextImpl.java
修改方法如下:
class ReceiverRestrictedContext extends ContextWrapper {
... ...
@Override
public void unbindService(ServiceConnection conn) {
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
getOuterContext(), conn);
try {
ActivityManager.getService().unbindService(sd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (IllegalArgumentException e) {
//com.google.android.gms.ui Service not registered Crash
android.util.Log.e("wjwj","---ContextImpl GMS Crash---");
e.printStackTrace();
}
} else {
throw new RuntimeException("Not supported in system context");
}
}
... ...
}
3.修改思路:
在ContextImpl
的unbindService
方法中try-catch
抓住代码中抛出的异常IllegalArgumentException
。
在ContextImpl的unbindService 方法中try-catch IllegalArgumentException
二、gms.ui BadTokenException Crash
1.Crash Log如下:
12-31 21:01:26.711 3776 3776 E AndroidRuntime: FATAL EXCEPTION: main
12-31 21:01:26.711 3776 3776 E AndroidRuntime: Process: com.google.android.gms.ui, PID: 3776
12-31 21:01:26.711 3776 3776 E AndroidRuntime: android.view.WindowManager$BadTokenException:
Unable to add window -- token android.os.BinderProxy@f176911 is not valid; is your activity running?
12-31 21:01:26.711 3776 3776 E AndroidRuntime: at android.view.ViewRootImpl.setView(ViewRootImpl.java:567)
12-31 21:01:26.711 3776 3776 E AndroidRuntime: at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:310)
12-31 21:01:26.711 3776 3776 E AndroidRuntime: at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
12-31 21:01:26.711 3776 3776 E AndroidRuntime: at android.app.Dialog.show(Dialog.java:319)
12-31 21:01:26.711 3776 3776 E AndroidRuntime: at com.google.android.location.network.ConfirmAlertChimeraActivity.a(:com.google.android.gms:164)
12-31 21:01:26.711 3776 3776 E AndroidRuntime: at rzo.onServiceConnected(:com.google.android.gms:71)
12-31 21:01:26.711 3776 3776 E AndroidRuntime: at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1223)
Unable to add window -- token android.os.BinderProxy@f176911 is not valid; is your activity running
2.解决方案如下
主要修改类:frameworks/base/core/java/android/view/ViewRootImpl.java
在 ViewRootImpl
类中,解决恢复出厂设置后的问题,修改方案如下:
public class ViewRootImpl extends AbsViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
... ...
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
... ...
if (res < WindowManagerGlobal.ADD_OKAY) {
mAttachInfo.mRootView = null;
mAdded = false;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
switch (res) {
case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
// add by wangjie for com.google.android.gms.ui crash
int deviceProvisioned = android.provider.Settings.Global.getInt(mContext.getContentResolver(), android.provider.Settings.Global.DEVICE_PROVISIONED,0);
if(deviceProvisioned==0){
android.util.Log.e("wjwj","---ViewRootImpl GMS Crash---");
return;
}else{
throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not valid; is your activity running?");
}
// add by wangjie for com.google.android.gms.ui crash
case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not for an application");
... ...
}
}
}
... ...
}
修改差异点如下
Unable to add window -- token android.os.BinderProxy@f176911 is not valid; is your activity running?
三、setupwizard ConcurrentModificationException Crash
1.Crash Log如下:
--------- beginning of crash
01-01 12:00:00.918 1583 1583 E AndroidRuntime: FATAL EXCEPTION: main
01-01 12:00:00.918 1583 1583 E AndroidRuntime: Process: com.google.android.setupwizard, PID: 1583
01-01 12:00:00.918 1583 1583 E AndroidRuntime: java.lang.RuntimeException: Error receiving broadcast Intent { act=android.intent.action.TIME_SET flg=0x25200010 } in com.google.android.setupwizard.time.DateTimeMonitor$1@7465601
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52497(LoadedApk.java:1323)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.app.-$Lambda$aS31cHIhRx41653CMnd4gZqshIQ.$m$7(Unknown Source:4)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.app.-$Lambda$aS31cHIhRx41653CMnd4gZqshIQ.run(Unknown Source:39)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:790)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.os.Looper.loop(Looper.java:164)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6523)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:857)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: Caused by: java.util.ConcurrentModificationException
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at java.util.ArrayList$Itr.next(ArrayList.java:860)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at com.google.android.setupwizard.time.DateTimeMonitor.updateStatus(DateTimeMonitor.java:134)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at com.google.android.setupwizard.time.DateTimeMonitor.-wrap0(Unknown Source:0)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at com.google.android.setupwizard.time.DateTimeMonitor$1.onReceive(DateTimeMonitor.java:73)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$-android_app_LoadedApk$ReceiverDispatcher$Args_52497(LoadedApk.java:1313)
01-01 12:00:00.918 1583 1583 E AndroidRuntime: ... 9 more
--------- beginning of system
ConcurrentModificationException
2.解决方案如下:
此问题关键在于解决ConcurrentModificationException
,但是没有GMS
源码,只能尝试规避方案。
修改类如下:/frameworks/base/core/java/android/app/LoadedApk.java
修改点如下:
public final class LoadedApk {
... ...
final class Args extends BroadcastReceiver.PendingResult {
public final Runnable getRunnable() {
... ...
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
sendFinished(mgr);
}
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//setupwizard TIME_SET RuntimeException Crash
if("android.intent.action.TIME_SET".equals(intent.getAction())){
if(mReceiver.toString().contains("com.google.android.setupwizard")){
android.util.Log.e("wjwj","---LoadedApk GMS setupwizard Crash---");
return;
}
}
//setupwizard TIME_SET RuntimeException Crash
throw new RuntimeException(
"Error receiving broadcast " + intent
+ " in " + mReceiver, e);
}
}
... ...
};
}
}
... ...
}
修改差异点如下:
throw new RuntimeException 异常没有被try-catch 导致crash
四、setupwizard ActivityNotFoundException Crash
1.Crash Log如下:
--------- beginning of crash
12-12 15:19:11.984 1471 1471 E AndroidRuntime: FATAL EXCEPTION: main
12-12 15:19:11.984 1471 1471 E AndroidRuntime: Process: com.google.android.setupwizard, PID: 1471
12-12 15:19:11.984 1471 1471 E AndroidRuntime: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.android.wizard.NEXT (has extras) }
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1843)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1557)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4228)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4187)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at com.google.android.setupwizard.BaseActivity.startActivityForResult(BaseActivity.java:665)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at com.google.android.setupwizard.BaseActivity.nextAction(BaseActivity.java:651)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at com.google.android.setupwizard.BaseActivity.nextAction(BaseActivity.java:637)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at com.google.android.setupwizard.user.SuggestedActionsActivity.onItemSelected(SuggestedActionsActivity.java:226)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at com.android.setupwizardlib.items.RecyclerItemAdapter$1.onClick(RecyclerItemAdapter.java:106)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at android.view.View.performClick(View.java:5624)
12-12 15:19:11.984 1471 1471 E AndroidRuntime: at android.view.View$PerformClick.run(View.java:22285)
com.google.android.setupwizard 报错log
2.解决方案如下:
在Instrumentation
类中对Google
开机向导进行特殊处理。
主要修改类如下:/frameworks/base/core/java/android/app/Instrumentation.java
主要修改方案如下:
public class Instrumentation {
... ...
/** @hide */
public static void checkStartActivityResult(int res, Object intent) {
if (!ActivityManager.isStartResultFatalError(res)) {
return;
}
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
+ "; have you declared this activity in your AndroidManifest.xml?");
//GMS Setupwizard ActivityNotFoundException Crash
if("com.android.wizard.NEXT".equals(((Intent)intent).getAction())){
android.util.Log.e("wjwj","Instrumentation GMS Setupwizard Crash ");
return;
}
//GMS Setupwizard ActivityNotFoundException Crash
throw new ActivityNotFoundException(
"No Activity found to handle " + intent);
case ActivityManager.START_PERMISSION_DENIED:
throw new SecurityException("Not allowed to start activity "
+ intent);
case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
throw new AndroidRuntimeException(
"FORWARD_RESULT_FLAG used while also requesting a result");
case ActivityManager.START_NOT_ACTIVITY:
throw new IllegalArgumentException(
"PendingIntent is not an activity");
... ...
}
}
... ...
}
主要修改差异点如下:
Instrumentation 类中对Google 开机向导进行特殊处理下
五、setupwizard On-body ActivityNotFoundException Crash
1.Crash Log如下:
--------- beginning of crash
12-31 19:00:26.668 2010 2010 E AndroidRuntime: FATAL EXCEPTION: main
12-31 19:00:26.668 2010 2010 E AndroidRuntime: Process: com.google.android.setupwizard, PID: 2010
12-31 19:00:26.668 2010 2010 E AndroidRuntime: android.content.ActivityNotFoundException: Unable to find explicit activity class {com.google.android.gms/com.google.android.gms.trustagent.discovery.OnbodyPromotionActivity}; have you declared this activity in your AndroidManifest.xml?
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1523)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4229)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:4188)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at com.google.android.setupwizard.BaseActivity.startActivityForResult(BaseActivity.java:665)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at com.google.android.setupwizard.BaseActivity.startFirstRunActivityForResult(BaseActivity.java:719)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at com.google.android.setupwizard.user.SuggestedActionsActivity.onItemSelected(SuggestedActionsActivity.java:217)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at com.android.setupwizardlib.items.RecyclerItemAdapter$1.onClick(RecyclerItemAdapter.java:106)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.view.View.performClick(View.java:5675)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.view.View$PerformClick.run(View.java:22641)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:836)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:103)
12-31 19:00:26.668 2010 2010 E AndroidRuntime: at android.os.Looper.loop(Looper.java:203)
Unable to find explicit activity class Log
2.解决方案如下:
com.google.android.setupwizard 解决方案
六、Google play Service NullPointerException Crash
1.Crash log
Google play Service
空指针的Log
由于目前没有找到,后续补上。
2.解决方案如下:
主要修改类:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
修改方法如下:
public class PackageManagerService extends PackageManagerServiceExAbs
implements PackageSender {
/**
* Important: The provided filterCallingUid is used exclusively to filter out activities
* that can be seen based on user state. It's typically the original caller uid prior
* to clearing. Because it can only be provided by trusted code, it's value can be
* trusted and will be used as-is; unlike userId which will be validated by this method.
*/
private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
int filterCallingUid, int userId) {
boolean isAppClone = false;
if (component != null && AppCloneUserInfo.containsCloneTag(component.getPackageName())) {
userId = AppCloneUserInfo.getUserIdFromCloneTag(component.getPackageName(), userId);
final String packageName = AppCloneUserInfo.removeCloneTag(component.getPackageName());
final String className = component.getClassName();
component = new ComponentName(packageName, className);
isAppClone = true;
}
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId, component);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get activity info");
synchronized (mPackages) {
PackageParser.Activity a = mActivities.mActivities.get(component);
if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
if (a != null) {
// SPRD: Add for AppClone (Components), generate activity info of owner.
int lastUserId = userId;
if(!mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
lastUserId = AppCloneUserInfo.adjustAppCloneUserId(
a.info.applicationInfo, userId);
}
if (mSettings.isEnabledAndMatchLPr(a.info, flags, lastUserId)) {
PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
if (ps == null) return null;
if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, lastUserId)) {
return null;
}
/* SPRD: modify to distinguish package of appclone @{ */
/*return PackageParser.generateActivityInfo(a, flags, ps.readUserState(userId),
userId);*/
ActivityInfo info = PackageParser.generateActivityInfo(a, flags, ps.readUserState(lastUserId),
lastUserId);
if (info != null && isAppClone) {
info.packageName = AppCloneUserInfo.addCloneTag(info.packageName, lastUserId);
}
return info;
/* @} */
}
}
// GMS Google play Service NullPointerException Crash
if (null != mResolveComponentName && mResolveComponentName.equals(component)) {
android.util.Log.e("wjwj","PackageManageServices GMS Google play Service NullPointerException Crash ");
// GMS Google play Service NullPointerException Crash
/* SPRD: modify to distinguish package of appclone @{ */
/*return PackageParser.generateActivityInfo(
mResolveActivity, flags, new PackageUserState(), userId);*/
ActivityInfo info = PackageParser.generateActivityInfo(
mResolveActivity, flags, new PackageUserState(), userId);
if (info != null && isAppClone) {
info.packageName = AppCloneUserInfo.addCloneTag(info.packageName, userId);
}
return info;
/* @} */
}
}
return null;
}
}
Google play Service NullPointerException Crash主要修改点如下:
Google play Service NullPointerException Crash主要修改点
七、恢复出厂设置或者第一次开机,先闪壁纸再显示开机向导
1.解决方案如下:
主要修改KeyguardServiceDelegate
这个类。frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
1.修改点1:
在此类中添加判断方法,获取手机DEVICE_PROVISIONED
状态信息。
在此类中添加判断方法
2.修改点2:
此类的构造方法中,如果获取到的为true,先隐藏
此类的构造方法中,如果获取到的为true,先隐藏
3.修改点3:
在onScreenTurningOn
中判断显示
onScreenTurningOn 中判断显示
系统原生显示与隐藏方法
友情推荐
至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!
分享到朋友圈吧,方便您使用时快速查找!