You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用按Home键关闭后无法恢复至ActivityB问题求助

问题:按Home返回后无法恢复到ActivityB界面

我的应用包含4个Activity:SplashActivity、LoginActivity、ActivityA和ActivityB。其中ActivityB由ActivityA启动。SplashActivity作为应用启动页(Launcher),会检查用户登录状态:已登录则启动ActivityA,未登录则启动LoginActivity。

现在遇到的问题是:在ActivityB界面按Home键退出应用,再次打开时却跳转到ActivityA,预期应该直接恢复到ActivityB界面。

现有Manifest配置

<activity
    android:name=".screen.splash.SplashActivity"
    android:exported="true"
    android:launchMode="singleTask"
    android:theme="${splashTheme}"
    android:noHistory="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity
    android:name=".ActivityA"
    android:exported="false"
    android:launchMode="singleInstance" />

<activity
    android:name=".ActivityB"
    android:exported="false"
    android:windowSoftInputMode="adjustResize"
    android:alwaysRetainTaskState="true"/>

<activity
    android:name="LoginActivity"
    android:exported="false"
    android:theme="${splashTheme}" />

SplashActivity核心逻辑

if (SettingService.isLogged()) {
    val intent = Intent(this@SplashActivity, ActivityA::class.java)
    startActivity(intent)
} else {
    startActivity<LoginActivity>() // org.jetbrains.anko
}

问题根源

  1. ActivityA的singleInstance模式:这个模式会让ActivityA独占一个独立的任务栈,从ActivityA启动ActivityB时,B会被放入应用的默认任务栈。此时应用存在两个独立任务栈:一个是ActivityA的专属栈,另一个是包含ActivityB的默认栈。
  2. SplashActivity的启动逻辑缺陷:每次从Launcher打开应用,Splash都会直接启动ActivityA,系统会把ActivityA的任务栈带到前台,而包含ActivityB的默认栈被压在后台,因此显示的是ActivityA。

解决方案

方案1:修正ActivityA的启动模式(推荐)

把ActivityA的launchMode从singleInstance改为默认的standard或singleTop,让A和B处于同一个任务栈中,这样系统就能正确恢复到栈顶的ActivityB:

<activity
    android:name=".ActivityA"
    android:exported="false"
    android:launchMode="standard" /> <!-- 或singleTop,根据业务需求选择 -->

保留ActivityB的alwaysRetainTaskState="true",它能避免系统因内存回收销毁任务栈状态。

方案2:修改SplashActivity的启动逻辑(适配特殊场景)

如果必须保留ActivityA的singleInstance模式,需要在Splash中判断应用是否已有存活的任务栈,有则直接唤起栈顶Activity,而非重新启动ActivityA:

if (SettingService.isLogged()) {
    val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
    var hasExistingTask = false
    // 遍历当前运行的任务栈
    for (task in activityManager.appTasks) {
        val taskInfo = task.taskInfo
        if (taskInfo.baseActivity?.packageName == packageName && 
            !taskInfo.topActivity?.className.equals(SplashActivity::class.java.name)) {
            // 唤起已有任务栈的顶层Activity
            task.moveToFront()
            hasExistingTask = true
            break
        }
    }
    // 没有存活任务栈才启动ActivityA
    if (!hasExistingTask) {
        val intent = Intent(this@SplashActivity, ActivityA::class.java)
        startActivity(intent)
    }
} else {
    startActivity<LoginActivity>()
}

注:API 21及以上推荐用appTasks替代已废弃的getRunningTasks方法。

补充说明

SplashActivity的singleTask和noHistory="true"设置是合理的:singleTask确保Splash不会重复创建实例,noHistory让Splash启动后不会留在任务栈中,无需改动。


内容的提问来源于stack exchange,提问作者Khoa Chau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:17:51