I have a common menu on my app with icons. Clicking an icon will start an Activity. Is there a way to know if an activity is already running and prevent it from starting multiple times (or from multiple entries)? Also can I bring an activity that is in onPause state to the front?
Use this:
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
while starting Activity.
from documentation:
If set in an Intent passed to Context.startActivity(), this flag will
cause the launched activity to be brought to the front of its task's
history stack if it is already running.
In your activity declaration in Manifest file, add the tag android:launchMode="singleInstance"
I got it perfectly working by doing the following.
In the caller activity or service (even from another application)
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(APP_PACKAGE_NAME);
//the previous line can be replaced by the normal Intent that has the activity name Intent launchIntent = new Intent(ActivityA.this, ActivityB.class);
launchIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(launchIntent);
and in the manifest of the receiver activity (the I want to prevent opening twice)
<activity android:name=".MainActivity"
android:launchMode="singleTask"
>
This works for me :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
from official documentation
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
also, you can use FLAG_ACTIVITY_NEW_TASK with it.
then the code will be :
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
Just use
Intent i = new Intent(ActivityA.this, ActivityB.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
create an instance of your activity which you dont want to start multiple times like
Class ExampleA extends Activity {
public static Activity classAinstance = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
classAinstance = this;
}
}
Now where ever u want to crosscheck i mean prevent it from starting multiple times, check like this
if(ExampleA.classAinstance == null) {
"Then only start your activity"
}
please add this in menifest file
<activity
android:name=".ui.modules.profile.activity.EditProfileActivity"
android:launchMode="singleTask" // <<this is Important line
/>
Related
I am launching an activity from a Service using the normal pattern:
Intent i = new Intent(getApplicationContext(), MyActivity.class);
startActivity(i);
I want to animate that launch e.g. slide in from left.
From an Activity, you can use Activity.overridePendingTransition().
Is there a way to animate an activity launch from a Service?
I went with the workaround of placing my own activity into the launch process.
My Service launches my HelperActivity with extras in the intent identifying the task I wish to launch/bring to front.
HelperActivity launches the actual task in onCreate(), animating the change with overridePendingTransition(). Then calls finish() in order to remain hidden.
Obviously HelperActivity needs to remain hidden from the backstack, so the manifest reflects this.
There are also security concerns to this naive method - see related post by Commonsware:
Beware Accidental APIs
This type of activity should be as secure as possible. For my demo version, I'm happy to just set android:exported="false".
Manifest Code:
<activity
android:name=".SwitchAnimationHelperActivity"
android:excludeFromRecents="true"
android:exported="false"
android:noHistory="true" >
</activity>
HelperActivity Code:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
String componentName = getIntent().getStringExtra("TASK_ID_API");
Intent newTask = new Intent(Intent.ACTION_MAIN);
newTask.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newTask.setComponent(ComponentName.unflattenFromString(componentName));
startActivity(newTask);
overridePendingTransition(R.anim.anim_zoom_in, R.anim.anim_slide_out_left);
// job is done
finish();
}
So there it is - one way to animate the launch of a task from a Service.
I have an activity (A) that is declared in AndroidManifest.xml:
<activity
android:name="A"
android:launchMode="singleTask">
</activity>
I want to from other activity in application start A and override android:launchMode="singleTask" to android:launchMode="singleTop"
How can i do that? Thanks in advance.
What worked for me is to finish the current activity and post start activity to the activity ui thread.
// get rid of this activity instance and start a new instance one
finish();
final Intent intent = new Intent(this, MyActivity.class);
runOnUiThread(new Runnable() {
#Override
public void run() {
startActivity(intent);
}
});
See FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_MULTIPLE_TASK at http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK
If you want to be able to start that Activity in an existing task, then you need to change the launchMode back to standard or singleTop. If you set the launchMode to singleTask then you are telling Android that you do not want your Activity to be launched into an existing task. Being able to override that would be counter-productive. That's the whole point of this launchMode!
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)
}
}
I have need to show autorizationa activity if user not autorized.
I have use Launcher activity (has nohistory flag) with next code:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (Autorization.isAutorized())
{
Intent newIntent = new Intent(this, MainActivity.class);
// add some flags????
startActivity(newIntent);
}
else startActivity(new Intent(this, AutorizationActivity.class));
}
When autorization are complete, AutorizationActivity starts Launcher with FLAG_ACTIVITY_CLEAR_TOP and then Launcher starts MainActivity, but I have some trubles with backstack. By pressing back in MainActivity android shows AutorizationActivity again instead to hide task.
What flags I must use to prevent go back to AutorizationActivity from MainActivity?
There are several ways to do this , the easiest would be to use the AndroidManifest.xml file. Just add android:noHistory = "true" in the authorization activty.
Also have a look at the following question : removing an activity from the history stack
try setting flags for AuthorizationActivity in Manifest something like this.... right now your flag applies only to MainActivity and not the Current Activity.. so set in Manifest instead..
Is it possible to start an activity on the stack, clearing the entire history before it?
The situation
I have an activity stack that either goes A->B->C or B->C (screen A selects the users token, but many users only have a single token).
In screen C the user may take an action which makes screen B invalid, so the application wants to take them to screen A, regardless of whether it is already in the stack. Screen A should then be the only item on the stack in my application.
Notes
There are many other similar questions, but I haven't found anything that answers this exact question. I tried calling getParent().finish() - this always results in a null pointer exception. FLAG_ACTIVITY_CLEAR_TOP only works if the activity is already on the stack.
In API level 11 a new Intent Flag was added just for this: Intent.FLAG_ACTIVITY_CLEAR_TASK
Just to clarify, use this:
Java
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Kotlin
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
Unfortunately for API lvl <= 10, I haven't yet found a clean solution to this.
The "DontHackAndroidLikeThis" solution is indeed pure hackery. You should not do that. :)
Edit:
As per #Ben Pearson's comment, for API <=10 now one can use IntentCompat class for the same. One can use IntentCompat.FLAG_ACTIVITY_CLEAR_TASK flag to clear task. So you can support pre API level 11 as well.
Case 1:Only two activity A and B:
Here Activity flow is A->B .On clicking backbutton from B we need to close the application then while starting Activity B from A just call finish() this will prevent android from storing Activity A in to the Backstack.eg for activity A is Loding/Splash screen of application.
Intent newIntent = new Intent(A.this, B.class);
startActivity(newIntent);
finish();
Case 2:More than two activitiy:
If there is a flow like A->B->C->D->B and on clicking back button in Activity B while coming from Activity D.In that case we should use.
Intent newIntent = new Intent(D.this,B.class);
newIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(newIntent);
Here Activity B will be started from the backstack rather than a new instance because of Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_NEW_TASK clears the stack and makes it the top one.So when we press back button the whole application will be terminated.
With Android's Newer Version >= API 16 use finishAffinity()
approach is suitable for >= API 16.
Intent mIntent = new Intent(mContext,MainActivity.class);
finishAffinity();
startActivity(mIntent);
Its is same as starting new Activity, and clear all stack.
OR Restart to MainActivity/FirstActivity.
I spent a few hours on this too ... and agree that FLAG_ACTIVITY_CLEAR_TOP sounds like what you'd want: clear the entire stack, except for the activity being launched, so the Back button exits the application. Yet as Mike Repass mentioned, FLAG_ACTIVITY_CLEAR_TOP only works when the activity you're launching is already in the stack; when the activity's not there, the flag doesn't do anything.
What to do? Put the activity being launching in the stack with FLAG_ACTIVITY_NEW_TASK, which makes that activity the start of a new task on the history stack. Then add the FLAG_ACTIVITY_CLEAR_TOP flag.
Now, when FLAG_ACTIVITY_CLEAR_TOP goes to find the new activity in the stack, it'll be there and be pulled up before everything else is cleared.
Here's my logout function; the View parameter is the button to which the function's attached.
public void onLogoutClick(final View view) {
Intent i = new Intent(this, Splash.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
}
Immediately after you start a new activity, using startActivity, make sure you call finish() so that the current activity is not stacked behind the new one.
You shouldn't change the stack. Android back button should work as in a web browser.
I can think of a way to do it, but it's quite a hack.
Make your Activities singleTask by adding it to the AndroidManifest
Example:
<activity android:name=".activities.A"
android:label="#string/A_title"
android:launchMode="singleTask"/>
<activity android:name=".activities.B"
android:label="#string/B_title"
android:launchMode="singleTask"/>
Extend Application which will hold the logic of where to go.
Example:
public class DontHackAndroidLikeThis extends Application {
private Stack<Activity> classes = new Stack<Activity>();
public Activity getBackActivity() {
return classes.pop();
}
public void addBackActivity(Activity activity) {
classes.push(activity);
}
}
From A to B:
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(A.class);
startActivity(this, B.class);
From B to C:
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.addBackActivity(B.class);
startActivity(this, C.class);
In C:
If ( shouldNotGoBackToB() ) {
DontHackAndroidLikeThis app = (DontHackAndroidLikeThis) getApplication();
app.pop();
}
and handle the back button to pop() from the stack.
Once again, you shouldn't do this :)
Advanced Reuseable Kotlin:
You can set the flag directly using setter method. In Kotlin or is the replacement for the Java bitwise or |.
intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
If you plan to use this regularly, create an Intent extension function
fun Intent.clearStack() {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
You can then directly call this function before starting the intent
intent.clearStack()
If you need the option to add additional flags in other situations, add an optional param to the extension function.
fun Intent.clearStack(additionalFlags: Int = 0) {
flags = additionalFlags or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
Try below code,
Intent intent = new Intent(ManageProfileActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_CLEAR_TASK|
Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Try this:
Intent logout_intent = new Intent(DashboardActivity.this, LoginActivity.class);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
logout_intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(logout_intent);
finish();
For me none of the above methods not work.
Just do this to clear all previous activity:
finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)
Intent i = new Intent(MainPoliticalLogin.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
In Java: -
startActivity(new Intent(getApplicationContext(),ChooseServiceActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
Sometimes your android emulator might fails to connect eclipse DDMS tool and ask for adb to start manually. In that case you can start or stop the adb using the command prompt.
I found too simple hack just do this add new element in AndroidManifest as:-
<activity android:name=".activityName"
android:label="#string/app_name"
android:noHistory="true"/>
the android:noHistory will clear your unwanted activity from Stack.