Android ActivityRecord 为空的异常处理方案

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





你可能感兴趣的:(常见问题)