在实际的开发中,遇到一种崩溃,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 能正常启动!