Re-launch of Activity on Home button, but...only the first time
Asked Answered
D

4

53

The application that I am developing has a weird behavior the first time that it is installed. If the user backs out of the application normally the first time, it will forever behave as it should. If the user uses the home button the first time after installing the application, it treats the application as though it should re-launch the home screen again and launch a new version of an activity in front of the old one.

So there are really two issues at hand. I can't seem to resolve both of them.

  1. Keep the application from closing when it is first installed upon the user hitting the home button.
  2. Keep multiple versions of the application from launching when it does this (launchMode helps here a bit, but the first component still triggers).

I don't have the launchMode attribute in the manifest file defined as anything. So there shouldn't be any odd behavior as the result of this. I have experimented now with the launchmode attribute of the application to see if I could get it to behave the way it is intended, but there seems to be more to it here than just launching the activities properly. There is no reason that an application should close itself the first time as far as I can see when the home button is pressed.

I don't use the onUserLeaveHint within the application either. I had to be sure once again by doing a search over the project. So there doesn't seem to be any overriding of the home button attempted at all.

Even after re-starting the phone, the home button behaves normally again. Not sure what causes the initial installation to treat the home button as a flag to start the application from scratch.

Once the user backs out of the application the first time, the issue is permanently resolved. Any thoughts on where I should look?

Recently there has been a search within the application to see if perhaps it triggers only then because of an onUpgrade() component of the SQLite database method causing some odd behavior.

@Override
public void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion) {
                if (newVersion > oldVersion) {

           }
       }

Or in another location that might trigger with an update from the manifest file if I was passing along a newer version of the APK along to a device that had a version on it already that was one lower than the current one. However, nothing in this part of the code leads me to believe that it should affect anything related to the launch sequence.

The manifest file (with names changed) is supplied below for what is currently being used in the application.

<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10"/>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="com.android.vending.CHECK_LICENSE"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<uses-permission android:name="android.permission.VIBRATE" android:required="false"/>
<uses-permission android:name="android.permission.CAMERA" android:required="false"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>

<application android:icon="@drawable/icon"
             android:label="@string/app_name"
             android:allowBackup="false"
             android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
             >
    <activity android:name=".MyMain"
              android:label="@string/app_name_with_version"
              android:screenOrientation="portrait"
              android:windowSoftInputMode="adjustPan"   />
    <activity android:name=".StartupActivity"
              android:label="@string/app_name"
              android:screenOrientation="portrait"
              >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity   android:name=".SelectActivity"  
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"/>
    <activity   android:name=".ImageSelectionActivity"
                android:theme="@android:style/Theme.Dialog"
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"
                android:configChanges="orientation|keyboardHidden"/>            
    <activity   android:name=".DetailsActivity"
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"/>
    <activity   android:name=".EMailActivity"   
                android:label="@string/app_name_with_version"       
                android:screenOrientation="portrait"/>
    <activity   android:name=".SendTo" 
                android:label="@string/share_label" 
                android:theme="@android:style/Theme.Dialog" >
        <INTENT-FILTER>  
            <ACTION android:name="android.intent.action.MAIN">  
            <CATEGORY android:name="android.intent.category.LAUNCHER"/>  
            <INTENT-FILTER>  
                <ACTION android:name="android.intent.action.VIEW">  
                <CATEGORY android:name="android.intent.category.DEFAULT">  
                    <CATEGORY android:name="android.intent.category.BROWSABLE">  
                    <DATA android:scheme="callback" android:host="twitter"/>  
                    </CATEGORY>  
                </CATEGORY>
                </ACTION>
            </INTENT-FILTER>
            </ACTION>
        </INTENT-FILTER>
    </activity>
    <activity   android:name=".CreateMyActivity"
                android:label="@string/create_account_label"
                android:screenOrientation="portrait"
                android:theme="@android:style/Theme.Dialog"/>
    <activity   android:name=".ViewInLayoutActivity"
                android:label="@string/app_name_with_version"   
                android:screenOrientation="portrait"/>
    <activity   android:name=".Preferences"
                android:label="@string/set_preferences" 
                android:screenOrientation="portrait"
                android:theme="@android:style/Theme.Dialog"/>
    <activity   android:name=".AboutActivity"   
                android:label="@string/app_name_with_version"       
                android:screenOrientation="portrait"/>
    <activity   android:name=".InteractiveActivity" 
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"
                android:theme="@android:style/Theme.Dialog"/>   
    <activity   android:name=".AlertFailedCommunications"
                android:screenOrientation="portrait"
                android:label="@string/alert_account_label"
                android:theme="@android:style/Theme.Dialog"/>
</application>    

Departed answered 29/4, 2013 at 15:59 Comment(4)
It actually only happens the first time when distributed with the APK. It doesn't happen the first time if uninstalled and re-launched from the IDE (Eclipse). So it must have something to do with remote installation that is different from direct installation.Departed
Additionally, it only happens if launched immediately from the installation window. If after installation you say close, and then launch it from the home screen or from the app window, it never gets into this state for the first launch. There must be something in the life-cycle of the first window that causes this.Departed
There are many warnings about using single instance and you may just be catching one of them. From what I read single instance will make the activity the only task in the back stack which I dont think you wish to do. You do not have you code posted so I cannot really give any other answer. Please post you manifest file and the main activity you are refering to and I'll be able to give a better answer.Necessary
@JaySnayder I am facing the same issue.I am overriding onUserLeaveHint in one of the activity,Once i put the app in background using home and launch it again using launcher or shortcut icon,then the app restarts..Does Overriding the onUserLeaveHint cause this? This happens only during installation from PlayStore for the first time.Uzial
A
92

Welcome to the ever-growing list of users who have been bitten by this one.

This is a well-known and long-standing Android bug. in the way applications get launched the first time from the installer, web-browser and via IDE (IntelliJ, Eclipse, etc.). See these issues filed long ago related to the problem:

http://code.google.com/p/android/issues/detail?id=2373

http://code.google.com/p/android/issues/detail?id=26658

It is still broken and you cannot prevent this from happening. The only thing you can do is to detect when Android has launched a second instance of your root activity into an existing task. You can do this by putting this code in onCreate() of your root activity:

if (!isTaskRoot()) {
    // Android launched another instance of the root activity into an existing task
    //  so just quietly finish and go away, dropping the user back into the activity
    //  at the top of the stack (ie: the last state of this task)
    finish();
    return;
}
Agonizing answered 8/5, 2013 at 18:17 Comment(28)
See also #4342100Alliber
I had been fearful it was something like this. At least the QA has allowed to continue with this problem still in the program. I will be using the work-around that you have shown to me in a future release however after I have had some time to do tests with it. Really appreciate it.Departed
My pleasure. I'd appreciate it if you would go to the referenced issues on Google Code and star/comment them. The more noise we make about this, the more likely it is to get fixed in a future release. As a temporary fix you can tell your users not to click the "open" button after installing your app. Also be aware that this happens also after an app upgrade via the installer.Agonizing
Also starred the issues as well. You are right, the more noise that we make on these issues the better. An odd one that many people might not even know exists or is even happening in their application until it is brought forward to them and demonstrated.Departed
Still broken in 5.0 :-(Agonizing
"Welcome to the ever-growing list of users who have been bitten by this one." always a sad end to a day of despair. But at least I'm not alone. Seems to me that if there were an intent flag to do the same as recents we could fix this. I've raised a feature request to this effect here: code.google.com/p/android/issues/detail?id=180433 (as well as starring the linked issued). My own specific incarnation of this bug is documented here: #31458754Footboy
My take on this is that the app is being started from a different task (the installer) from the launcher. The different Task UIDs force the FLAG_ACTIVITY_NEW_TASK flag to be set and used. I noticed I also got this bug from a foreground service notification. If i didnt set that flag, the activity manager forced it on. Interestingly the bug seems to go away for a single activity with singleTask launchmode set. so Google Maps behaves just fine (it's one activity with a load of fragments)Footboy
Here we go: #20056100Footboy
Still broken in Android 6.0.1 :-(Agonizing
Still broken in Android 7 :-(Agonizing
Yep. This is still occurring. Thanks for this solution. It is working well for me.Blarney
On some devices, isTaskRoot returns false if app launched by a deep link even if its really root task, so this control breaks my deep link work logic.Inland
@Inland i find this incredibly hard to believe. You should actually check using adb shell dumpsys activity activities what the task looks like.Agonizing
@DavidWasser i couldnt find the devices but it was something like note 3 and Nexus 5. On Note 3, deeplink activated by chrome browser and it was fine, but when used with samsung internal browser isTaskRoot was false. On Nexus 5, deeplink activated by chrome browser and isTaskRoot was false too.Inland
@Inland like I said, this is hard to believe. If you can repro it and dump the task stack I would be grateful. Because you may just be seeing some other problem.Agonizing
Could it be possible that it is still broken in Android 8.1?Jinajingle
@Jinajingle I assume this is still broken. As far as I know, it has never been fixed.Agonizing
This solution is not working for me, I'm still able to spawn multiple instances of the appPsia
@Psia please post a new question and include a description of your problem. I'll take a look.Agonizing
@DavidWasser, thanks, the question is here #55888719Psia
This only works for me in combination with android:launchMode="singleTop"Guthrie
@Guthrie That makes no sense. Please open a new question and give more information.Agonizing
@DavidWasser how can i check it in develop mode when running from Android Studio?Sejm
@UrielFrankel Sorry, I don't understand your question.Agonizing
@DavidWasser I want to reproduce the problem and fix it in my app. I want to be able to reproduce it, then add the fixing code and check if it is fixedSejm
@UrielFrankel not so easy. You need to build your app and copy the apk to the device. Then open the apk with a file browser and install it. After installation, click the "open" button. Now your app is running. Press HOME. Now tap the app icon on the HOME screen to start the app again. What should happen is that Android brings the existing task to the foreground without launching a new Activity. What happens is that Android launches a new Activity into the existing task, so you now have 2 copies of the Activity in the task. You can check this using adb shell dumpsys activity activities.Agonizing
@DavidWasser i tried but it isn't workingSejm
@UrielFrankel please open a new question and show us the problem. We can't do this in the comment thread of another question.Agonizing
T
6

Why this is behaving, no clue. But I know that custom Launcher have specific launchModes set.

For example the ADW.Launcher:

android:clearTaskOnLaunch="true"
android:launchMode="singleTask" 

Home application in the Android SDK samples: android-sdk\samples\android-16\Home\AndroidManifest.xml

android:launchMode="singleInstance"

To quote CommonsWare: How to prevent custom home launcher app restart activity?

I am going by the Home sample application from the SDK, which uses singleInstance. Curiously, the AOSP launchers use singleTask

Thrawn answered 2/5, 2013 at 12:38 Comment(2)
Appreciate the input. I have attempted various launchModes with the main class previously. This resolves partially the issue at hand, but still causes the application to close when hitting the home button. It prevents the Activity from creating multiple copies of itself though.Departed
Additionally I had found that when I do implement the lanchMode as indicated, the application now closes every single time when hitting the home button, not just the first time. That was the large downside.Departed
E
2

Looks like the issue is caused by the different instances of the app. Probably the first instance is launched under the installer's task and the second one is under its own task, when user clicks on app icon. It seems to user he/she resumes the app but actually he launches it again at this moment.

If you want to get your app to run in its own task only, a possible way is to add

android:allowTaskReparenting="true"

to the application-level of your AndroidManifest. Once the app icon is clicked for the first time after installation, your application will be moved to the separated task.

Exponential answered 29/5, 2017 at 18:18 Comment(1)
Works elegantly and perfectly.Santonin
S
2

The answers above didn't work for me using Nativescript - this solved the issue by adding these two properties in the activity tag:

android:alwaysRetainTaskState="true"
android:launchMode="singleTask"

This link provided this solution: https://github.com/NativeScript/NativeScript/issues/3415

Shum answered 3/7, 2021 at 20:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.