前言
-
在
Android開發中,會經常存在 “一鍵退出App” 的需求
-
但市面上流傳著 太多不可用的“一鍵退出
App”功能實現
-
本文將全面總結“一鍵退出
App”的實現方式,并為你一一實踐,希望你們會喜歡。
目錄
1. 需求本質
一鍵退出 App 其實是 兩個需求:
1. 一鍵結束當前App所有的Activity
2. 一鍵結束當前App進程
即 需要2個步驟 才可 完成 一鍵退出 App 需求。下面,我將根據這兩個步驟進行功能實現講解。
2. 功能實現
2.1 (步驟1)一鍵結束當前 App 所有 Activity
2.1.1 實現方法類型
-
主要分為2類:通過
Android組件 & 自身實現
-
具體如下圖:
注:上述方法僅僅只是結束當前App所有的Activity (在用戶的角度確實是退出了 App),但實際上該App的進程還未結束。
2.1.2 具體介紹
a. 通過 Android 組件:Activity
方法1:采用Activity啟動模式:SingleTask
-
原理
-
將
App的入口 Activity 采用 SingleTask 啟動模式
a. 入口 Activity 此時處于棧底
b. 關于 SingleTask的原理如下:
-
當需要退出
App時啟動入口 Activity
此時入口 Activity 上層的Activity實例都將自動關閉移除 & 自身被放置在棧頂(這是SingleTask啟動模式的特點)
-
通過在入口
Activity 回調的onNewIntent()中關閉自身即可
若在后面的Activity啟動 任務棧底的Activity時,就會調用任務棧底Activity的onNewIntent()
-
具體實現
步驟1:將 App的入口 Activity 設置成 SingleTask 啟動模式
<activity
android:launchMode="singleTask" </activity>
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
步驟2:在入口 Activity重寫 onNewIntent()
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (intent != null) { boolean isExitApp = intent.getBooleanExtra("exit", false); if (isExitApp) { this.finish();
}
}
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
步驟3:在需要退出時調用 exitApp()
private void exitApp() {
Intent intent = new Intent(context, MainActivity.class);
intent.putExtra("exit", true);
context.startActivity(intent); }
-
優點
使用簡單 & 方便
-
缺點
-
規定 App的入口Activity采用SingleTask啟動模式
-
使用范圍局限:只能結束當前任務棧的Activity,若出現多任務棧(即采用
SingleInstance啟動模式)則無法處理
-
應用場景
Activity單任務棧
方法2:采用Activity啟動標記位
步驟1:在MainActivity 中設置 重寫 onNewIntent()
MainActivity.Java
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) {
startActivity(new Intent(MainActivity.this, Activity2.class));
}
});
} @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (intent != null) { boolean isExitApp = intent.getBooleanExtra("exit", false); if (isExitApp) { this.finish();
}
} }
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
步驟2:在需要退出的地方(Activity2)啟動MainActivity & 設置標記位
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.putExtra("exit", true);
startActivity(intent);
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
方法3:通過系統任務棧
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
// 1. 通過Context獲取ActivityManager
ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE) // 2. 通過ActivityManager獲取任務棧
List<ActivityManager.AppTask> appTaskList = activityManager.getAppTasks() // 3. 逐個關閉Activity
for (ActivityManager.AppTask appTask : appTaskList) {
appTask.finishAndRemoveTask() }
// 4. 結束進程
// System.exit(0)
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
b. 通過 Android 組件: BroadcastReceiver
即使用 BroadcastReceiver 廣播監聽
步驟1:自定義廣播接收器
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();
}
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
步驟2:在每個 Activity 里注冊廣播接收器(響應動作 = 關閉自身)
public class Activity extends AppCompatActivity { private ExitAppReceiver mExitAppReceiver;
// 1. 在onCreate()中注冊廣播接收器 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mExitAppReceiver = new ExitAppReceiver(this);
registerReceiver(mExitAppReceiver,new IntentFilter(BaseApplication.EXIT));
} protected void onDestroy() { super.onDestroy();
unregisterReceiver(mExitAppReceive);
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
步驟3:當需要退出App時 發送廣播請求
context.sendBroadcast(new Intent(BaseApplication.EXIT));
// 注:此處不能使用:System.exit(0);結束進程
// 原因:發送廣播這個方法之后,不會等到廣播接收器收到廣播,程序就開始執行下一句System.exit(0),然后就直接變成執行System.exit(0)的效果了。
-
優點
應用場景廣泛:兼顧單 / 多任務棧 & 多啟動模式的情況
-
缺點
實現復雜:需要在每個 Activity 里注冊廣播接收器
-
應用場景
任意情況下的一鍵退出 App,但無法終止 App 進程
所以該方法僅僅是在用戶的角度來說 “一鍵退出App”
c. 自身實現
方法1:創建 鏈表
步驟1:在BaseApplication類的子類里建立Activity鏈表
Carson_BaseApplicaiton.java
public class Carson_BaseApplicaiton extends Application { public static LinkedList<Activity> activityLinkedList;
@Override public void onCreate() {
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); }
@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 void exitApp() {
Log.d(TAG, "容器內的Activity列表如下 "); for (Activity activity : activityLinkedList) {
Log.d(TAG, activity.getLocalClassName());
}
Log.d(TAG, "正逐步退出容器內所有Activity"); for (Activity activity : activityLinkedList) {
activity.finish();
} }
} <application
android:name=".Carson_BaseApplicaiton" ....
</application>
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
步驟2:需要一鍵退出 App 時,獲取該 Applicaiton類對象 & 調用exitApp()
private Carson_BaseApplicaiton app;
app = (Carson_BaseApplicaiton)getApplication();
app.exitApp();
方法2:RxBus
步驟1:在每個 Activity里注冊RxBus訂閱(響應動作 = 關閉自身)
public class Activity extends AppCompatActivity { private Disposable disposable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity2); disposable = RxBus.getInstance().toObservable(String.class)
.subscribe(new Consumer<String>() { @Override public void accept(String s) throws Exception { if (s.equals("exit")){
finish();
}
}
});
} @Override protected void onDestroy() { if (!disposable.isDisposed()){
disposable.dispose();;
}
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
步驟2:當需要退出App時 發送退出事件
RxBus.getInstance().post("exit") System.exit(0)
2.2 (步驟2)一鍵結束當前 App 進程
主要采用 Dalvik VM本地方法
-
作用
結束當前 Activity & 結束進程
即 在 (步驟1)結束當前 App 所有的 Activity 后,調用該方法即可一鍵退出 App(更多體現在結束進程上)
-
具體使用
// 方式1:android.os.Process.killProcess()
android.os.Process.killProcess(android.os.Process.myPid()) ;
// 方式2:System.exit()
// System.exit() = Java中結束進程的方法:關閉當前JVM虛擬機
System.exit(0) // System.exit(0)和System.exit(1)的區別
// 1. System.exit(0):正常退出;
// 2. System.exit(1):非正常退出,通常這種退出方式應該放在catch塊中。
-
特別注意
假設場景:當前 Activity ≠ 當前任務棧后1個Activity時,調用上述兩個方法會出現什么情況呢?(即Activity1 - Activity2-Activity3(在Activity3調用上述兩個方法))
答:
1. 結束Activity3(當前 Activity )& 結束進程
2. 再次重新開啟進程 & 啟動 Activity1 、 Activity2
即在android 中,調用上述Dalvik VM本地方法結果是:
1. 結束當前 Activity & 結束進程
2. 之后再重新開啟進程 & 啟動 之前除當前 Activity 外的已啟動的 Activity
至此,關于 一鍵退出App 的兩個步驟講解完畢。
3. Demo地址
關于上述說的方法Demo都在Carson_Ho的Github地址:一鍵退出App
4. 總結
-
在 需要實現 一鍵退出
App 功能時,實際上是需要完成2個步驟:
步驟1:一鍵結束當前App所有的Activity
步驟2:一鍵結束當前App進程
-
每個步驟的方法總結如下
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。