恢复顶部活动而不是启动启动器活动

40
我在我的应用程序中有两个活动,一个是启动器,另一个是从第一个活动中作为显式调用启动的。
我的问题是,当我从第二个活动按下Home键返回到主屏幕并重新启动应用程序时,即使第二个活动已经在后台运行,第一个活动仍会被初始化。
第一个Activity被编写用于下载应用程序所需的资产,一旦下载完成,它会触发第二个活动并调用自身的finish()。
以下是我的应用程序清单。
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="14" />

<application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">

    <! Download the Required Assets if not found on SD Card -->
    <activity android:name=".ContentDownload"
        android:screenOrientation="landscape"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|locale" 
        android:launchMode="singleTask"
        android:alwaysRetainTaskState="true">

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

        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

    </activity>

    <activity android:name=".ActualAppActivity" 
        android:screenOrientation="landscape" 
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|locale" 
        android:launchMode="singleTask"
        android:alwaysRetainTaskState="true"
        />

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>  

<supports-screens android:smallScreens="false" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"/>

请问有没有人能指导我如何让第二个活动直接获得控制,而不是再次通过第一个活动,如果启动器被调用并且它在后台运行。

以下是我的onResult回调方法。

public void onResult(String assetPath, int result)
{
    if(result == RESULT_OK)
    {
        startActivity(new Intent(this, ActualAppActivity.class));
        activity.destroyDownloadActvity();
        finish();
    }
    else
    {
        finish();
        java.lang.System.exit(0);
    }
    activity.destroyDownloadActvity();
    activity = null;
}
6个回答

39

请尝试在Manifest文件中指定为启动器活动的活动(即问题中发布的原始代码中的ContentDownload活动)的onCreate方法中使用以下代码:

if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
  finish();
  return;
}

通过检测已存在任务,这将在启动器活动显示之前完成其关闭,并使您的应用程序恢复到上次可见的活动。

请参阅Android文档中关于Android清单启动模式的页面:http://developer.android.com/reference/android/R.styleable.html#AndroidManifestActivity_launchMode


嗨,Jadent,感谢您的回答,尽管这个问题是很久以前发布的,我刚刚意识到我没有选择任何答案。从链接中我假设您的解决方案应该可以工作,并将其选为答案,但我不再有访问那个项目来验证这种行为。 - Sudhaker
3
问题是,你需要将代码段复制到每个活动中。 - Logan Guo
你能提供更多关于flag的信息吗? - King of Masses
在某些设备上对我不起作用(我有需要被销毁的启动画面,所以问题基本相同)。从我的测试中看来,isTaskRoot() 总是正常工作。 - user1209216

13

在我的应用程序的LAUNCHER活动中,我使用以下代码以防止应用程序在后台仍然存在并且单击图标时再次启动

@Override
protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (!isTaskRoot()) {
        finish();
        return;
    }

    // Rest of your onCreate stuff goes here
}

这只是完成了LAUNCHER活动并恢复了上次使用的一个。


13

你把两个活动都定义为 launchMode="singleTask",这就是问题的根源。请移除。


你是想让我在两个地方都完全删除它们,还是必须用其他东西替换它们? - Sudhaker
1
如果我没有使用singleTask,那么在我的应用程序中可能会出现同一活动的多个实例(我之前遇到过这种情况,所以我将其放置在其他问题得到解决的位置),例如当活动在后台时,从搜索栏启动它将启动一个新的活动而不是恢复现有的活动。 - Sudhaker
1
不,这不是解决问题的正确方式,这也是你陷入困境的原因。如果你的应用程序在后台运行并再次启动根活动,则通常情况下Android只会将现有任务带到前台,而不会创建活动的新实例。 - David Wasser
1
好的,我知道了。如果您从搜索栏启动应用程序,则活动可能会结束在另一个任务中。在这种情况下,您可能会在不同的任务中有不同的实例。如果这不是您想要的,则可以指定 launchMode="singleTask",但仅适用于根活动(ContentDownload),而不适用于其他活动。 - David Wasser
不行 David,奇怪的是当我再次恢复时,即使第二个活动也会崩溃 :( - Sudhaker
显示剩余2条评论

4

不要调用finish()方法。你需要在Intent中传递标记FLAG_ACTIVITY_CLEAR_TASK和FLAG_ACTIVITY_NEW_TASK。

Intent intent = new Intent(this, ActualAppActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK| Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

我会尝试,但是当活动根本没有被使用时,将其保留在后台是否不必要?而且,当我从第二个活动退出时,我不应该返回到下载器活动,如果我没有在启动器活动上调用finish,则假定启动器活动将恢复。 - Sudhaker
清除任务并没有起作用,反而重新启动了第二个活动。但它应该在原来中断的位置继续执行第二个活动... :( - Sudhaker
我认为清除任务或顶部并不起作用,因为第二个活动没有任何意图过滤器,所以操作系统别无选择,只能调用第一个活动... - Sudhaker
如果您不知道之前运行的活动是什么,该怎么办?我遇到了一个奇怪的情况,在某些设备上,即使被解除的运行活动(按下主页按钮)不是主要活动,主要活动也会被调用。我需要检查堆栈吗?是的? - Mikey0000

1

没有看到你的代码,但我认为你想要这样的答案:

Android finish Activity and start another one

你需要设置 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);,并且你还需要结束你的启动活动 finish()


但是你没有像我链接中建议的那样调用 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);。尝试一下,看看是否有效。 - themanatuf
我刚刚尝试使用CLEAR TOP,但是当点击图标时仍会调用启动,但第二个活动会从暂停的位置恢复(之前也是这样)。 - Sudhaker
我认为清除任务或顶部不起作用,因为第二个活动没有任何意图过滤器,所以操作系统别无选择,只能调用第一个活动... - Sudhaker

-1
你可以将一个字符串存储在持久化存储中,以确定资源是否已被加载。然后,在主活动中,你可以检查资源是否已被加载,并启动所需的活动。
if(assets_already_downloaded)
  second_activity();
else
  download_asset_activity();

下载器活动以库的形式存在,因此我无法绕过或更改其反应方式,必须启动库活动以确定是否已下载资产... - Sudhaker
我已经更新了我的问题中的onResult代码,似乎类似的实现已经存在... - Sudhaker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接