编辑
第二次打开被杀死的Android应用出现了奇怪的问题
本文访问次数:0

问题描述如下:
打开应用,返回到主界面,在终端执行以下命令

adb shell am kill me.zongren.android.app

从任务管理重新打开应用,应用没有打开Launcher Activity,而是直接打开了退出之前的Activity(例如RootActivity),页面显示空白(应该是主题主色调),相关的单例对象被重新创建。由于业务需要每次打开应用都必须检测应用相关状态(是否被远程关闭等),相关代码被放在SplashActivity中,所以这个问题必须解决。一开始以为是launchMode设置的问题,结果并不是,仔细看了一下现在的manifest.xml文件,如下所示:

<manifest 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="me.zongren.android.app"
    >
    <application
        ...
        android:allowBackup="true"
        ...
        >

        <activity android:name=".Activity.SplashActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".Activity.RootActivity"
            android:launchMode="singleTask"
            />
        ...
    </application>
</manifest>

注意到allowBackup属性,看一下官方的解释,原文如下:

Whether to allow the application to participate in the backup and restore infrastructure. If this attribute is set to false, no backup or restore of the application will ever be performed, even by a full-system backup that would otherwise cause all application data to be saved via adb. The default value of this attribute is true.

简单翻译一下,大概就是

是否允许应用参与备份恢复机制,如果设置为false,应用不会进行任何备份和恢复操作,即使使用完整的系统备份功能。默认值为true。

另外关于这个属性的漏洞可以查看这篇文章:Android 属性 allowBackup 安全风险浅析

如果其他库设置了allowBackup=true,还需要设置一下

<application
    xmlns:tools="http://schemas.android.com/tools"
    android:allowBackup="false"
    tools:replace="android:allowBackup,android:icon"
    >

注意application不能同时存在tools:ignore和tools:replace。

将其设置为false后也没有解决问题,然后重新思考了一下,发现这应该是Android自带的机制,打开最后一个Activity,即使程序被杀死了。所以目前能想到的解决办法是,在每个Activity的onCreate判断是否是重新启动,如果是,则打开SplashActivity,代码如下

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (!App.getInstance().launched) {
        Intent intent = new Intent(getApplicationContext(), SplashActivity.class);
        startActivity(intent);
        finish();
    }
    ...
}

同时修改主题,添加背景图,这样从后台打开就不会显示纯色的背景

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowBackground">@drawable/activity_splash_background</item>
</style>
没有任何评论