In fact, I am new to Android App Development. In my application, I have a couple of activities and I have provided my users with an exit option menu to be able to leave the application. But there is a problem. When they hit the Exit button, they are able to leave the application but when they enter the application for the second time, the page that they left off the last time will be launched.
Here comes my code:
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
switch (item.getItemId()) {
case 0 :
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
Toast.makeText(this, "Goodbye Dear", Toast.LENGTH_LONG).show();
break;
Android Activity has two methods onPause and onDestroy where you can do the necessary cleanup.
http://developer.android.com/reference/android/app/Activity.html
Instead of using finish(), use System.exit(0);.
You have to override onPause and/or onDestroy methods inside your activity and delete your view within these methods.
The problem in your code is that Intent.FLAG_ACTIVITY_NEW_TASK doesn't remove your current Task. Read more about it here: Task and Back Stack | Android Developers.
Try using Intent.FLAG_ACTIVITY_CLEAR_TOP. From the documentation we can see that this gives the desired behavior.
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.
Related
I have 2 Activities in my Android application - Activity A and Activity B.
When the user presses a button on Activity A, he is navigated to Activity B.
I want Activity A to close after going to the next activity and is completely removed from the activity stack.
I tried adding intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); , but this not work as Activity A was still accessible after pressing the back button.
I added finishAffinity(); , this worked, but while transitioning, the previous activity in the activity stacks gets visible and then it goes to Activity B.
Video
(here the application drawer is shown, and then it goes to Activity B) -
Code -
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this);
Intent i = new Intent(MainActivity.this, MainActivity2.class);
startActivity(i, options.toBundle());
finishAffinity();
Any fix so that the previous activity is not visible and activity is also closed ?
EDIT : I tried finish(), finishAfterTransition() and supportFinishAfterTransition() instead of finishAffinity() but still the previous screen is visible.
So I guess there's an issue with finishAfterTransition()
I solved it by adding android:noHistory="true" attribute to the activity (which has to be removed from the stack) in the manifest file solves the issue.
There is no need to use finish() in the java code after this change.
Method 2 -
Refer #Pratyay ' s answer for a way around.
you have to use finish but like this:
startActivity(Your Activity here)
then Finish()
if you do reverse you can see black screen for a short time do this way
#Override
public void onBackPressed() {
finishAffinity();
}
Use this function in Activity B, this will exit app on pressing back button. And don't use any finish(); or finishAffinity(); in Activity A. This will give a smooth transition
I have been spending lots of hours figuring the reason why top of the stack is not cleared yet.
Well I tried the following:
Intent intent = new Intent(ActionBarActivity.this, MainActivity.class);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
And it turned me to the MainActivity. Then when I try to press back button, the program does not exit, but instead it turns me to the first page of ActionBarActivity.
Let me be more specific:
In MainActivity I call ActionBarActivity. In the ActionBarActivity I have a search bar and I enter a query there and just print the value of the query.
If you think how it will work is a below:
MainActivity -> ActionBarActivity1 -> ActionBarActivity2 -> ActionBarActivity3 -> ..
In that ActionBarActivity I have also an option which brings me back to the MainActivity.
So as I said when I run application with the way above, it will bring me to the MainActivity.
Nice so far, but when I press the back button I expect it to exit, but instead it goes to ActionBarActivity1. I doubt the stack is not properly erased.
What should I do in this case. Thanks
I'm assuming you've seen this post: Android: Clear the back stack and it is not what you want
The FLAG_ACTIVITY_NEW_TASK is creating an new task stack. When you hit "back" that is the only activity in that stack, so Android goes to the previous task - which has the calling activity at the top.
If you remove that flag, then MainActivity is already in the task stack and is brought to the top. And "back" removes it and brings you back to the calling activity. So far, that is the expected Android behavior.
EDIT: Since you commented that you only have 2 activities, then one option is to "finish()" ActionBarActivity after it starts MainActivity like this:
startActivity(intentMainActivity);
finish();
To get the behavior you want with many activities or only in certain situations, you need to use SET_RESULT and finish the activities in the stack when you hit the button to go to the MainActivity. In other words, Android assumes you want to keep activities even when new ones start. But in this case you don't, so you have to tell the activity to destroy itself.
i.e. call setResult(DONE) and then use startActivityForResult and check for your "DONE" flag in the onActivityResult method.
then this:
MainActivity -> ActionBarActivity1 -> ActionBarActivity2 -> ActionBarActivity3
-> MainActivity
becomes:
MainActivity -> ActionBarActivity1 -> ActionBarActivity2 -> ActionBarActivity3
-> call "Done"
Destroy ActionBarActivity3
Destroy ActionBarActivity2
Destroy ActionBarActivity1
MainActivity remains
For example, in ActionBarActivity2:
startActivityForResult(intentActionBarActivity3, ActionBarActivity2_ID);
Then in ActionBarActivity3:
public void exitButton(View view) {
setResult(MY_DONE_FLAG);
finish();
}
And back in ActionBarActivity2:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ActionBarActivity2_ID && resultCode == MY_DONE_FLAG) {
setResult(MY_DONE_FLAG, data);
finish();
}
}
And so on with all activities that you want to "close" when that button is pressed.
try
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
finish();
insetead of
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
and you should also use it with every intent which leads you to ActionBarActivity.
i mean if you are going back to ActionBarActivity form ActionBarActivity1 then you use it with intent.
then create intent for MainActivity in your so called ActionBarActivity.
Intent intent = new Intent(ActionBarActivity.this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
Good luck !!!
the following sheet represents the working flow in the application this question is about.
I ran into problems with OutOfMemory Errors, mostly because users were able to switch from activity B to activity D multiple times (They are showing different content for every attempt), without the previous activity being destroyed. This led into a very large backstack resulting in an OutOfMemory error.
To avoid this, I followed the recommendation to add parent activites to the manifest and create new backstacks with the TaskStackBuilder class:
void openDFromB()
{
Intent i = new Intent(this, ActivityD.class);
TaskStackBuilder.create(this)
.addParentStack(ActivityD.class)
.addNextIntent(i)
.startActivities();
}
If a user now switches from activity B to D, MainMenu, A and B are destroyed and a new Backstack (MainMenu, C, D) is created.
This solves my memory problems for api level greater 10, but unfortunately the TaskStackBuilder does not create backstacks for devices pre api 11.
Any idea what to do in order to avoid users stacking infinite amounts of activities prior api 11? Is this even possible or should I try to free as many resources as possible in onPause to gain a maximum amount of stacked activities before OoM?
thanks in advance!
Try this-
Intent intent = new Intent(getApplicationContext(),yourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Another solution is-
Setting android:noHistory="true" on the activity in your manifest file will remove an activity from the stack whenever it is navigated away from.
But the most appropriate way is to call finish() method whenever you start new activity like in the following sample code-
Intent intent = new Intent(this, yourActivity.class);
startActivity(intent);
finish();
You can also create custom Broadcast receiver and register it in every activity which can be fired on event of your choice. For more help you can check this link.
Zabri answer is good, but i would propose another probably is better:
You dont close every activity, but when you are opening a new activity that has been open before, you tell the system that it can clear the way back and reopen that one, of course with a new intent and all the new data that you need.
So, if you do A - B - D - B - D - B, instead of having that big stack,you will have
A - B
A - B - D
A - B
A - B - D
A - B
So, if you do C - D - B - D - B - D, your stack will be
C - D
C - D - B
C - D
C - D - B
C - D
and so on.
In this way, i think the stack actually reflects what the user can have in mind, and also navigation is very logic, you don't even need to captre back button to have the navigation making sense, (of course you can do it if you want a more specific user experience)
The code to achieve this, is:
create a function that receives a class (something like ActivityD.class), there you create an intent, with the flags Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_NEW_TASK and then when you need to open an activity, just call this function. You dont care about if the activity is in the stack or not. If it isnt,it is created normally.
protected void startActivity(Class<?> clase) {
final Intent i = new Intent(this, clase);
int flags = Intent.FLAG_ACTIVITY_CLEAR_TOP;
flags |= Intent.FLAG_ACTIVITY_NEW_TASK;
i.setFlags(flags);
startActivity(i);
}
startActivity(ActivityD.class);
May be your application having memory leaks and due to that older activities not getting reclaim by the GC and eventually getting heap size increase every-time activity switch occurs.
How to find leaks?
Please watch: http://www.youtube.com/watch?v=_CruQY55HOk
References:
http://android-developers.blogspot.in/2011/03/memory-analysis-for-android.html.
http://kohlerm.blogspot.in/2009/07/eclipse-memory-analyzer-10-useful.html
I don't know how it works with the Navigation Drawer, but I was creating an Android application some time ago which started with a loading screen and then moved to the main activity of the app. Since I didn't need/want the user ever to go back to the loading screen, I just called finish() before moving to the main activity. Like this:
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
And then, when the user pressed the back button from the main activity, they didn't get to the loading activity, but to wherever they were even before that.
So you could also try to do this:
void openDFromB()
{
Intent i = new Intent(this, ActivityD.class);
startActivity(i);
finish();
}
As I said, I have never implemented a Navigation Drawer, but something tells me that doing this might break its whole behaviour. Also, calling finish() in an activity is such a basic concept that I would be surprised if you hadn't tried it already. :) But still, I am posting it as a shot in the dark, just in case it helps you. Good luck. :)
Hello you can try to add the following statement in your manifest file under application tag:
android:largeHeap="true"
Also make sure your android:targetSdkVersion is 14.
#Override
public void onClick(View view) {
// Launching News Feed Screen
Intent i = new Intent(getApplicationContext(), Profile.class);
startActivity(i);
}
});
what is the difference of using this code and what difference does it do on the program compared to this doe
Intent i = new Intent(CurrentActivityName.this, NextActivityName.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
First one uses getApplicationContext() to launch the intent.
Application context is attached to the application's life-cycle and will always be same throughout the life of application. So if you are using Toast, you can use application context or even activity context (both) because a toast can be raised from anywhere with in your application and is not attached to a window.
Second one uses the Activity context.
Activity context is attached to the Activity's life-cycle and can be destroyed if the activity's onDestroy is raised. If you want to launch a new activity, you must need to use activity's context in its Intent so that the new launching activity is connected to the current activity (in terms of activity stack).
So, Whenever you need to manipulate Views then go for Activity-Context, else Application-Context would be enough.
Source: this answer at difference and when to use getApplication(), getApplicationContext(), getBaseContext() and someClass.this question.
Also, reading some of above links would help:
What's the difference between the various methods to get a Context?
getApplicationContext(), getBaseContext(), getApplication(), getParent()
OK,I'm new at this forum, so don't blame me for putting this in the wrong tags,not putting something in,eg.
I want to learn how to create a shortcut(I did that by Googling) and link it to an activity (In this case, com.android.mms.ui.ComposeMessageActivity)
I tried doing it, but it only showed me a toast saying "Application not installed" and I'm pretty sure it is.
It would be better if you can display a "complete action with another application" dialog.
If I assumed your question correctly, you mean a button or something within an activity that leads to another activity, that being -- "com.android.mms.ui.ComposeMessageActivity"
if your activity that you want to link to is in another application-- then
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.mine", "com.android.mms.ui.ComposeMessageActivity"));
startActivity(intent);
if it is within the same application, then
Intent intent = new Intent(this, ComposeMessageActivity.class);
startActivity(intent);
//optional add this to your manifest to finish the current loading activity so
//as to not keep it in the activity stack
//<activity android:name="yourActivity" android:noHistory="true" ... />
EDIT If you mean a shortcut on a homescreen, then I would create a tiny application that only has one activity which uses the above method to link to a different application. Then I would drag that application to the home screen, and boom. If there's a better way, then please feel free to correct me