Preventing multiple async startActivity calls in Android - android

I have a listView with items that, when clicked, create an intent and start an activity with that intent using the startActivity method.
The issue is that items can be pressed multiple times while the asynchronous call to startActivity is made, which will open multiple activities one on top of each other.
Using the FLAG_ACTIVITY_SINGLE_TOP doesn't solve it either, perhaps because the activity being opened from intent 1 hasn't been placed at the top of the stack when intent 2 fires?
How can I handle this?
Manifest:
<activity
android:name=".Activity2"
android:parentActivityName=".Activity1"
android:launchMode="singleTask"/>
Intent code:
Intent intent = new Intent(Activity1.this, Activity2.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("a", "b");
startActivityForResult(intent, REQUEST_CODE);

In Your Manifest file inside activity tag add android:launchMode="singleTask"
<activity
android:name="YourActivity"
android:launchMode="singleTask"/>

Solved with the FLAG_ACTIVITY_REORDER_TO_FRONT intent flag instead of FLAG_ACTIVITY_SINGLE_TOP

Related

Single android application with two tasks and its navigation

I am developing a calling application. My HomeActivity is a singleTask activity. My call activity is also a singleTask activity.
From HomeActivity a call is initiated. At this moment, there are two tasks for my application as they both are singleTask. In call screen I have a button to reach my HomeActivity.
When I press the home button in my call screen and navigate back, my call activity is destroyed. But it should not get destroyed. It should remain.
When I press home button in call screen I do the below.
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setClass(this.getActivity(), MyHomeActivity.class);
startActivity(intent);
My manifest declaration:
<activity
android:name=".XXX.MyHomeActivity"
android:label="#string/app_name"
android:alwaysRetainTaskState="true"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustNothing"
android:theme="#style/MyTheme"
>
</activity>
<activity
android:name=".XXX.MyCallActivity"
android:label="#string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="#style/MyTheme"
android:windowSoftInputMode="adjustResize">
Inflating HomeActivity from CallActivity:
Intent intent = new Intent();
intent.setClass(this.getActivity(), HomeActivity.class);
startActivity(intent);
Inflating CallActivity:
Intent intent = new Intent();
intent.setClass(this, CallActivity.class);
startActivity(intent);
Can anyone help me with the navigation parameters to use to achieve this?
In order to have 2 tasks, you need to make sure that the root Activity of the tasks have different taskAffinity, otherwise Android will put both in the same task. The default taskAffinity is the name of your package.
Add android:taskAffinity="" to one of the <activity> declarations.
According to the documentation using FLAG_ACTIVITY_CLEAR_TASK will do the following:
this flag will cause any existing task that would be associated with
the activity to be cleared before the activity is started. That is,
the activity becomes the new root of an otherwise empty task, and any
old activities are finished.
So if want your CallActivity to stay in the back stack you can simply do this:
Intent intent = new Intent();
intent.setClass(this.getActivity(), MyHomeActivity.class);
startActivity(intent);

Start another app activity removing it from recents list

I'm trying to start an activity of an app (that is not mine and which code I don't know and/or can't edit), from my app.
What I want to do, is that after starting that activity (let's call it OtherAppActivity) neither my activity (let's call it MyAppActivity) nor OtherAppActivity remain shown in the recent apps list.
My current code:
AndroidManifest.xml
<activity
android:name=".activities.Launch"
android:noHistory="true"
android:exported="true"
android:excludeFromRecents="true"
android:launchMode="singleInstance"
android:theme="#style/EmptyActivity">
MyAppActivity.java
// Intent to launch OtherAppActivity
Intent intent = new Intent();
intent.setClassName(PKG, ACTIVITY);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivityForResult(intent, 88);
I have done a lot of search, but none of the answers I have found, have worked for me.
I hope you understand what I want to do, and can help me. Thanks in advance.
For your app, try adding android:excludeFromRecents="true" to your application tag in the manifest file and for the intent try setting this flag:
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

startActivity(intent) it doesn't working ? when my DemoActivity use android:launchMode="singleTask",

This is my AndroidManifest.xml
<activity android:name=".ui.activity.ERPWebContainerActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="#style/Theme.Eallcn.Fullscreen">
</activity>
When I step into a new Demo1Activity, I deal with some data, Step to Demo2activity from Demo1Activity.
when I in the Demo2activity activity. I use this method: startActivity() doesn't work.
Intent intent = new Intent(this, ERPWebContainerActivity.class);
intent.putExtra("waitUploadImageLists", waitUploadImageLists);
startActivity(intent);
finish();
You can use android:launchMode="singleInstance"which work almost same.
but still if your requirement is to use singleTask only then you can use that in this way:
android:launchMode="singleInstance"
Just remove the launchMode="singleTask" and set FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP flag whenever call an intent to your activity
You can override this method, you can get the Intent data!
why ? because the activity didn't finish, When i startActivity form Demo2activit, It does't go to onCreate method!
you can get the reslove way: you can see Android: lunchMode
enter link description here
Try in this order.
finish();
Intent intent = new Intent(/*intent parameters, but as I can't copy and paste it from a picture then... */);
startActivity(intent);

Could an activity with single task flag be cleared via clear top?

Assume that I have a launcher activity A which has singleTask launch mode. Now imagine that A starts Activity B like;
Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, REQ_ACCOUNT_ACTIVITY);
In this case it seems like A's not destroyed. I wonder if it's correct or did I something wrong?
You can achieve this by using below attribute in AndroidMenifest file
android:finishOnTaskLaunch="true"
<application
...
>
<activity
android:finishOnTaskLaunch="true"
android:launchMode="singleTask"
...>
</activity>
</application>
If you not want to kept new activity in the history stack. Use below one_
FLAG_ACTIVITY_NO_HISTORY
//Actvity B is not in BackStack if we set FLAG_ACTIVITY_NO_HISTORY flag
Intent intent = new Intent(this, B.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivityForResult(intent, REQ_ACCOUNT_ACTIVITY);
As soon as the user navigates away from Activity B, the activity is finished. This may also be set with the noHistory attribute.
For more -> Tasks and Back Stack
It's been a while but I came across my own question when I was wandering over here.
The activity A was not getting deleted because the flags are set for the activity B. And when I call this code, there's no such activity called B in the task stack already. So effectively, nothing to clear on top of B.
Hope this helps.

Android remove Activity from back stack

Okay so I'm kind of stumped on what to do with this. So I have the MainActivity, and from there an Activity can be launched to DegreePlanActivity, and from there another Activity can be launched to EditDegreePlan. I've got EditDegreePlan set to noHistory in the AndroidManifest. The problem is after they save the EditDegreePlan it launches an Activity to DegreePlan. So if the user presses Back they have to press it twice to get to MainActivity again. I want to get rid of that so they only have to press it once. I'm stumped on how to do this though.
If I set DegreePlanActivity to noHistory then they couldn't press Back to it while in EditDegreePlan.
I've tried overriding onBackPressed method and launching an intent to MainActivity. The problem then is that they have to press Back multiple times to exit the app then.
What should I do?
FLAG_ACTIVITY_CLEAR_TOP clears your Activity stack , you can use the code below:
Intent intent = new Intent(this, Activity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Remember that this flag clears just Intermediate Activities , for example if you have A,B,C in your Back Stack then going from C Activity to D with this flag this does not clear Back Stack and the Stack would be A,B,C,D but if you go from Activity D to Activity A with this flag , B,C,D Activities will pop up from the stack and you will have just A in the Back Stack .
To remove activity from back stack inside manifest add android:noHistory="true" to your activity inside the manifest file.
See sample below.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.activity"
android:versionCode="1"
android:versionName="1.0">
<application android:name="MyApp" android:label="My Application">
<activity android:name=".LoginActivity"
android:noHistory="true"> //add this line to your activity inside manifest
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
simple solution for API >= 15 to API 23
user activity name in intent.
Intent nextScreen = new Intent(currentActivity.this, MainActivity.class);
nextScreen.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(nextScreen);
ActivityCompat.finishAffinity(currentActivity.this);
I would suggest that you use startActivityForResult(), instead of simply startActivity(), when you launch the EditDegreePlan-Activity, as described in the Android tutorials.
In the EditDegreePlan-Activity you then call
setResult(RESULT_OK);
finish();
If you don't expect any data from the EditDegreePlan-Activity, then you don't necessarily have to implement the onActivityResult.
It seems, that you will get the desired behavior if you do not specify any flags at all. The back button would just do the right thing. To get an activity closed from within your code use the finish() method it has the same effect as the user pressing the back button. So you will automatically arrive at DegreePlan when you finish the EditDegreePlan, no need to call any Intents either.
You can call finish before you start your new activity. This will remove the current activity from the stack, so when you press back button from the next activity, the first activity will not be called from the stack history.
Intent i = new Intent(MainActivity.this, NextActivity.class);
finish();
startActivity(i);
Here is your flow:
MainActivity --> DegreePlanActivty --> EditDegreePlan--> DegreePlan --> MainActivty
Override these method inside your "DegreePlan"
public void onBackPressed() {
super.onBackPressed();
Intent goToMainActivity = new Intent(getApplicationContext(), MainActivity.class);
goToMainActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // Will clear out your activity history stack till now
startActivity(goToMainActivity);
}
use this to clear the stack :
menuIntent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent intent = new Intent(getContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
You can add flags as follows and start Activity, try below code
Intent i = new Intent(activity, Payment.class);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(i);
This code should help you out: It is in Kotlin
private fun verifyIfUserIsLoggedIn(){
val uid = FirebaseAuth.getInstance().uid
if(uid== null){
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK.or(Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
}
}

Categories

Resources