inexplicable behaviour of activity backstack - android

I have simple app with two activities. Here is manifest:
<application>
<activity
android:name=".ActivityA"
android:theme="#style/AppTheme.NoActionBar.Map">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".ActivityB"
android:theme="#style/AppTheme.NoActionBar">
<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:host="https://stackoverflow.com/"
android:scheme="http"
android:pathPrefix="/questions/ask"
/>
</intent-filter>
</activity>
</>
as u can see, when link "https://stackoverflow.com/questions/ask" will be clicked - my app will open second activity.
In the ActivityB I override onBackPressed method:
override fun onBackPressed() {
if(isTaskRoot){
startActivity(Intent(this, MapActivity::class.java))
finish()
} else {
super.onBackPressed()
}
}
so when second activity started from link and I click on back btn, ActivityA is opened and ActivityB is finished.
for the first look everything looks fine, but if after this i press home btn, and then relaunch app from stack - ActivityB is opened again instead ActivityA.
Please explain me why it happen and how to fix this issue. Thanks!
UPDATE
after onBackPressed in ActivityB, ActivityA is opened, and then i click onBackBtn instead HomeBtn, so app is closed. in this case after relaunch from stack ActivityB is opened.

When you press the home btn in ActivityB, Android calls the onPause() method on activity lifecycle, and in this moment your app is paused on activityB. It are not destroyed like you did overriding onBackPressed(). So when you relaunch your app again, the SO will be call onResume() on ActivityB that is in backstack.
To change this behavior, you have to override the onPause() method on finish the activity manually.

Related

Unable to fully close activity when using "singleTask" as launch mode

I'm trying to create a separate activity and use it to receive data from other applications. This SecondaryActivity is being launched through intent.action.SEND and android.intent.action.SEND_MULTIPLE in the manifest. I have also set it to use launchMode="singleTask" to avoid a duplicate app problem (if you keep selecting the app in the android share sheet and clicking back you can spin up multiple instances of the app).
launchMode="singleTask seems to work so far but I cannot get it to close even when adding finish() and finishAffinity() in onBackPressed(). When i look at the back stack, it says that SecondaryActivity is closed, but upon pressing the navigaton button, I can still see the activity.
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.TestProject">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondaryActivity"
android:launchMode="singleTask"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
My SecondActivity looks like this
class SecondaryActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_secondary)
}
override fun onBackPressed() {
finish()
finishAffinity()
}
}
This problem happens when the app is completely closed and is launched through sharing a file. I cannot get the SecondaryActivity to not show up in the navigation screen even after closing it by pressing the back button. adb says there are no activities in the stack but i still see it in the navigation.
This is called Recents screen which is a system-level UI that lists recently accessed activities and tasks even if the application has finished.
If you don't want to see the app in the recent apps after pressing back button, using finishAndRemoveTask
override fun onBackPressed() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAndRemoveTask()
} else {
finish()
}
}

Difference between launching app from recents and home screen

I have ActivityA as launcher activity.
From ActivityA I open -> ActivityB. I put the app in background.
When I open the app from recents the app is resumed with ActivityB.
When I open the app from homescreen, the app is resumed with ActivityA without calling onCreate(), just onResume().
Why is ActivityB cleared from stack when I open the app from homescreen, even if onCreate() from ActivityA is never called, and how to fix this?
Manifest file looks like this:
ActivityA:
<activity-alias
android:name=".Launcher"
android:label="#string/app_name"
android:targetActivity="path.ActivityA">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
<activity
android:name=".path.ActivityA"
android:launchMode="singleTask"
android:screenOrientation="sensorPortrait"
android:theme="#style/BlackIntroTheme"
android:windowSoftInputMode="adjustPan">
<nav-graph android:value="#navigation/graph1" />
<nav-graph android:value="#navigation/graph2" />
<nav-graph android:value="#navigation/graph3" />
<nav-graph android:value="#navigation/graph4" />
</activity>
ActivityB:
<activity
android:name=".path.ActivityB"
android:launchMode="singleTask"
android:screenOrientation="sensorPortrait"
android:windowSoftInputMode="adjustPan" />
this is how Activity stacking works, some nice example of all launchModes in HERE, more complex info in DOCs
in short - Activity with singleTask started (again) will clear all on-top-of-it Activities. you have your first MAIN Activity declared with this launchMode, so every icon click on devices launcher will clear your Activities stack. you can track this by overriding onNewIntent method. picking from recents just brings all your Activities stack to front, with last opened on top ofc.
consider removing launchMode (is this necessary line for you?) or set it as standard (default)
android:launchMode="standard"

How to open an Activity using deeplink in the same task as current Activity?

I have 2 activtity MainActitvity(launchMode: standard) and DeepLinkingActivity(launchMode: standard)
<activity
android:name=".feature.deepLink.DeepLinkActivity"
android:launchMode="standard">
<intent-filter
android:autoVerify="true"
tools:targetApi="m">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="${deepLinkURI}"
android:path="#string/path_prefix"
android:scheme="https" />
</intent-filter>
</activity>
<activity
android:name=".feature.main.MainActivity"
android:launchMode="standard"
android:windowSoftInputMode="adjustPan|stateAlwaysHidden"/>
When the MainActivity is presented, I click on a link that will open the DeepLinkActivity. From the doc
https://developer.android.com/guide/components/activities/tasks-and-back-stack#ManifestForTasks
The DeepLinkingActivity should be started in the same Task as MainActivity and placed on the top of that Task. It appears not, MainActity and DeepLinkingActivity now live in 2 separate Tasks (Pressing back on DeepLinkingActivity navigates me to the Launcher screen instead of MainActivity).
I did try to change the launchMode of DeepLinkingActivity to singleTask. It started DeepLinkingActivity in the same task MainActivity but it also cleared the back stack (There is no MainActivity to go back to)
So, how can I make DeeplinkingActivity placed on top of MainActivity in the same Task when I start it from a deep link.
put code in this method,
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
}

How to invoke method in Activity from another Activity without startActivityForResult()?

I have two activities. Activity1 contains TextView with HTML links. When user click any link - it launch Activity2 (so I cannot use startActivityForResult()). Then user make some actions in Activity2, click "Back" button and return to Activity1. At this moment I need to invoke method in Activity1 with information from Activity2. But how to do that? I need to use BroadcastReceiver?
For launching Activity2 I using this:
Manifest:
<activity android:name=".Activity2" >
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="myapp" />
</intent-filter>
</activity>
And all links in my TextView start with "myapp://".

Open only one activity, without the main activity

I have an application that has one service and 2 activities.One activity (the main one) is a preferences activity and the other one is a dialog themed activity. The service from time to time needs to open only the dialog themed activity (using FLAG_ACTIVITY_NEW_TASK).
The problem is that when the preferences activity is opened in background (for example the user pressed HOME key instead of BACK, so the activity is OnPause) and the service tries to open the dialog themed activity, also the main activity is opened (comes in foreground).
I don't want this. So, how can I open only the themed activity from the service, without the main activity pop up ?
Android Manifest .xml
<service android:name=".SimpleService"> </service>
<activity
android:name=".Preferences" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".popup_activity" android:theme="#android:style/Theme.Dialog" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="screenon.popup.activity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And from the service :
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addCategory("screenon.popup.activity");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
I believe you're looking for the android:launchMode attribute.
Alex , I believe that all you want is to display preferences activity just once & then it must die(or lets say finish()) .
In that case you can override onResume of the preferences activity
to finish your preferences activity after it is resumed after pause
#Override
public void onResume()
{
//if activity is resumed after onPause then only run it
this.finish(); //simply kill your activity if it is resumed after pause
}
EDIT-To know whether the activity was paused you need to override onPause().I think you can dig out the rest.
Hope it helps!

Categories

Resources