在实际的开发中,遇到一种崩溃,log 如下
04-20 13:50:54.624 E/MtaSDK (30339): java.lang.RuntimeException: Unable to resume activity {ctrip.android.view/ctrip.android.hotel.view.UI.video.HotelVideoActivity}: java.lang.IllegalArgumentException 04-20 13:50:54.624 E/MtaSDK (30339): at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3603) 04-20 13:50:54.624 E/MtaSDK (30339): at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3643) 04-20 13:50:54.624 E/MtaSDK (30339): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1634) 04-20 13:50:54.624 E/MtaSDK (30339): at android.os.Handler.dispatchMessage(Handler.java:102) 04-20 13:50:54.624 E/MtaSDK (30339): at android.os.Looper.loop(Looper.java:154) 04-20 13:50:54.624 E/MtaSDK (30339): at android.app.ActivityThread.main(ActivityThread.java:6321) 04-20 13:50:54.624 E/MtaSDK (30339): at java.lang.reflect.Method.invoke(Native Method) 04-20 13:50:54.624 E/MtaSDK (30339): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:939) 04-20 13:50:54.624 E/MtaSDK (30339): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:829) 04-20 13:50:54.624 E/MtaSDK (30339): Caused by: java.lang.IllegalArgumentException 04-20 13:50:54.624 E/MtaSDK (30339): at android.os.Parcel.readException(Parcel.java:1688) 04-20 13:50:54.624 E/MtaSDK (30339): at android.os.Parcel.readException(Parcel.java:1637) 04-20 13:50:54.624 E/MtaSDK (30339): at android.app.ActivityManagerProxy.isTopOfTask(ActivityManagerNative.java:5677) 04-20 13:50:54.624 E/MtaSDK (30339): at android.app.Activity.isTopOfTask(Activity.java:6106) 04-20 13:50:54.624 E/MtaSDK (30339): at android.app.Activity.onResume(Activity.java:1284) 04-20 13:50:54.624 E/MtaSDK (30339): at android.support.v4.app.FragmentActivity.onResume(SourceFile:485) 04-20 13:50:54.624 E/MtaSDK (30339): at ctrip.android.basebusiness.activity.CtripBaseActivity.onResume(SourceFile:166)
这段代码报错出现在 系统层面,通过现象来看 主要是出现在android 7.0 android 8.0 以上的机型
通过源码看进去
@CallSuper protected void onResume() { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this); getApplication().dispatchActivityResumed(this); mActivityTransitionState.onResume(this, isTopOfTask()); mCalled = true; }
在这里我们看到 了 isTopTask 的这个方法
继续走进去
/** * Indication of whether this is the highest level activity in this task. Can be used to * determine whether an activity launched by this activity was placed in the same task or * another task. * * @return true if this is the topmost, non-finishing activity in its task. */ private boolean isTopOfTask() { if (mToken == null || mWindow == null) { return false; } try { return ActivityManagerNative.getDefault().isTopOfTask(getActivityToken()); } catch (RemoteException e) { return false; } }
我们看到走进 AMS 中去了
@Override public boolean isTopOfTask(IBinder token) { synchronized (this) { ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r == null) { throw new IllegalArgumentException(); } return r.task.getTopActivity() == r; } }
我门看到 ActivityRecord r 为空了,是什么原因导致的 现在还不好去分析,所以做了保护的处理方案
在super.resume 的地方 添加 异常捕获
try { super.onResume(); } catch (Exception e) { callUpActivity(); e.printStackTrace(); }
private void callUpActivity() { try { Class videoSuperClass = Activity.class; Field callField = videoSuperClass.getDeclaredField("mCalled"); callField.setAccessible(true); callField.setBoolean(HotelVideoActivity.this, true); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } }通过反射的方式,将mCalled 这个参数强制设置为true,保证Activity 能正常启动!