40

I have two activities in My application, one being launcher and the other is launched as a explicit call from the first.

Here My problem is when i go back to home screen by pressing home key from second activity and launch the application, again the first activity gets initiated even though the second activity is already in the background.

The first Activity is written to download the required assets for the application to work, once the assets are downloaded it triggers the second activity and calls finish for self.

Below is my manifest of the application.

<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"/>

Can Somebody please guide me on how to make the second activity gain the control directly instead of going through the first again if launcher is called and it is in the background.

Below is my onResult Call back method.

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;
}
Sudhaker
  • 785
  • 1
  • 6
  • 13

6 Answers6

39

Try using the following code in the onCreate method of the activity that is specified as the Launcher Activity in the Manifest, i.e. the ContentDownload activity from the original code posted in the question:

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

This will finish your Launcher Activity before it is displayed by detecting that there is already a task running, and your app should instead resume to the last visible Activity.

See this page in the Android documentation regarding Android Manifest launchModes: http://developer.android.com/reference/android/R.styleable.html#AndroidManifestActivity_launchMode

Jadent
  • 974
  • 8
  • 14
  • Hi Jadent, Thanks for the answer, though this question is posted long back and I just realised I did not select any answer to this. From the link I am assuming your solution should work and selecting this as an answer but I no longer have access to that project to verify this behaviour. – Sudhaker Mar 26 '14 at 08:15
  • 3
    the problem is, you should copy the code segment to every activity. – Logan Guo Aug 13 '15 at 03:25
  • can u provide info about flag more . – King of Masses Aug 08 '17 at 13:21
  • Not working for me on some devices (I have splash screen that needs to be destroyed, so problem is pretty the same). `isTaskRoot()` works fine always (from my tests) – user1209216 Oct 16 '17 at 07:32
13

You've got both your activities defined with launchMode="singleTask". This is the root of your problem. Remove that.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • you want me to remove them completely in both places or they must be replaced with something else? – Sudhaker Jul 30 '12 at 15:35
  • Remove completely in both places. – David Wasser Jul 30 '12 at 15:36
  • 1
    If I dont have singleTask then there can be multiple instances of the same activity in my application (which I encountered earlier so placed it which solved my other issues) such as when activity is in the background launch it from search bar a new activity will be started instead of resuming the existing one. – Sudhaker Jul 31 '12 at 13:26
  • 1
    No, this is the wrong way to solve that problem, which is why you are in this mess in the first place. If your app is in the background and you launch the root activity again, normally Android will just bring the existing task to the foreground. It will not create a new instance of the activity. – David Wasser Jul 31 '12 at 16:31
  • 1
    OK, I see. if you launch the app from search bar the activity may end up in another task. In that case you could have different instances of it in different tasks. If that isn't what you want then you can specify `launchMode="singleTask"` but **only** for the root activty (ContentDownload), not for the other activities. – David Wasser Jul 31 '12 at 16:37
  • Nope David, weird thing is that even the second activity is crashing when I resume again :( – Sudhaker Aug 03 '12 at 22:02
  • What's in the logcat in that case? – David Wasser Aug 03 '12 at 22:04
13

I use the following code in the LAUNCHER Activities of my apps to prevent the app from beeing started again when its still alive in the background and the icon is tapped

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

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

    // Rest of your onCreate stuff goes here
}

This just finishes the LAUNCHER Activity and resumes the last used one.

Saenic
  • 1,593
  • 13
  • 14
4

Do not call finish(). You need to pass to the Intent the flag FLAG_ACTIVITY_CLEAR_TASK and 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);
Uriel Frankel
  • 14,304
  • 8
  • 47
  • 69
  • I will try that, but is it not unnecessary to keep the activity in the background when it is not used at all and more over I should not go back to the downloader activity when I exit from the second one, I assume the launcher activity will resume if I do not call finish on the it. – Sudhaker Jul 30 '12 at 12:50
  • Clearing the task is not working instead it is starting the second activity again but was resuming the second activity where it was interrupted before... :( – Sudhaker Jul 30 '12 at 13:07
  • i think clearing the task or top does nothing as the second activity does not have any intent filter and so the OS has no choice but to invoke the first Activity... – Sudhaker Jul 30 '12 at 13:22
  • what about in the case where you don't know what activity was previously running, I have a weird case where on some devices the main activity gets called even when the running activity that was dismissed(home button press) isn't the main activity. I would have to check the stack? yes? – Mikey0000 May 13 '16 at 00:05
1

Without seeing your code, I think you want something like this answer:

Android finish Activity and start another one

You need to set intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); and you'll also need to finish() your launcher activity as well.

Community
  • 1
  • 1
themanatuf
  • 2,880
  • 2
  • 25
  • 39
  • But you're not calling `intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);` as the answer I linked too suggested. Try that and see if it works. – themanatuf Jul 30 '12 at 12:52
  • I Just tried using CLEAR TOP still the launched is invoked when tapped on icon but the second activity resume from where it was paused (Was happening the same previously)... – Sudhaker Jul 30 '12 at 13:13
  • i think clearing the task or top does nothing as the second activity does not have any intent filter and so the OS has no choice but to invoke the first Activity... – Sudhaker Jul 30 '12 at 13:22
-1

what you can do is store a string in the persistent storage which determines whether the assets have been loaded before or not.

Then, in the main activity, you may check if the assets have been loaded or not and then start the required activity.

if(assets_already_downloaded)
  second_activity();
else
  download_asset_activity();
Tanuj Wadhwa
  • 2,025
  • 9
  • 35
  • 57
  • The Down loader activity is in the form of a library so I cannot by pass or change the way it reacts and the library activity has to be launched to determine if the assets are downloaded... – Sudhaker Jul 30 '12 at 12:42
  • I Updated the onResult Code in my question, seems the similar implementation is already there... – Sudhaker Jul 30 '12 at 12:46