7
votes

My app contains an initial splash screen, followed by a listview (main activity). Clicking on each row of listview opens each activity.

My requirement is that if we single press the back button from any of my inner activities (activities that are opened when we click the listview rows), it must navigate to my main listview, and then if we press once more from the listview the app must gets closed.

So, if I press the back button from my listview twice it will exit the app correctly. My main problem is that if I press the back button twice from any of my inner activities, my app is not getting closed. I need to press three times, instead of closing the app from any of my inner activities. Can anyone please help me ?

This is my code for exiting the app. I added this code in my main listview class..

private static final int TIME_INTERVAL = 3000; // # milliseconds, desired time passed between two back presses.
private long mBackPressed;

@Override
public void onBackPressed()
{
    if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) 
    { 
        super.onBackPressed(); 
        return;
    }
    else { Toast.makeText(getBaseContext(), "Tap back button in order to exit", Toast.LENGTH_SHORT).show(); }

    mBackPressed = System.currentTimeMillis();
}
} 

my manifest.xml

<application
    android:allowBackup="true"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"> 

    <meta-data android:name="com.google.android.gms.version"
       android:value="@integer/google_play_services_version"/>


    <activity
        android:name="learnersseries.mathematics.complexnumbers.Firstintro"
         android:screenOrientation="portrait" 
         android:launchMode="singleTop"            
        android:label="@string/app_name" >


        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />

        </intent-filter>
    </activity>


    <activity android:name="Myintegralpage"
        android:screenOrientation="portrait"
                   >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="myimagine"
        android:screenOrientation="portrait" 

       >
        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Myintroductionpage"
        android:screenOrientation="portrait" 

      >
        <intent-filter></intent-filter>
    </activity>
    <activity android:name="MainActivity"
        android:noHistory="false"
        android:screenOrientation="portrait" 
       >


        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Complexnumbers"
        android:screenOrientation="portrait"
         >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Equality"
        android:screenOrientation="portrait"
         >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Additionofcomplex"
        android:screenOrientation="portrait"
          >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Subtraction"
        android:screenOrientation="portrait" 
        >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="multiplication"
        android:screenOrientation="portrait" >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Division"
        android:screenOrientation="portrait" >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Conjugate"
        android:screenOrientation="portrait" >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Modulus"
        android:screenOrientation="portrait" >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Reciprocal"
        android:screenOrientation="portrait" >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Square"
        android:screenOrientation="portrait">


    </activity>
    <activity android:name="Representation"
        android:screenOrientation="portrait" >

        <intent-filter></intent-filter>
    </activity>
    <activity android:name="Argument"
        android:screenOrientation="portrait" >
12

12 Answers

14
votes

Try this way,hope this will help you to solve your problem.

Take one flag doubleBackToExitPressedOnce which is by default (false ) in you Activity and when back button pressed first time flag value changed to (ture) and again back button pressed within 2 second exit from you app if back button again not pressed within 2 second set flag value (false).

private boolean backPressedToExitOnce;

@Override
public void onBackPressed() {
    if (doubleBackToExitPressedOnce) {
        super.onBackPressed();
        return;
    }

    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT).show();

    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            doubleBackToExitPressedOnce=false;                       
        }
    }, 2000);
} 
3
votes

This is a guaranteed working solution to exit app on 2 times back press

int doubleBackToExitPressed = 1;
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onBackPressed() {
    if (doubleBackToExitPressed == 2) {
        finishAffinity();
        System.exit(0);
    }
    else {
        doubleBackToExitPressed++;
        Toast.makeText(this, "Please press Back again to exit", Toast.LENGTH_SHORT).show();
    }

    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            doubleBackToExitPressed=1;`enter code here`
        }
    }, 2000);
}
2
votes

Hi I know that my answer is too late but Please take tour on the following snippet to get clear solution:

@Override
public void onBackPressed() {
    if(canExit)
        super.onBackPressed();
    else{
        canExit = true;
        Toast.makeText(getApplicationContext(), "Press again", Toast.LENGTH_SHORT).show();
    }
    mHandler.sendEmptyMessageDelayed(1, 2000/*time interval to next press in milli second*/);// if not pressed within 2seconds then will be setted(canExit) as false
}


public Handler mHandler = new Handler(){

        public void handleMessage(android.os.Message msg) {

            switch (msg.what) {
            case 1:
                canExit = false;
                break;
            default:
                break;
            }
        }
    };
1
votes

Here is the full working and simple code to do this. And also don't forget to remove the callbacks in onDestroy method so that it don't cause a memory leak in the app. :)

private boolean backPressedOnce = false;
private Handler statusUpdateHandler = new Handler();
private Runnable statusUpdateRunnable;

public void onBackPressed() {
        if (backPressedOnce) {
            finish();
        }

        backPressedOnce = true;
        final Toast toast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_SHORT);
        toast.show();

        statusUpdateRunnable = new Runnable() {
            @Override
            public void run() {
                backPressedOnce = false;
                toast.cancel();  //Removes the toast after the exit.
            }
        };

        statusUpdateHandler.postDelayed(statusUpdateRunnable, 2000);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (statusUpdateHandler != null) {
        statusUpdateHandler.removeCallbacks(statusUpdateRunnable);
    }
}
0
votes

Try adding Parent Activity to the new activities in manifest.
Eg:

<activity android:name="myimagine"
          android:screenOrientation="portrait"
          android:parentActivityName="com.example.previous_activity" />
0
votes

In Adding to Haresh Chhelana... Just create one Base Activity and after that extend all other activitys from it. That code which wrote by Haresh Chhelana insert in your BaseActivity. I think it must resolve your problem

0
votes

When you override your onBackPressed, after second click you need to:

  • finish an app process:

    ActivityManager am = (ActivityManager) getSystemService(Activity.ACTIVITY_SERVICE); am.killBackgroundProcesses(packageName);

  • finish your first activity. Here is the example: https://stackoverflow.com/a/14002030/3864698

UPD

First case:

@Override
    public void onBackPressed() {
        if (doubleBackToExitPressedOnce) {
            ActivityManager manager =  (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
            List<ActivityManager.RunningAppProcessInfo> activityes = ((ActivityManager) manager).getRunningAppProcesses();
            for (int i = 0; i < activityes.size(); i++){
                if (activityes.get(i).processName.equals(getApplicationInfo().packageName)) {
                    android.os.Process.killProcess(activityes.get(i).pid);
                }
            }
            return;
        }
        doubleBackToExitPressedOnce = true;


        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                doubleBackToExitPressedOnce = false;
                myOwnBackPress();
                }
        }, 1000);
}

private void myOwnBackPress() {
    if(!isFinishing()) {
        super.onBackPressed();
    }
}

Actually google does not recommend to kill processes.

Second case:

//for all activity besides HomeActivity.
@Override
    public void onBackPressed() {
        if (doubleBackToExitPressedOnce) {
            Intent intent = new Intent(getApplicationContext(), HomeActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            intent.putExtra("EXIT", true);
            startActivity(intent);
            return;
        }
        doubleBackToExitPressedOnce = true;


        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                doubleBackToExitPressedOnce = false;
                myOwnBackPress();
            }
        }, 1000);
}

private void myOwnBackPress() {
    if(!isFinishing()) {
        super.onBackPressed();
    }
}

In your HomeActivity don't override onBackPressed and add the next in onCreate:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       // initialize a lot of variables
        if (getIntent().getBooleanExtra("EXIT", false)) {
            finish();
        }
        // some code..
}
0
votes

Try this way,hope will help you !

    public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
        switch (event.getAction()) {
        case KeyEvent.ACTION_DOWN:
            if (event.getDownTime() - lastPressedTime < PERIOD) {
                moveTaskToBack(true);
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(1);
            } else {
                Toast.makeText(getApplicationContext(),
                        "Press again to exit.", Toast.LENGTH_SHORT).show();
                lastPressedTime = event.getEventTime();
            }
            return true;
        }
    }
    return false;
}
0
votes

After having to implement many times a behavioural requirements of capturing double back press action, built a library to do just that. The DoubleBackPress Android Library provides easy handling with builtin templates for such situations.

So for something like exiting on pressing back button twice, just do :

// set the Action to occur on DoubleBackPress
DoubleBackPressAction doubleBackPressAction = new DoubleBackPressAction() {
    @Override
    public void actionCall() {
          // TODO : Exiting application code
          finish();
    }
};

// setup DoubleBackPress behaviour
DoubleBackPress doubleBackPress = new DoubleBackPress()
        .withDoublePressDuration(3000)                  // timeout duration - msec
        .withDoubleBackPressAction(doubleBackPressAction);

And set the new behaviour as the default for back press in your Activity.

@Override
public void onBackPressed() {
    doubleBackPress.onBackPressed();
}

Example GIF of similar requirements

0
votes

Easy and Simple solution use with Toast

In Java

private Toast exitToast;

@Override
public void onBackPressed() {
    if (exitToast == null || exitToast.getView() == null || exitToast.getView().getWindowToken() == null) {
        exitToast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_LONG);
        exitToast.show();
    } else {
        exitToast.cancel();
        super.onBackPressed();
    }
}

In Kotlin

private var exitToast: Toast? = null

override fun onBackPressed() {
    if (exitToast == null || exitToast!!.view == null || exitToast!!.view.windowToken == null) {
        exitToast = Toast.makeText(this, "Press again to exit", Toast.LENGTH_LONG)
        exitToast!!.show()
    } else {
        exitToast!!.cancel()
        super.onBackPressed()
    }
}
0
votes
  1. Define a global variable name Counter.

int counter=0;

  1. Override onBacPressed() methos in you MainActivity.java

  2. And follow the step as below,

In java

    @Override
    public void onBackPressed() {
        counter+=1;
        if (counter==2){
            super.onBackPressed();
        }else {
            Toast.makeText(this, "Press one more time to exit", Toast.LENGTH_SHORT).show();
        }

    }
0
votes

Define a boolean variable name doubleBackToExitPressedOnce.

boolean doubleBackToExitPressedOnce = true;

Override onBackPressed() method in your MainActivity.java

And follow the step as below,

@Override
public void onBackPressed() {
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        if (doubleBackToExitPressedOnce) {
            this.doubleBackToExitPressedOnce = false;
            Globals.showToast(this, "Please press back again to exit.");
        } else {
            finish();
        }
    }
}