Retaining android app state using alwaysRetainTaskState and lauchMode

14,207

Solution 1

I solved this by adding the screenless DispatcherActivity and making it the default one (by using the very same intent filter). In its onCreate method you create and call the Intent based on some reasonable default (your Main activity for example) OR based on some saved token that identifies which Activity should be started. That token is saved/refreshed in onStop method of any Activity you want to call on restart. You can save this token to Preferences.

The rational here is that last activity that was visible will execute onStop method when interrupted.

Word of caution here: I did implement this pattern and it worked reasonably well. However it seems not play too well with history and finally I just gave up and yanked this code out. Nobody complained so far.

Solution 2

FYI singleTask is not what you want, since it starts a new task:

http://developer.android.com/guide/topics/manifest/activity-element.html#lmode

How are you launching Activity B? Any non-standard launch modes or Intent flags?

Solution 3

For anyone coming here with similar problems, I found something strange that might be what you are seeing... maybe.

Say I have an app with activities A -> B -> C etc. I was having issues with my app always "resuming" to A if it was launched from the app list aka launcher. Resuming from the "resents" screen (long home press) would exhibit correct resume behaviour though (resume to B or C as expected). My manifest was nothing special, I have alwaysRetainTaskState="true" set in my root activity, and launch mode is default (standard).

I was loading the apk onto my phone via a website. After downloading and installing, I would press "Open" to launch the app right away. For some reason (after uninstalling the app) I tired downloading again, installing, but then I pressed the "Done" button instead. Then Launching the app from the launcher/"all apps" list has the same resume behaviour as resuming from recents - in other words my problems were being caused somehow because of the installation process when clicking "Open" instead of "Done".

I verified this "solution" on API10 (2.3.5) and API15 (4.0.4)

Share:
14,207
jlim
Author by

jlim

Updated on June 04, 2022

Comments

  • jlim
    jlim almost 2 years

    In my Android app, I have a main activity that serves as an entry point to my application, which is configured in my manifest file like this :

    <activity android:name=".Main"
                  android:label="@string/app_name"
                  android:screenOrientation="portrait"
                  android:alwaysRetainTaskState="true"
                  android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    

    So for a particular use case, lets say a user starts up the app from the home screen by clicking the icon inside the application launcher. After starting the app, the user navigates from the Main activity to activity A and then finally to activity B. At this point, the user decides to check their facebook, so they click the home button to put my app in the background, and launches the facebook app.

    After checking their facebook, the user wants to return to my app, so they press the home key, and launch the application from the application launcher (just like they did the first time it was launched).

    When a user returns to my app, I want the app to return to the last activity the user was at when the app was put into the background, which in this case is activity B. In the manifest file, I have set alwaysRetainTaskState=true to make sure the OS doesn't kill my app's activities.

    Now to my question: how do I get the behavior I described above? Whenever I click my app's icon, it always starts at the Main activity, no matter what. I think this is because of the category.LAUNCHER attribute. I have tried android:launchMode=singleTask, but it hasn't made a difference; it always starts at Main.

    If someone could clarify intent filters, launch modes, and tasks, that would be great!