android 8.0可以实现后台包活么,Android 8.0 应用保活实践 · Jaqen Ng
8種機械鍵盤軸體對比
本人程序員,要買一個寫代碼的鍵盤,請問紅軸和茶軸怎么選?
雖然我也覺得強行保活應用挺不厚道的,但是沒辦法,為了完成需求。
一開始嘗試的方案是 Android 5.0 后系統(tǒng)提供的 JobScheduler,能夠預先設置條件,達到條件時自動啟動 JobService,在 Android 8.0 以下都能很愉快的使用。但是在華為的 Android 8.0 上,當應用被殺后,JobService 就不能被系統(tǒng)調用了。
于是采取了雙進程服務綁定方式,實現(xiàn)了應用保活功能。
直接看原理圖:
原理就是利用 Binder 的訃告機制,如果 Service Binder 實體的進程被殺,系統(tǒng)會向 Client 發(fā)送訃告,這個時機就是保活的空子了。所以可以通過兩個進程啟動兩個 Binder 服務,互為 C/S,一旦一個進程掛掉,另一個進程就會收到 Binder 訃告,這時可以拉起另一個進程。
那么圖中兩個進程中的 TransferActivity 是干什么用的 ,這個在后面再說。
這里我寫了兩個應用,一個是 AIDLServer,相當于服務端;一個是 AIDLClient,相當于客戶端。而兩個進程之間的通信采用 AIDL 方式。1
2
3
4
5
6
7
8
9
10
11
12package com.wuzy.aidlserver;
// Declare any non-default types here with import statements
interface{
void bindSuccess();
void unbind();
}
注意兩個應用的 AIDL 文件必須一致,包括包名。
然后,編寫兩個 binder 實體服務 RemoteService 、LocalService,主要代碼如下: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
61public class RemoteService extends Service{
private static final String TAG = "RemoteService";
public void onCreate(){
super.onCreate();
Log.e(TAG, "onCreate: 創(chuàng)建 RemoteService");
bindLocalService();
}
public IBinder onBind(Intent intent){
return stub;
}
private IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() {
public void bindSuccess() throws RemoteException{
Log.e(TAG, "bindSuccess: LocalService 綁定 RemoteService 成功");
}
public void unbind() throws RemoteException{
Log.e(TAG, "unbind: 此處解除 RemoteService 與 LocalService 的綁定");
getApplicationContext().unbindService(connection);
}
};
/**
* 綁定 LocalService
*/
private void bindLocalService(){
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.wuzy.aidlclient", "com.wuzy.aidlclient.LocalService"));
if (!getApplicationContext().bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
Log.e(TAG, "bindLocalService: 綁定 LocalService 失敗");
stopSelf();
}
}
private ServiceConnection connection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service){
}
@Override
public void onServiceDisconnected(ComponentName name){
// bindRemoteService();
createTransferActivity();
}
};
private void createTransferActivity(){
Intent intent = new Intent(this, TransferActivity.class);
intent.setAction(TransferActivity.ACTION_FROM_SELF);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}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
59public class LocalService extends Service{
private static final String TAG = "LocalService";
@Override
public void onCreate(){
super.onCreate();
Log.e(TAG, "onCreate: 創(chuàng)建 LocalService");
bindRemoteService();
}
@Override
public IBinder onBind(Intent intent){
Log.e(TAG, "onBind: 綁定 LocalService");
return stub;
}
private IMyAidlInterface.Stub stub = new IMyAidlInterface.Stub() {
@Override
public void bindSuccess() throws RemoteException{
Log.e(TAG, "bindSuccess: RemoteService 綁定 LocalService 成功");
}
@Override
public void unbind() throws RemoteException{
getApplicationContext().unbindService(connection);
}
};
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service){
}
@Override
public void onServiceDisconnected(ComponentName name){
// bindRemoteService();
createTransferActivity();
}
};
private void createTransferActivity(){
Intent intent = new Intent(this, TransferActivity.class);
intent.setAction(TransferActivity.ACTION_FROM_SELF);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
private void bindRemoteService(){
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.wuzy.aidlserver", "com.wuzy.aidlserver.RemoteService"));
if (!getApplicationContext().bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
Log.e(TAG, "bindRemoteService: 綁定 RemoteService 失敗");
stopSelf();
}
}
}
在 onCreate 的時候相互綁定,并在 onServiceDisconnected 收到訃告的時候,重新啟動服務綁定彼此即可。
但是我在系統(tǒng)是 8.0 的華為機器上是無效的,也就是當 LocalService 所在進程被殺后,RemoteService 無法啟動LocalService,反過來也是如此。
所以,這里只能采取 “曲線救國” 的方式。通過 TransferActivity 中轉下,先啟動守護進程的 TransferActivity,再從守護進程的 TransferActivity 中啟動保活進程的 TransferActivity,這是沒有問題的,再從保活進程的 TransferActivity 中啟動 LocalService,重新綁定服務即可,反過來也是一樣的。當然,TransferActivity 要用戶無感知,不然會很突兀,所以這里的 TransferActivity 都是 1 個像素,做完任務及時銷毀即可。
TransferActivity 的代碼就不貼了,具體可以去 GitHub 了解。
這種方式用來保活一般是沒有問題的,因為 Binder 訃告是系統(tǒng)中 Binder 框架自帶的,除非一次性殺了兩個進程,那就沒轍了。
最后,一般保活的目的是為了做某項任務,所以,任務完成后應該結束保活功能,不然老是占著內存確實挺不厚道的。
總結
以上是生活随笔為你收集整理的android 8.0可以实现后台包活么,Android 8.0 应用保活实践 · Jaqen Ng的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 圣贝原浆啤酒 330ML ✘
- 下一篇: android5多窗口,教程 开启 Ne