onBackPressed() not working while coming from another activity - java

I have three activities: First, Second and Third. I used this method in Second activity:
public void onBackPressed() {
super.onBackPressed();
finish();
}
and this on Third activity:
public void onBackPressed() {
super.onBackPressed();
Intent i = new Intent(Third.this, Second.class);
startActivity(i);
finish();
}
The problem is when I press back button after coming from the Third activity, I am going into First activity instead of finish(). I am successfully exiting the application when I click back button right after coming from first activity but not after coming from Third activity.
How to solve this problem?
EDIT: Thanks for the answers guys,the answer of "Ved Prakash" solved the problem for me.But i have a weird problem now.When i press back button the app is successfully exiting but the app which i minimized to Recent Apps button is coming on to the screen and exiting.For example,if i have opened Setting app before opening my app,when i press back button,my app is exiting and immediately Settings app is also opening and exiting itself.What might be the problem?

Your problem is that you don't seem to understand how Activities work. The finish() function ends the current Activity, and then you receive the previous Activity from the backstack.
My recommendation is that you should use a single Activity, and hold Fragments inside it. If you want it so that pressing the Back button ends the application at any screen that is displayed, you could do the following:
Activity XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/initial_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Activity that holds the Fragments:
public class InitialActivity extends FragmentActivity implements ReplaceWith
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_initial);
getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener()
{
public void onBackStackChanged()
{
int backCount = getSupportFragmentManager().getBackStackEntryCount();
if (backCount == 0)
{
finish();
}
}
});
if (savedInstanceState == null)
{
getSupportFragmentManager().beginTransaction().add(R.id.initial_container, new FirstFragment()).commit();
}
}
#Override
public void replaceWith(Fragment fragment)
{
getSupportFragmentManager().beginTransaction().replace(R.id.initial_container, fragment).commit();
}
}
Example for a Fragment:
public class FirstFragment extends Fragment implements View.OnClickListener
{
private ReplaceWith activity_replaceWith;
private ImageView exampleImage;
public FirstFragment()
{
super();
}
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try
{
activity_replaceWith = (ReplaceWith) activity;
}
catch (ClassCastException e)
{
Log.e(getClass().getSimpleName(), "Activity of " + getClass().getSimpleName() + "must implement ReplaceWith interface!", e);
throw e;
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
exampleImage = (ImageView) rootView.findViewById(R.id.fragment_first_example_image);
exampleImage.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v)
{
if(v == exampleImage)
{
activity_replaceWith.replaceWith(new SecondFragment());
//please note that this should be done only if you are planning
//only on single-screen applications
//with no other layouts based on orientation or size
//otherwise, the Activity needs to be responsible for this, not the Fragment
}
}
}
This way, when you press the Back button, your application would end from any displayed screen.

Ok your code is wrong.
If you will look at activity source, you see that activity.onBackPressed() is calling finish(). So if call super.onBackPressed() you don't need to call finish.
Finish() is not stopping your application, it's stopping current activity.
Your code on third activity very strange. You are trying to stop activity and start another same activity.
What exactly you want to achieve?
If you want to exit application from your third activity, you need to clear your backstack. But I think you have problem with structure of your app.

Ok. then you should finish your first activity when you go to second activity like this(If you are using intent for that):
Intent it=new Intent(FirstActivity.this,SecondActivity.class);
finish();
startactivity(it);
and same for Second Activity:
Intent it=new Intent(SecondActivity.this,ThirdActivity.class);
finish();
startactivity(it);
this done your work...when you are in third activity the above activities are finished..
and when you press backButton you will be exit from application..
Good luck.

You can use -
public static final int FLAG_ACTIVITY_CLEAR_TOP
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.
And here is how -
When the user wishes to exit all open activities, they should press a button which loads the first Activity that runs when your app starts, in my case "MainActivity".
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
The above code clears all the activities except for LoginActivity. LoginActivity is the first activity that is brought up when the user runs the program. Then put this code inside the LoginActivity's onCreate, to signal when it should self destruct when the 'Exit' message is passed.
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
This explanation part is also introduced at exit-an-android-app.

Related

Close MainActivity(main) from another activity (ActivityPoliticas)

I'm looking for a solution to press the (non-personalized ads) button of the ActivityPolicies and close the MainActivity and then reopen the MainActivity with the correct ad.
MainActivity(principal)
public void politicas(View view) // button
{
Intent i = new Intent (this, ActivityPolicies.class);
i.putExtra("valor","politicas");
startActivity(i);
}
ActivityPolicies
public void NonPersonalizedAdvertising(View view) //button
{
SharedPreferences myPreferences = PreferenceManager.getDefaultSharedPreferences(MensajePoliticas.this);
SharedPreferences.Editor myEditor =myPreferences.edit();
myEditor.putString("POLITICAS","LEIDO_NOACEPTADO");
myEditor.commit();
//Missing some option to close the main activity
*
*
*
//Reopen the main activity
Intent entrar=new Intent(this,MainActivity.class);
startActivity(entrar);
finish(); // Close the current activity (ActivityPolicies)
}
The goal is to close the MainActivity to reload the correct personalized or non-personalized ad. I already have the code but I am missing this option to reload the MainActivity.
Another question:
Close the main activity to reload the ads, can I have problems with some Admob rule?
Thank you very much
If your MainActivity is in backstack, you can call same activity like this:
Intent entrar = new Intent(this,MainActivity.class);
entrar.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // this will open the same MainActivity instance and also give you a new intent.
startActivity(entrar);
Now in your MainActivity you can override onNewIntent
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// here you will get the new Intent. You can reload only the ads programmatically or just call `this.recreate();`
}

Call a Method from another Method Android

I am not sure this workaround is the correct way to achieve my goal of having a prompt text in a spinner. What happens with this application is the spinner navigates to another Activity via an Intent and when the user navigates back to the Main Activity with the spinner they have two ways back. One with a Button and a click event the other by clicking the device BACK button. I am trying to call the code in the click event from the method that manages the device BACK button
I do not know how to call the click event from the device BACK button Method
#Override
public void onBackPressed() {
Toast.makeText(getApplicationContext(),"Use BACK BUTTON\n\n"+"On the Screen",Toast.LENGTH_LONG).show();
// I want to call goBack(View view) from here
// +++++++++++++++++++++++++++++++++++++++++++
}
public void goBack(View view){
Intent i = new Intent( PageTwo.this, MainActivity.class );
startActivity( i );
}
The reason I use this Intent to navigate BACK to the Main Activity is it reloads the variables in the Spinner
It looks like goBack(View) is most likely from an onClick setup in your layout XML. Since you aren't using the view, just pass null:
#Override public void onBackPressed() {
goBack(null);
}
I don't know if I get you right, if you just want to go back to the activity which started another activity, you can just call finish() method of Activity class:
#Override
public void onBackPressed() {
finish();
}
finish() reference

Android exit whole program syntax

currently I'm working on Android development, now I'm facing a problem to exit the whole application that had launched.
I'v tried .finish(), but it doesn't show what I want.
I have 2 Activities, A and B. Activity A will forward to Activity B when button click. In activity B, when I click button "Exit" (that I created) with the listener to trigger .finish(), it just back to Activity A but not to close whole application (what I want is back to home screen directly and kill the background process as well).
How can I exit whole application wherever in the application? Thank you.
button.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
//here to exit whole application not just backwards to previous activity
}
});
You write in Activity A after
startActivity(new Intent(A.this, B.class))
finish()
then you also write in Activity B finish() on button click listener. It should works.
public class A extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(A.this, B.class));
finish(); // you must write this also in A activity to close whole application
}
});
}
public class B extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_1);
Button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
EDIT: I assumed there are cases when the underlying activity either should or shouldn't be terminated on return. This will allow you to handle both cases.
Case A)
Activity A starts activity B, which starts activity C. You want to close all of them from activity C. If they're all in the same task (i.e. probably your case) you can close the whole task by calling
finishAffinity();
According to docs this is what happens:
Finish this activity as well as all activities immediately below it in the current task that have the same affinity. This is typically used when an application can be launched on to another task (such as from an ACTION_VIEW of a content type it understands) and the user has used the up navigation to switch out of the current task and in to its own task. In this case, if the user has navigated down into any other activities of the second application, all of those should be removed from the original task as part of the task switch.
Note that this finish does not allow you to deliver results to the previous activity, and an exception will be thrown if you are trying to do so.
See Activity.finishAffinity().
Case B)
Activity A starts activity B, which starts activity C. You want to close activities B and C from activity C.
This is how you start activity C from B expecting and handling a result:
public class ActivityB extends Activity {
private static final int RC_ACTIVITY_C = 1;
public static final int RESULT_FINISH = 1;
...
public void startActivityC() {
Intent intent = new Intent(this, ActivityC.class);
startActivityForResult(intent, RC_ACTIVITY_C);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_ACTIVITY_C && resultCode == RESULT_FINISH) {
finish();
}
}
}
This is how you let activity B it has to finish from activity C. At any point before finishing activity C call:
setResult(ActivityB.RESULT_FINISH);
See Activity.startActivityForResult(Intent, int) and Activity.setResult(int).
You can try System.exit(0). That should do the job.
EDIT: Take a look at this post for the difference between finish() and System.exit(). Difference between finish() and System.exit(0)

Have to press the back button twice to get to previous activity?

I am simply trying to click back and navigate to my previous activity. My flow is this: I go to news_feed activity -> Comments activity -> User Profile activity -> click back (Go to Comments activity) -> click back (This does nothing for some reason) -> Click back (Go back to news_feed activity). I'm not sure why I have to click back twice when I try to go from Comments activity back to news_feed activity. If I go from news_feed activity -> Comments -> press back (Go to news_feed activity) this works perfectly. Here is my code:
news_feed.java:
#Override
public void onBackPressed() {
super.onBackPressed();
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startMain);
}
Comments.java:
#Override
public void onBackPressed() {
super.onBackPressed();
this.finish();
}
UserProfile.java:
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = new Intent(UserProfile.this, Comments.class);
Bundle bundle = new Bundle();
bundle.putString("postId", postId);
bundle.putString("posterUserId", posterUserId);
bundle.putString("posterName", posterName);
bundle.putString("postStatus", postStatus);
bundle.putString("postTimeStamp", postTimeStamp);
bundle.putString("postTitle", postTitle);
intent.putExtras(bundle);
startActivity(intent);
finish();
}
I don't think navigating to these activities would change anything, but I can include the intents that I used to navigate to these activities also if necessary. Otherwise I just included the onBackPressed code that I had for these activities. Any ideas why this might cause a problem? Any help would be appreciated. Thanks.
In your UserProfile class, in onBackPressed() method, you are starting the Comments class again. Why do you have to do this?
What is happening is, you are starting a new Comments activity onBackPressed() of the USerProfile class, so there are two instances of Comments Activity. So you feel you are pressing back btn twice.
If you have to pass data back to Comments from UserProfile class, then make use of setResult() method.
This will be of help
How to pass data from 2nd activity to 1st activity when pressed back? - android
Sending data back to the Main Activity in android
I you want to send back the result to previous activity the start activity by using
startActivityForResult()
insead of
startActivity()
and don't override
onBackPressed()
You can try something like this:
private boolean clicked;
#Override
public void onBackPressed() {
if (!clicked) { // if it was not clicked before, change the value of clicked to true and do nothing directly return, if clicked again, then it will be finish the activity.
clicked=true;
return;
}
super.onBackPressed();
}
And if you are going to use the time, then you can do like this:
private long lastClicked;
#Override
public void onBackPressed() {
if (System.currentTimeMillis() - lastClicked < 1000) { // within one second
super.onBackPressed();
}
lastClicked = System.currentTimeMillis();
}
You don't need to override onBackPressed() if all you're going to do is call startActivity() and finish() in the current activity. The Android backstack will handle both of those for you. Moreover, in your UserProfile.java you are passing data to previous activity. For this, you should use startActvityForResult() in the Comments activity (i.e the previous activity) instead of startActivity().
To learn more about startActvityForResult() visit: https://developer.android.com/training/basics/intents/result.html
public void onBackPressed() {
if (this.lastBackPressTime < System.currentTimeMillis() - 2000) {
this.lastBackPressTime = System.currentTimeMillis();
} else {
//super.onBackPressed(); for exit
//INTENT HERE TO YOUR SECOND ACTIVITY like below
Intent intent=new Intent(A.this,B.class);
startActivirty(intent);
}
}
Create a global variable
private long lastBackPressTime = 0;
Hope this will help you,Let me know..

Android setContentView on pretty short Activity life time

The first activity of my android app, the "launcher activity", finishes pretty quickly. It's goal is to redirect to the MainActivity or to the UserLoginActivity, depending on the value of a shared-preferences variable.
If this variable does not exist, it automatically perform a StartActivity to the MainActivity.
If this variable is set, then it will perform an HTTP request to my API, in order to Authenticate the user. Then it will start the MainActivity. The HTTP request usually takes less than one second.
The thing is that I would like to display a progress bar, in the center of the LauncherActivity, so the user can understand that something is loading.
The problem is that nothing is displayed on the screen. But if I comment the line that starts the activity, then it will be displayed... It seems that the activity duration is too fast to display anything !
I thought calling the setContentView() method will instantly load Views on the screen. Is my case a normal behavior ? How could I display a progress bar on the screen, knowing that the activity will last around one second ?
Here you can see my Launcher Activity
public class Launcher extends Activity {
private void goToUserLogin(){
Intent intent;
intent = new Intent(this, UserLoginActivity.class);
startActivity(intent);
finish();
}
private void goToMain(){
YokiAPI API = new YokiAPI(this);
Intent intent;
try {
if (API.authenticateSmart(YokiGlobals.preferences.getSavedUserId(this))) {
intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
} else {
this.goToUserLogin();
}
} catch (Exception e){}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launcher);
// Launch Demo if First Run
if (YokiGlobals.preferences.getFirstLaunch(this)){
YokiGlobals.preferences.updateFirstLaunch(false, this);
this.launchDemo();
}
/*
** If userId saved, smart Auth and go to Main
** Else go to User Login for Full Auth or register
*/
if (YokiGlobals.preferences.getSavedUserId(this) == null){
this.goToUserLogin();
}
else {
this.goToMain();
}
}
}
And the .xml ressource file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="THIS TEXT WONT APPEAR"
android:layout_marginTop="208dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Thanks,
Oscar
I thought calling the setContentView() method will instantly load Views on the screen
No it won't because you are still in onCreate(). If you want to see any UI you need to let the activity cycle to go further, so rework your code or move your authentication to separate activity, meybe?
PS: you use this. without any real reason.
Thank you for your help. I used AsyncTask in order to fetch data from the API.
The main UI thread can now load the view.
Here is some very simplified code that maybe could help others.
public class UserSmartAuthActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_smart_auth);
new SmartAuth().execute();
}
private class SmartAuth extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
Context context = getApplicationContext();
YokiAPI API = new YokiAPI(context);
Intent intent = null;
try {
if (API.authenticateSmart(YokiGlobals.preferences.getSavedUserId(context)))
intent = new Intent(context, MainActivity.class);
else
intent = new Intent(context, UserLoginActivity.class);
} catch (Exception e){}
startActivity(intent);
finish();
return null;
}
}
}

Categories

Resources