preface

  • inAndroidIn development, there is often a “one-click exit”AppThe demand of”
  • But there are too many “one-click exit App” implementations out there that don’t work
  • This article will fully summarize the one-click exitApp“, and practice for you one by one, I hope you will like.

directory


1. The nature of demand

There are actually two requirements for one-click exit from App:

  1. End the current buttonAppAll of theActivity
  2. End the current buttonAppprocess

That is, it takes 2 steps to complete the one-click exit App requirement. Below, I’ll walk you through these two steps.


2. Function realization

2.1 (Step 1) One-click end of all activities in the current App

2.1.1 Implementation method type
  • It is mainly divided into two categories: passAndroidComponent & self implementation
  • The details are as follows:

Note: The above method only ends all activities in the current App (indeed exits the App from the user’s perspective), but the App process is not actually finished.

2.1.2 Detailed introduction

A. Using the Android component: Activity

Method 1: Use the Activity startup mode: SingleTask

  • The principle of

    1. willAppThe entrance of theActivityusingSingleTaskBoot mode

    A. Entry Activity is now at the bottom of the stack b. The principle of SingleTask is as follows:

    1. When it’s time to quitAppStart entry whenActivity

    All Activity instances above the entry Activity are automatically closed and removed & are placed at the top of the stack (this is a feature of SingleTask startup mode).

    1. Through at the entranceActivityThe callbackonNewIntent()To close itself

    OnNewIntent () is called when a subsequent Activity starts an Activity at the bottom of the task stack.

  • The specific implementation

Step 1: Set the App entry Activity to “SingleTask” startup mode

// The Activity configuration in AndroidMainifest. XML is set < Activity android:launchMode="singleTask"SingleInstance: singleInstance: singleInstance: singleInstance: singleInstance: singleInstance: singleInstance: singleInstance: singleInstance: singleInstance: Singleton mode // If not set, the Activity starts in standard mode by default.Copy the code

Step 2: Rewrite the Activity onNewIntent() in the entry

@override protected void onNewIntent(Intent Intent) {super.onnewintent (Intent Intent);if(intent ! Intent.getbooleanextra (intent.getBooleanExtra(intent.getBooleanExtra))"exit".false);
            if(isExitApp) {// Close itself this.finish(); }}}Copy the code

Step 3: Call exitApp() when you need to exit

private void exitApp() {
        Intent intent = new Intent(context, MainActivity.class);
        intent.putExtra("exit".true); context.startActivity(intent); // end the process // system.exit (0); }Copy the code
  • Advantages Simple & convenient to use

  • disadvantages

    1. Specify that the entry Activity of App adopts SingleTask startup mode
    2. Limitations: You can only end an Activity in the current task stack, if there is a multi-task stack (i.eSingleInstanceBoot mode) cannot be processed
  • Application scenario Activity Single-task stack


Method 2: Start the Activity flag bit

  • Principle: Use 2 flag bits for entry Activity:

    1. Intent.FLAG_ACTIVITY_CLEAR_TOP: Destroy targetActivityAnd everything above itActivityTo recreate the targetActivity
    2. Intent.FLAG_ACTIVITY_SINGLE_TOP: If enabledActivityAt the top of the task stack, so thisActivityIs not rebuilt, but reuses instances at the top of the stackonNewIntent())
  • How to use it (jump from MainActivity (entry Activity) to Activity2 & one-click exit)

Step 1: Set the MainActivity to override onNewIntent() mainActivity.java

/ / set button to jump to Activity2 button. SetOnClickListener (new View.OnClickListener() { @Override public void onClick(View view) { startActivity(new Intent(MainActivity.this, Activity2.class)); }}); } // Pass an identifier to onNewIntent (). app@override protected void onNewIntent(Intent Intent) {super.onnewintent (Intent Intent);if(intent ! Intent.getbooleanextra (intent.getBooleanExtra(intent.getBooleanExtra))"exit".false);
            if(isExitApp) {// Close itself this.finish(); }} // end the process // system.exit (0); }}Copy the code

Step 2: Start MainActivity where you want to exit (Activity2) & set the flag bit

Intent Intent = new Intent(); intent.setClass(Activity2.this, MainActivity.class); Intent.setflags (intent.flag_activity_clear_top); Intent.addflags (intent.flag_activitY_singLE_TOP); intent.flag_activitY_singLE_top (intent.flag_activitY_singLE_TOP); // Step 2: If the Activity is started at the top of the task stack, the instance of the Activity is not rebuilt. Instead, the instance at the top of the stack is reused (calling onNewIntent() of the instance) // In Step 1: Activity2 on top of MainActivity is destroyed, and MainActivity is at the top of the stack. Because of the setup in Step 2, instead of creating a new MainActivity, you reuse the instance at the top of the stack & call the real onNewIntent() // pass in your own setting to exit the App flag Intent.putextra ("exit".true);

                startActivity(intent);
Copy the code
  • Advantages Simple & convenient to use

  • Disadvantages: You can only end the Activity in the current task stack, and cannot process the Activity in the multi-task stack (i.e., using SingleInstance startup mode)

  • Application scenario Activity Single-task stack


Method 3: Through the system task stack

  • How it works: Get the current system’s task stack from ActivityManager & exit all activities in the stack one by one

  • The specific use

@TargetApi(Build.VERSION_CODES.LOLLIPOP) // 1. ActivityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE); / / 2. Through the ActivityManager for task List < ActivityManager, AppTask > appTaskList = ActivityManager. GetAppTasks (); // 3. Close the Activity one by onefor(ActivityManager.AppTask appTask : appTaskList) { appTask.finishAndRemoveTask(); } // 4. End the process // system.exit (0);Copy the code
  • Advantages Simple and convenient to use

  • disadvantages

    1. Limitations: You can only end an Activity in the current task stack, if there is a multi-task stack (i.eSingleInstanceBoot mode) cannot be processed
    2. rightAndroidVersion requirements are high:The Android 5.0The above
  • Application scenario Android 5.0 or higher single-task Activity stack


B. Using the Android component: BroadcastReceiver

BroadcastReceiver is used to broadcast listening

  • How it works: Register a broadcast receiver in each Activity (response action = close itself); Send a broadcast request when you need to exit the App

  • The specific implementation

Step 1: Customize broadcast receivers

public class ExitAppReceiver extends BroadcastReceiver { private Activity activity; public ExitAppReceiver(Activity activity){ this.activity = activity; } @Override public void onReceive(Context context, Intent intent) { activity.finish(); }}Copy the code

Step 2: Register broadcast receivers in each Activity (response action = close itself)

Public class Activity extends AppCompatActivity {private ExitAppReceiver mExitAppReceiver; Protected void onCreate(Bundle savedInstanceState) {super.oncreate (savedInstanceState);setContentView(R.layout.activity_main); mExitAppReceiver = new ExitAppReceiver(this); registerReceiver(mExitAppReceiver,new IntentFilter(BaseApplication.EXIT)); } // 1. In onDestroy (), unregister the broadcast receiver protected voidonDestroy() {
        super.onDestroy();
        unregisterReceiver(mExitAppReceive);
    }

Copy the code

Step 3: Send a broadcast request when you need to exit the App

context.sendBroadcast(new Intent(BaseApplication.EXIT)); // Note: this cannot be used: system.exit (0); // Cause: After sending the broadcast method, the program will not wait for the broadcast receiver to receive the next sentence system.exit (0), which is immediately changed to system.exit (0).Copy the code
  • Advantages Wide application scenarios: considering single/multi-task stack & multi-boot mode

  • The downside is complex implementation: you need to register broadcast receivers in each Activity

  • Application Scenario One-click exit of the App in any case, but the App process cannot be terminated

So it’s just a one-click exit from the App from the user’s perspective.


C. Self-implementation

Method 1: Create a linked list
  • Create a linked list of activities in a subclass of Application. When you need to exit App with one click, you can exit all Activity instances in the linked list one by one

  • The specific use

Step 1: Create a linked list of activities in a BaseApplication subclass

Carson_BaseApplicaiton.java

Public class Carson_BaseApplicaiton extends Application {public class Carson_BaseApplicaiton extends Application { Static LinkedList<Activity> activityLinkedList; @Override public voidonCreate() {
        super.onCreate();

        activityLinkedList = new LinkedList<>();

        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                Log.d(TAG, "onActivityCreated: "+ activity.getLocalClassName()); activityLinkedList.add(activity); } @override public void onActivityDestroyed(Activity Activity) {log.d (TAG,"onActivityDestroyed: "+ activity.getLocalClassName()); activityLinkedList.remove(activity); Public void onActivityStarted(Activity Activity) {} @override public void onActivityStarted(Activity Activity) {} @override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } }); } public voidexitApp() {

        Log.d(TAG, "The list of activities in the container is as follows"); // Print the list of activities in the current containerfor (Activity activity : activityLinkedList) {
            Log.d(TAG, activity.getLocalClassName());
        }

        Log.d(TAG, "Phasing out all activities in the container"); // Exit the Activity one by onefor(Activity activity : activityLinkedList) { activity.finish(); } // End the process // system.exit (0); }} // Remember to add <application Android :name= to manifest.xml".Carson_BaseApplicaiton". </application>Copy the code

Step 2: get the Applicaiton class object & call exitApp() when you need to exitApp with one click

                private Carson_BaseApplicaiton app;

                app = (Carson_BaseApplicaiton)getApplication();
                app.exitApp();


Copy the code
  • rendering

  • Advantages Wide application scenarios: considering single/multi-task stack & multi-boot mode

  • Disadvantages Require the Activity to go through a normal life cycle, which calls onCreate () when it is created and onDestroy () when it ends.

This is the only way to properly write and write an Activity to the container through a normal life cycle

  • Usage Scenario One-click exit in any caseAppimplementation

Method 2: RxBus

  • How it works: Use RxBus as an event bus, register RxBus subscriptions in each Activity (response action = shut itself down); Send the exit event request when you need to exit the App.

  • The specific use

Step 1: Register the RxBus subscription in each Activity (response action = close itself)

public class Activity extends AppCompatActivity {
  private Disposable disposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity2); Subscribe (new Consumer<String>() {@override); // Register the RxBus subscription disposable = rxbus.getInstance ().toobServable (string.class).subscribe(new Consumer<String>() {@override Public void Accept (String s) throws Exception {// Response action = Close itselfif (s.equals("exit")){ finish(); }}}); } // Be sure to unsubscribe @override protected voidonDestroy() {
        if (!disposable.isDisposed()){
              disposable.dispose();;
        }
}
Copy the code

Step 2: Send an exit event when you need to exit the App

        RxBus.getInstance().post("exit");
        System.exit(0);
Copy the code
  • Advantages can be combined with RxJava & RxBus

  • Disadvantages complex implementation: RxBus itself is difficult to implement & requires registering and unsubscribing to RxBus for each Activity

  • Application scenario When RxJava needs to be used together

If the project does not use RxJava & RxBus, do not use it

  • At this point, one key to end the currentAppAll of theActivityThe explanation of the method is complete.
  • Note: The above method only ends the presentAppAll of theActivity(From the user’s point of view, yesApp), but in fact it shouldAppThe process is not finished yet

2.2 (Step 2) One-click Termination of the App Process

The local method of Dalvik VM is mainly used

  • Effect End currentActivity& End the process

That is, after (Step 1) ending all activities in the current App, call this method to exit the App with one click (more on the end process).

  • The specific use
/ / way 1: the android OS. Process. KillProcess () android. OS) Process. The killProcess (android. OS. Process. MyPid ()); Exit (0) = Exit (0); exit(0) = exit(0); // system.exit (0) : exit normally; // system.exit (0) : exit normally; // 2.system.exit (1) : An abnormal exit. Normally this exit should be placed in a catch block.Copy the code
  • Pay special attention to the hypothetical scenario: the presentActivity≠ Last 1 in current task stackActivityWhat happens when you call the above two methods? (i.e.Activity1Activity2Activity3(in theActivity3Call the above two methods))

A:

  1. The end of theActivity3(the currentActivity) & End the process
  2. Restart the process again & startActivity1Activity2

That is, in Android, calling the above Dalvik VM local method results in:

  1. End of the currentActivity& End the process
  2. Then restart the process & remove the current before startingActivityExternal startedActivity
  • Reason: ** ActivityManager in Android is always listening for processes **. It will try to restart the process if it detects that it has terminated abnormally.

  • Application Scenario When only the current Activity is left in the task stack (that is, after exiting other activities), call this method to exit the process. That is, after (Step 1) ending all activities in the current App, call this method to exit the App with one key (more on ending the process).

Note: This differs from “Finish () on the last Activity call” : Finish () does not end the process, as the above two methods do

Now, the two-step explanation of one-click exit App is complete.


3. The Demo address

All of the above mentioned methods are at Carson_Ho’s Github address: one-click exit App


4. To summarize

  • In need to achieve one-click exitAppIn fact, you need to complete two steps: Step 1: One-click terminationAppAll of theActivityStep 2: One-click endAppprocess
  • The methods for each step are summarized below

  • So I’m going to continue with thisAndroidIn the knowledge of in-depth explanation, interested can continue to pay attention toCarson_Ho android Development Notes

Thumb up, please! Because your encouragement is the biggest power that I write!


Welcome to follow Carson_ho on wechat