有没有办法处理处于暂停状态的Android应用程序被杀死,以使系统自动重新启动活动?

时间:2019-08-09 12:51:10

标签: android cordova ionic-framework kill kill-process

我有一个Ionic / Cordova应用,该应用大量使用了相机插件,并且在Android上运行时遇到了问题。

Android Activity Lifecycle docs文档和Cordova's Lifecycle Docs for the Android Platform中所述,当摄像头来到前台时,应用的主要活动将被放入pausedstopped中状态在后台。

尽管主要活动处于上述两种状态中,但如果它需要释放内存,则很容易被系统杀死,这种情况在此应用程序中经常发生,足以使用户抱怨。

在测试中,我发现有时在关闭相机后该应用程序会自行重启,而有时活动似乎已经消失在相机后面,因此当用户关闭相机时,该应用程序似乎崩溃了。

阅读了上述文档后,我向由Cordova生成的MainActivty android代码添加了一些日志记录,以便可以观察使用相机时的状态变化,还向onCreate添加了未捕获的异常处理程序:

public class MainActivity extends CordovaActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.e("com.xxx.test", "onCreate");
        super.onCreate(savedInstanceState);

        // enable Cordova apps to be started in the background
        Bundle extras = getIntent().getExtras();

        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }

        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);


        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
                Log.e("com.xxx.test", "onCreate, UNCAUGHT EXCEPTION!!!");
                System.exit(2);
            }
        });
    }

    @Override
    public void onStart() {
        Log.e("com.xxx.test", "onStart");
        super.onStart();

    }

    @Override
    public void onResume() {
        Log.e("com.xxx.test", "onResume");
        super.onResume();

    }

    @Override
    public void onPause() {
        Log.e("com.xxx.test", "onPause");
        super.onPause();
    }

    @Override
    public void onStop() {
        Log.e("com.xxx.test", "onStop");
        super.onStop();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("com.xxx.test", "onDestroy");

    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        Log.e("com.xxx.test", "onSaveInstanceState");
        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        Log.e("com.xxx.test", "onRestoreInstanceState");
        super.onRestoreInstanceState(savedInstanceState);
    }
}

我运行该应用程序,并过滤logcat中包含“ com.xxx.test”的行,并显示以下结果:

相机正常操作

//camera button tapped
onPause
onSaveInstanceState
onStop

//user takes photo and dismisses camera
onResume

应用重新启动

到目前为止,一切都很好。现在,如果在关闭相机后应用重新启动,我会得到:

//camera button tapped
onPause
onSaveInstanceState
onStop

//user takes photo and dismisses camera, app restarts itself here
onCreate
onStart
onRestoreInstanceState
onResume

这是我期望在应用程序在后台终止活动时看到的内容-当用户导航回该活动时,系统会重新创建活动并加载任何保存的状态等。这很好,我将能够处理中断。

崩溃

但是,有时日志会这样做:

//camera button tapped
onPause

//sometimes it stops here, sometimes I also get
onSaveInstanceState

//boom! - the app seems to have crashed and the user is taken back to the home screen when dismissing the camera

因此,我怀疑正在发生的事情是系统在活动进入stopped状态之前就将其杀死,并且没有保存重新启动该活动所需的任何引用。然后,当我们尝试返回该活动时,系统不知道要加载什么,因此仅退出应用程序。

我不是100%肯定是这种情况。也许该应用在其他地方崩溃了,但我对此一无所知。

所以我的问题是,如果系统杀死了Android上处于paused状态的活动,我们是否应该能够根据需要再次导航回该活动,或者该标准行为是应用程序刚刚退出并且用户必须重新启动吗?如果是这样,是否有任何解决方法?

如果活动应该在不退出应用程序的情况下返回,那么我如何找出导致崩溃的原因?我的异常处理程序从未被调用过,我已经在logcat的所有行中苦苦跋涉,但是看不到任何东西可以为我提供有关问题所在的任何线索。

我已经使用事件探查器运行该应用程序,尽管内存使用率很高,大约为350mb,但似乎没有任何泄漏会随着拍摄更多照片而使它越来越高。

关于重新创建问题需要拍摄多少张照片,似乎也没有任何规律,有时它会一遍又一遍地重新启动,有时会一遍又一遍地退出,而另一些时候我会混合物。

任何有关如何阻止此类崩溃的想法都值得赞赏。

修改

我一直在浏览日志,试图整理发生的事情的时间表:

因此,用户在应用程序中点击相机按钮,主要活动进入paused状态,onSaveInstanceState()被称为...

16:23:10.244 505-505/com.xxx.test I/chromium: [INFO:CONSOLE(24978)] "photo button tapped", source: file:///android_asset/www/build/main.js (24978)
16:23:10.315 505-505/com.xxx.test E/com.xxx.test: onPause
16:23:10.315 505-505/com.xxx.test D/CordovaActivity: Paused the activity.
16:23:10.322 505-505/com.xxx.test E/com.xxx.test: onSaveInstanceState

此后,有一堆摄像机设置日志,但在所有主要活动中,所有日志都消失了,大概是被系统杀死以释放资源...

16:23:11.415 3696-6128/? I/WindowManager: WIN DEATH: Window{2ae98e1d0 u0 com.xxx.test/com.xxx.test.MainActivity}
16:23:11.415 3696-4312/? I/ActivityManager: Process com.xxx.test (pid 505) has died(377,151)

尽管onSaveInstanceState()被调用,但系统声称没有保存状态...

16:23:11.419 3696-4312/? W/ActivityManager: Force removing ActivityRecord{c76b13bd0 u0 com.xxx.test/.MainActivity t2117}: app died, no saved state

然后大约半秒钟,当相机仍然可见时,系统为我的包裹名称启动一个新过程...

16:23:12.047 3696-9816/? D/MountService: getExternalStorageMountMode : 3
    getExternalStorageMountMode : 3
    getExternalStorageMountMode : final mountMode=3, uid : 10298, packageName : com.xxx.test
16:23:12.061 3696-9816/? I/ActivityManager: Start proc 6426:com.xxx.test/u0a298 for content provider com.xxx.test/android.support.v4.content.FileProvider

虽然进程6426的日志记录很少,

16:23:12.062 6426-6426/? E/Zygote: v2
16:23:12.062 6426-6426/? I/libpersona: KNOX_SDCARD checking this for 10298
16:23:12.063 6426-6426/? I/libpersona: KNOX_SDCARD not a persona
16:23:12.063 6426-6426/? E/Zygote: accessInfo : 0
16:23:12.064 6426-6426/? W/SELinux: SELinux selinux_android_compute_policy_index : Policy Index[2],  Con:u:r:zygote:s0 RAM:SEPF_SECMOBILE_7.0_0007, [-1 -1 -1 -1 0 1]
16:23:12.064 6426-6426/? I/SELinux: SELinux: seapp_context_lookup: seinfo=untrusted, level=s0:c512,c768, pkgname=com.xxx.test
16:23:12.069 6426-6426/? I/art: Late-enabling -Xcheck:jni
16:23:12.098 6426-6426/? D/TimaKeyStoreProvider: TimaKeyStore is not enabled: cannot add TimaSignature Service and generateKeyPair Service

就是这样。不过,ActivityManager很快尝试将重新创建的活动移到最前面...

16:23:12.212 3696-5435/? D/ActivityManager: moveToFront() : reason=startedActivity setFocusedActivity isAttached=true TaskRecord{d952617d0 #2117 A=com.xxx.test U=0 StackId=1 sz=2}
16:23:12.213 3696-5435/? D/InputDispatcher: Focused application set to: xxxx

然后相机暂停,即使用户仍然可以看到它...

16:23:12.239 30891-30891/? V/Camera6: onPause

ActivityManager再次提到了我的包裹名称...

16:23:12.558 3696-6838/? D/ActivityManager: resumeTopActivityInnerLocked() : #1 prevTask=TaskRecord{d952617d0 #2117 A=com.xxx.test U=0 StackId=1 sz=2} next=ActivityRecord{bc76899d0 u0 com.sec.android.app.camera/.AttachActivity t2117} mFocusedStack=ActivityStack{33a525ad0 stackId=1, 2 tasks}

不久之后,MultiScreenManagerService抱怨任务有多个活动,ActivityManager开始做更多的事情……

16:23:14.529 3696-13852/? W/MultiScreenManagerService: moveTaskBackToDisplayIfNeeded(): The task has more than one activity
16:23:14.530 3696-13852/? D/ActivityManager: moveToFront() : reason=finishActivity adjustFocus setFocusedActivity isAttached=true TaskRecord{d952617d0 #2117 A=com.xxx.test U=0 StackId=1 sz=2}
16:23:14.535 3696-13852/? D/InputDispatcher: Focused application set to: xxxx
16:23:14.536 3696-13852/? D/ActivityTrigger: ActivityTrigger activityPauseTrigger
16:23:14.544 30891-30891/? V/AttachActivity: onPause
16:23:14.545 3696-5485/? D/ActivityManager: setAppIconInfo(), x : 0, y : 0, width : 0, height : 0, isHomeItem : false
    resumeTopActivityInnerLocked() : #1 prevTask=TaskRecord{d952617d0 #2117 A=com.xxx.test U=0 StackId=1 sz=2} next=ActivityRecord{1da4823d0 u0 com.sec.android.app.camera/.Camera t2117} mFocusedStack=ActivityStack{33a525ad0 stackId=1, 2 tasks}

最终,相机被用户关闭...

16:23:14.634 30891-30891/? V/Camera6: finish

这时,我们收到了MultiScreenManagerService的更多投诉,现在ActivityManager希望将com.sec.android.app.launcher移到前面,我想这是主屏幕... < / p>

16:23:14.637 3696-9814/? W/MultiScreenManagerService: moveTaskBackToDisplayIfNeeded(): root is not base activity
16:23:14.642 3696-9814/? D/ActivityManager: moveToFront() : reason=finishActivity adjustFocus setFocusedActivity isAttached=true TaskRecord{3965df5d0 #2072 A=com.sec.android.app.launcher U=0 StackId=0 sz=1}
16:23:14.642 3696-9814/? W/MultiScreenManagerService: moveTaskBackToDisplayIfNeeded(): root activity or app is null

ActivityManager的另一条日志中提到了相机的重复完成请求...

16:23:14.663 3696-6002/? W/ActivityManager: Duplicate finish request for ActivityRecord{1da4823d0 u0 com.sec.android.app.camera/.Camera t2117 f}

此时,我假设正在显示主屏幕,但是ActivityManager的包装上还有其他内容……

16:23:14.715 3696-5436/? D/ActivityManager: resumeTopActivityInnerLocked() : #0 prevTask=TaskRecord{d952617d0 #2117 A=com.xxx.test U=0 StackId=1 sz=2} next=ActivityRecord{eed8739d0 u0 com.sec.android.app.launcher/.activities.LauncherActivity t2072} mFocusedStack=ActivityStack{514789d0 stackId=0, 2 tasks}
    applyOptionsLocked(), pendingOptions : null

但无济于事,此后唯一提及我的活动的只是偶然的日志组,例如...

16:23:14.844 3696-3707/? D/PackageManager: getComponentMetadataForIconTray : com.xxx.test.MainActivity does not exist in mServices
    getComponentMetadataForIconTray : com.xxx.test.MainActivity does not exist in mProviders
    getComponentMetadataForIconTray : com.xxx.test.MainActivity does not exist in mReceivers
16:23:14.846 4439-4439/? I/ApplicationPackageManager: load=com.xxx.test, bg=192-192, dr=192-192, forDefault=true
    reset dr=192,192, bg=192,192

因此,问题出在哪里。在相机仍然可见的情况下,系统似乎尝试重新启动我的活动,这使事情搞砸了,但是我仍然不确定到底发生了什么或对此我能做些什么。

有人有什么主意吗?

0 个答案:

没有答案