Before you tell me that this question has already been asked, let me tell you that none of those questions have an answer that suits me. I have a main Activity for my app. Before it runs, I have a splash screen Activity. If I call finish(), the program returns to my splash screen. I do not want this. Do not tell me to use finish(). I have heard that it is bad practice to not let Android close the app on its own. I know what I am doing...probably....
I want to be able to completely close the application from the second activity. Does anyone know of a way I can do this?
when you want to close your application, you can call
finishAffinity();
or
if you want close it in background also you should write,
android:excludeFromRecents="true"
in AndroidManifest :
<activity
android:name="com.smart.remote.main.SplashActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Use finish() in your splash screen just before you create your second activity, then use finish() is the second activity: that will not bring back the splash screen.
Executing finish() on the splash activity is one solution, but two alternative methods are:
Start the splash activity with android:noHistory="true" in its manifest entry.
Launch the secondary activity with the Intent flag FLAG_ACTIVITY_CLEAR_TOP.
My preference would be the first, as users are unlikely to want to ever see the splash screen in the history stack (or at all, for that matter, but that's a different discussion).
finishAffinity();
This is simply exit from the app
Calling finish() at any Activity will go through its life cycle to destroy it. For sure destroying the fragment will remove it from the back stack.
So, you have to call finish(); method from your splash activity first, then start the MainActivity using intent as following
finish();
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
Yoi can also solve this problem by overriding the method OnBackPressed with an empty one without calling Super.onBackPressed ();
Even if you don't want it, I'm sorry to tell you that the only way of exiting cleanly is using finish(). If you're having some problems closing Activities in the background, there's another solution for it, check this link.
Basically there's no one-click or all-at-once way of accomplishing this, and don't use System.exit(), it's a bad practice, as you may read here.
Finish is the way to go. You can actually close your SplashScreen activity once it is no longer needed. Ie. after SplashScreen is no longer needed, just call finish on it, after starting your main activity.
Also, its not that finish() will close your application, even after calling it process for your app will still exists, all your static variables will be still valid, of course until android decides to kill your app which can happen long after your finish call.
EDIT: just to be clear, this is not the right way of exiting from an application. Use at your own risk. The OP was asking for A way of exiting the application, even though it was not the correct way.
System.exit(0)
Is this what you're looking for?
I totally agree with you that finish() is somehow not practical but anyways you can use it simply and all will be "kosher" with best practices I suppose.
Here is a short tutorial for you to handle "Exit" from any other activity in your app:
I assume that splash screen is the first activity in your app.
If you also have a main/home screen in your app then finish the splash activity right after the main/home has been called with Intent from your Splash activity with e.g.
startActivity(new Intent(getApplication(), Home.class));
Splash.this.finish();}After doing so, follow the step 2. but instead of overriding the onResume in splash screen override it in the Home/Main screen.
2. If your user needs access to the splash screen later, do not finish() your splash screen but override its onResume method as follows:
#Override
protected void onResume() {
super.onResume();
try {
Intent i = getIntent();
Boolean isExit = i.getBooleanExtra("isExitAction",false);
if(isExit){
this.finish();
}
}
catch (Exception e){}
}
3. In the activity from which you want to close the application, use the following code to exit where it suits you the most. Do not forget to substitute for Home.class depending which is your first unfinished activity.
Intent i = new Intent(this, Home.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("isExitAction", true);
startActivity(i);
WHAT IT DOES: If you press a button from your 5th activity which fires the code in the 3rd step it finishes all previous activities 4,3,2 and "redirects" you to activity 1, which is your Home (or Splash).
After the redirection, the onResume() is called, and it finishes the last remaining activity. The application reaches this.finish() only if isExitAction is true
Related
Currently, I have an Activity, which is used to configure home widget. It is shown during
When user place the home widget on desktop for the 1st time.
Or, when user tapped on the already shown home widget.
This is the Manifest for the Activity.
<activity android:name="com.xxx.widget.NoteListAppWidgetConfigureFragmentActivity"
android:taskAffinity="com.xxx.launcher"
android:windowSoftInputMode="stateAlwaysHidden" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
We specific android:taskAffinity explicitly, as we do not want this configuration activity, interference with our main app flow. Hence, We want this activity to be launched at separate task stack, by using android:taskAffinity.
When user "quit" the configuration Activity, we would like the "com.xxx.launcher" task to be cleared off completely.
Reason is that, without clearing the task, user can always check the recent task list, re-launch the old NoteListAppWidgetConfigureFragmentActivity again and then overwrite current widget settings with old settings. This is an unwanted behaviour.
Currently, there are 2 ways for user to "quit" the NoteListAppWidgetConfigureFragmentActivity
Pressing a Button control of the activity.
Pressing system back button.
Pressing a Button control
We notice by executing finishAndRemoveTask when the Button control pressed, we can clear off the task.
Pressing system back button
We cannot figure out a way to clear off task stack. We even try the following code, but it does NOT work.
#Override
public void onPause() {
super.onPause();
if (isFinishing()) {
this.finishAndRemoveTask();
}
}
We do not want to use android:noHistory="true", because it causes onActivityResult malfunction. We can no longer perform startActivityForResult in NoteListAppWidgetConfigureFragmentActivity
Reference: https://developer.android.com/guide/topics/manifest/activity-element.html
A value of "true" means that the activity will not leave a historical
trace. It will not remain in the activity stack for the task, so the
user will not be able to return to it. In this case,
onActivityResult() is never called if you start another activity for a
result from this activity.
Do you have an idea, how we can prevent Activity from staying in the task stack after "quit", without using android:noHistory?
I am developing an Android app in which I want to check if the user has minimized the application or just come from another activity.
In detail, if the user have started another app, went to the home screen or locked the screen, I want to show the activity where the user will enter the password to access the app. But where or how to check this exactly?
https://developer.android.com/guide/components/activities/activity-lifecycle.html
I was trying onResume() but according to documentation onResume() can be fired if the user’s navigating to another activity and coming back.
I'm not very clear on what you are trying to achieve.
The life cycle diagram is quite clear if you are wondering which lifecycle method it would hit when something happens.
Basically, it's the same to minimise the app and go to another activity. But if you are referring to coming from another activity in your own app, you can distinguish your own activity by adding extra information to the intent you use.
Basically, it's like this:
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra(key,value);
startActivity(intent);
And in your SecondActivity, you can always retrieve that data like this:
Bundle bundle = getIntent().getExtras();
if ( bundle != null && bundle.containsKey(key) ) {
value = bundle.getInt(key); // not nessecarily getInt(), you should use according to your value type
// use the value to tell if it is from your own app
} else {
// it is not from your own app
}
You can use this mechanism combined with the lifecycle methods. For example, if you use the latter code in your onCreate() method, then whenever the Activity is created, if will check who creates it, which sounds like your what you might want.
As soon as your activity becomes visible it will call OnStart() and as soon as it is ready for the interaction(such as touch ,click etc event). it calls onResume, at this stage your app is running and it is completely in foreground. When your activity start another activity or a dialog box then it calls onPause it means activity is visible but user can not interact with the Activity UI. in case we start another Activity which completely hides the previous activity then its onStop method is called
onPause: Called when another activity comes into the foreground.
onStop: Called when that other activity is completely visible.
onResume: Called when your activity is navigated back to from the onPause state.
Maybe your app was already in the onStop state, so then it would call onRestart.
I am writing a math app for little kids to learn maths. It first prompts the user to select what kind of questions they want (MainActivity), and then it shows a bunch of questions (QuestionsActivity). After answering 10 questions, it tells you which question(s) did you answer correctly and which you didn't (ResultsActivity).
I know that Android puts all the activities on a stack. In my case, it would look like this:
ResultsActivity
QuestionsActivity
MainActivity
And when you call finish, an activity is popped from the stack. I want there to be a back to main menu button in the ResultsActivity to go back to the MainActivity. However, if I call finish in the ResultsActivity, the user would see QuestionsActivity! So how am I going to call finish on the both activities?
Two options:
Call finish() in QuestionsActivity after you make the call to start the ResultsActivity. This will remove it from the stack so that pressing back from ResultsActivity returns to MainActivity.
Use Intent.FLAG_ACTIVITY_CLEAR_TOP in the intent to go back to MainActivity. This will clear all activities that are on top of it.
You can clear your stack by simple starting your MainActivity again and clearing the stack with the following flags:
final Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
I am executing maswebview class and I would like to finish only this activity. I tried maswebview.this.finish() but when executed, app is been closed. Then if I set a new view for the tab content, it is loaded properly and webviewmas dissapears but just for a while, then appears again fitting fullscreen. How to finish maswebview completely? ThanK you
public void onClick(View arg0)
{
/*
Intent intent = getIntent();
intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
startActivityForResult(intent, 1);
Intent intentmas = new Intent (maswebview.this, mas.class);
intentmas.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intentmas.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intentmas.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentmas.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
View vista = getLocalActivityManager().startActivity("maswb", intentmas).getDecorView();
setContentView(vista); */
maswebview.this.finish();
Do you have any other activities of your app in the stack by the time you call finish()? If you don't, you'll want to start the desired activity instead of finishing the current one.
But actually it seems to me that you're trying to accomplish something that can be done simpler. Can you provide more info on the task at hand and your app structure you're trying to go about it with?
From what you said, it seems like you have tabbed UI and you're trying to show a webview in one of the tabs, then hide it.
First, I don't see why you want the webview in a separate activity. Seems to me you could just have it in layout of one of the tabs and just call setVisibility(GONE) to hide it.
Second - and this is important - looks like you're trying to implement tabs the old way - TabWidget, TabHost, etc. Since Honeycomb has been released, there's much more convenient way to implement tabbed UI - Action Bar Tabs and Fragments - that approach is much more convenient and will render your webview problems obsolete: there's a thing called WebViewFragment which is basically a WebView but smarter - it will handle its own lifecycle with minimum effort required from you (i.e. pause when removed, resume when added). It will take some effort to study up on Fragments, but it's well worth it. You can get Fragments API for pre-Honeycomb android sdks as a static library - it's called android-support-v4 and you can download it in Android SDK Manager.
Are you calling "maswebview.this.finish();" before the new Activity is started?
Also if you want to just start this new activity without having the old activity in existence then you can add android:nohistory="true" to your manifest.xml. This will cause the current activity to be the only activity in the queue.
See HERE
You need to provide a little more information for us to better understand what exactly is going on.
I hope this helps.
Try following code
#Override
public void onBackPressed() {
if(childView != null && parentLayout.getChildCount()==2){
childView.stopLoading();
parentLayout.removeViewAt(parentLayout.getChildCount()-1);
if(webView.getVisibility() == View.GONE)
webView.setVisibility(View.VISIBLE);
}else{
super.onBackPressed();
}
Do you have a parent activity which is launching this one? If yes make sure you don't call finish() after launching maswebview, that way the parent activity will remain in the stack. Once maswebview would exit, onResume would be called for your parent activity.
In my application when i click the back button it passes through all the activities that i open them previously , i used the public void onBackPressed() method to make the back button back to the activity that i want as follow
public void onBackPressed()
{
startActivity(new Intent("com.MyDiet.Main"));
Tracker.this.finish();
}
is that true and safe way to code the back button ? how i can prevent the application from passing through all the previous opened activities when the back button is pressed ? and how i can make the application exit when i click the back button in the main activity?
In your application, and in ALL android applications, unless it's critical not to pass through unneeded steps (such as login if you're already logged in), it's VERY important not to override Android standard behaviour. Users normally complain about Android apps not having a common behaviour or style guideline.
Anyway, yeah, you can just override onBackPressed on all your activities and do whatever you want. But just don't.
This approach isn't good, because you're polluting the activity stack of your application
Example:
current stack: MainAct -> Act2 -> Act3 (we're in activity 3)
With your code above, when you press back, the stack now looks as follows:
MainAct -> Act2 -> MainAct
Because you ended Act3 and launched a NEW main activity, which may be not what you wanted.
To achieve what you want (Get back to main when the current activity is over) you need to work on the intermediate activities: In the example above, when from Act2 you call startActivity("Act3"), you should call "this.finish()". Therefore you don't have to override "onBackPressed()" of activity 3: simply the default value will terminate Act3 and the next activity in the stack will be MainAct
MainAct -> A2 (A2 launches A3 and then calls this.finish())
MainAct -> A3 (user now press back)
MainAct (the mainactivity is now on top)
To summarize, you don't have to override onBackPressed, you just have to correctly manage the lifecycle of the activity between the main one and the current one.
Generally speaking it's not recommended to make things work like user doesn't expect and that is considered as very bad practice. That's why it is not good to start activity from overriden onBackPressed().
When user press back by default activity will finish and one from back stack will be displayed. You as developer will (by writing code) decide which one is that. You can do it this way but later (or for somebody else) it will be a bit messy and difficult to find this unusual place for code which is starting other activity.
So..It would be useful to read about activity lifecycle and back stack to get impression how it works and understand terminology better.
If you want one of your activity not to stay on back stack you can add in manifest file file android:noHistory="true" for that activity.
Same thing you can achieve from code by adding appropriate flag to intent when you start activity: Intent.FLAG_ACTIVITY_NO_HISTORY
When user "go away" from ActivityOne (started using intent or defined in manifest like described), to new ActivityTwo and then press back, it will not go to ActivityOne because it will not be on back stack. Using this you can precisely control navigation through your activities.
More flags are available for use, but I guess this is what you wanted to achieve.
Hope you will find my answer useful. Cheers..
You can use a lot of tricks to exit your complet application for my part i use this start a intent and then from the androidmanifest i choose the category to home and than close the current activity such would be your mainactivity !
public void onBackPressed() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}