android應用被殺死
『壹』 android app被殺死 alarmmanager能不能喚醒
可以喚醒的,但是得需要注意設置進程屬性。
在Android中,AlarmManager提供了不受休眠狀態的系統定時功能,其一般使用方法如下。
1、創建一個BroadcastReceiver類的子類,接收定時器事件:
public class MyReceiver extends BroadcastReceiver {
......
}
2、在AndroidMenifest.xml中定義上述廣播事件接收類的定義:
<receiver android:name=".MyReceiver">
</receiver>
3、在程序中在需要時設置定時器:
Intent intent = new Intent(context,MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP , SystemClock.elapsedRealtime() + ms, pendingIntent);
經過ms毫秒之後,MyReceiver會被調用,從而實現定時觸發。
『貳』 android應用進程被殺死後,如何接收得到廣播
在具有root許可權的進程管理器清理後,便相當於系統中的強制停止了,廣播接收器等自然都不能使用了。為了最大可能地防止被這類有root許可權的進程管理器殺掉,可以在程序退出的時候殺掉自己的進程,這樣自己的廣播接收器還是可以使用的,但那些進程管理器就找不到我們的進程了,因為已經被我們自己殺死了。但是在廣播接收器收到廣播後,我們的應用里程就會再被創建,因此在處理完廣播後要再次殺死我們自己的進程。
『叄』 三星成為殺死Android後台應用程序的非官方最嚴重罪犯
在過去的幾年中,三星在將One UI皮膚構建為市場上最好的Android版本之一方面取得了長足的進步。好吧,看來事情正朝著錯誤的方向前進。顯然,三星在Android 11中引入了一些激進的後台應用程序終止策略,這些策略以最差的方式排在榜首。
Don'tKillMyApp 是一個獨立的網站,根據Android OEM處理後台應用程序管理的方式對它們進行排名。該網站研究了AOSP和Google自己的Pixels如何處理後台應用程序,並從那裡查看了主要OEM如何改變該平台,從而導致用戶看到其後台應用程序意外關閉。
多年以來,該榜單幾乎保持不變,索尼和諾基亞等股票將近庫存的Android製造商始終處於較低的排名(越低越好),而小米,華碩,Oppo等公司的更積極的改變則獲得了更高的排名。華為長期以來一直位居榜首,一加緊隨其後,三星落後。好吧,那已經改變了。
由於該公司在Android 11升級中所做的更改,因此在主動殺死後台應用程序方面,三星現在位居第一。三星已實施一項新限制,以防止應用程序在前台服務中保持喚醒鎖定。此更改默認情況下處於啟用狀態,被描述為「與標准Android流程管理策略存在重大差異」,並且可能導致某些後台應用中斷,包括某些 健康 應用可能會丟失收集感測器數據的功能。
幸運的是,有一種解決方法。用戶可以進入幾個不同的設置頁面( 「設置」>「應用程序」>「您的應用程序」>「電池」>「電池優化」>「所有應用程序」>「 [應用程序名稱]」>「不優化」 )並關閉電池優化。
值得注意的是,這是在Google表示將採取措施完全阻止其Android合作夥伴的這種行為之後。顯然,三星沒有得到該備忘錄,也沒有完全忽略它。
由於過去幾個月一直在使用三星最新的Galaxy S21設備和Galaxy Z Fold 2的人,我不能說我直接注意到了這些問題。但是,這可能與以下事實直接相關:所有這些三星設備都擁有大量的RAM,從而導致後台應用程序無法使用。這個問題可能會使自己在三星價格較低的設備上更加清楚。
『肆』 Android 應用進程被殺不能收到推送,這正常嗎
非常正常!應用程序就是靠後台才能接受和發送推送消息,安卓手機都這樣!只要關了後台,就會收不到消息!當然,像蘋果或者安卓手機廠商一些高端旗艦機有推送服務,只保留一個系統程序就可以接收應用消息!
『伍』 android應用被強殺或應用被回收導致的空指針問題等其他問題
在開發中我們經常會遇見app退到後台再打開會出現空指針、頁面顯示不全等一系列奇怪的問題。
當我們的進程被強殺或者被回收的時候,Android系統雖然讓你的進程沒有了,但是此進程中Activity中棧的信息還是存在的,也就是說此時當你點開此應用的時候程序中的Activity棧信息任然存在,只不過Activity中的數據都沒有了,需要重新創建新的Activity數據。
分別涉及到:一個單例ConstantInstance 基類BaseAcyivity 首頁MainActivity 啟動頁IndexActivity
『陸』 Android APP在後台被殺問題修復
目前項目採用單 Activity 模式,頁面採用 Jetpack Navigation 導航
布局如下:Splash -> Home -> Detail
不做任何事情
持有 LiveData 類型變數 hasSDKInit,根據SDK初始化成功與否設置 true 或者 false
調用 SDK 實現相關功能。
很明顯,被殺後與 Activity 生命周期關聯的 ViewModel 也結束了,與新打開 APP 的區別是,這時候是沒有通過 Splash 去 初始化 SDK 的, Home 直接調用一個沒有初始化的SDK 實例當然就報錯了。
這樣我們把 SDK 的初始化挪到 Activity::onCreate 就行了。
Fragment 中通過``ViewModelProvider(requireActivity()).get(GlobalViewModel::class.java)`獲取。
把 init SDK 放到 ViewModel 的構造函數中,並將 initSDK 方法私有化,不允許從外部調用
context 通過新建 ViewModelFactory 類傳入。
Google 官方不推薦 ViewModel 持有任何形式的 Context,如果確實要用,可以考慮單例或者 AndroidViewModel
Splash 頁面監聽 hasSDKInit 邏輯不變。
Home 頁面原有邏輯不變,必要時加上對 hasSDKInit 的監聽,true 才可進行後續操作。
而,如果SDK 的 init 不依賴網路等其他因素,默認情況下因為所有調用都在主線程,那麼 就不用做監聽。
『柒』 如何防止android app被kill
相較於/data/app下的應用,放在/system/app下的應用享受更多的特權,比如若在其Manifest.xml文件中設置persistent屬性為true,則可使其免受out-of-memory
killer的影響。如應用程序'Phone'的AndroidManifest.xml文件:
<application
android:name="PhoneApp"
android:persistent="true"
android:label="@string/dialerIconLabel"
android:icon="@drawable/ic_launcher_phone">
...
</application>
設置後app提升為系統核心級別,任何情況下不會被kill掉, settings->applications裡面也會屏蔽掉stop操作。
這樣設置前的log: Proc #19: adj=svc /B 4067b028 255:com.xxx.xxx/10001 (started-services)
# cat /proc/255/oom_adj
4
設置後的log: PERS #19: adj=core /F 406291f0 155:com.xxx.xxx/10001 (fixed)
# cat /proc/155/oom_adj
-12 # 這是CORE_SERVER_ADJ
註:init進程的oom_adj為-16(即SYSTEM_ADJ): cat /proc/1/oom_adj
Android相關部分分析:
在文件frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中有以下的代碼:
final
ProcessRecord addAppLocked(ApplicationInfo info) {
ProcessRecord
app = getProcessRecordLocked(info.processName, info.uid);
if
(app == null) {
app
= newProcessRecordLocked(null, info, null);
mProcessNames.put(info.processName,
info.uid, app);
updateLruProcessLocked(app,
true, true);
}
if
((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
==
(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
app.persistent
= true;
app.maxAdj
= CORE_SERVER_ADJ; //
這個常數值為-12。
}
if
(app.thread == null && mPersistentStartingProcesses.indexOf(app)
< 0) {
mPersistentStartingProcesses.add(app);
startProcessLocked(app,
"added application", app.processName);
}
return
app;
}
可
見要想成為core service (即app.maxAdj =
CORE_SERVER_ADJ(-12)),應用程序需要FLAG_SYSTEM和FLAG_PERSISTENT兩個標志,FLAG_SYSTEM指
的是應用位於/system/app下,FLAG_PERSISTENT就是指persistent屬性。
而對於frameworks/base/services/java/com/android/server/SystemServer.java,則調用
ActivityManagerService.setSystemProcess();
把自己的 app.maxAdj 設置成SYSTEM_ADJ,即-16。
原理:
Android中的進程是託管的,當系統進程空間緊張的時候,會依照優先順序自動進行進程的回收。由此帶來三個問題:
1)
回收規則: 什麼時候回收與回收哪一個?
2)
避免誤殺: 如何阻止被回收?
3)
數據恢復與保存: 被回收了怎麼辦?
Android將進程分為6個等級,它們按優先順序順序由高到低依次是:
1.前台進程(
FOREGROUND_APP)
2.可視進程(VISIBLE_APP
)
3.
次要服務進程(SECONDARY_SERVER )
4.後台進程
(HIDDEN_APP)
5.內容供應節點(CONTENT_PROVIDER)
6.空進程(EMPTY_APP)
特徵:
1.如果一個進程裡面同時包含service和可視的activity,那麼這個進程應該歸於可視進程,而不是service進程。
2.另外,如果其他進程依賴於它的話,一個進程的等級可以提高。例如,一個A進程里的service被綁定到B進程里的組件上,進程A將總被認為至少和B進程一樣重要。
3.系統中的phone服務被劃分到前台進程而不是次要服務進程.
在android中,進程的oom_adj值也就代表了它的優先順序。oom_adj值越高代表該進程優先順序越低。文件/init.rc中有以下屬性設置:
setprop
ro.FOREGROUND_APP_ADJ 0
setprop
ro.VISIBLE_APP_ADJ 1
setprop
ro.SECONDARY_SERVER_ADJ 2
setprop
ro.HIDDEN_APP_MIN_ADJ 7
setprop
ro.CONTENT_PROVIDER_ADJ 14
setprop
ro.EMPTY_APP_ADJ 15
/init.rc中,將PID為1的進程(init進程)的oom_adj設置為SYSTEM_ADJ(-16):
#
Set init its forked children's oom_adj.
write
/proc/1/oom_adj -16
查看本機設置:
cat /sys/mole/lowmemorykiller/parameters/adj
0,1,2,7,14,15
回收時機:
文件/init.rc中:
setprop
ro.FOREGROUND_APP_MEM 1536 // 6M
setprop
ro.VISIBLE_APP_MEM 2048 // 8M
setprop
ro.SECONDARY_SERVER_MEM 4096 // 16M
setprop
ro.HIDDEN_APP_MEM 5120 // 20M
setprop
ro.CONTENT_PROVIDER_MEM 5632 // 22.4M
setprop
ro.EMPTY_APP_MEM 6144 // 24M
這些數字也就是對應的內存閾值,一旦低於該值,Android便開始按順序關閉相應等級的進程。
注意這些數字的單位是page: 1 page = 4 kB。所以上面的六個數字對應的就是(MB): 6,8,16,20,22,24。
查看現在的內存閾值設置:
cat /sys/mole/lowmemorykiller/parameters/minfree
要想重新設置該值(對應不同的需求):
echo "1536,2048,4096,5120,15360,23040">/sys/mole/lowmemorykiller/parameters/minfree
這樣當可用內存低於90MB的時候便開始殺死"空進程",而當可用內存低於60MB的時候才開始殺死"內容供應節點"類進程。
具體的回收實現在ActivityManagerService.java中的函數trimApplications():
1.首先移除package已被卸載的無用進程;
2.基於進程當前狀態,更新oom_adj值,然後進行以下操作:
1)
移除沒有activity在運行的進程;
2)
如果AP已經保存了所有的activity狀態,結束這個AP。
3.
最後,如果目前還是有很多activities 在運行,那麼移除那些activity狀態已經保存好的activity。
更新oom_adj的值:
在ActivityManagerService.java文件的ComputeOomAdjLocked() 中計算出進程的oom_adj,例如:
if
(app == TOP_APP) {
//
The last app on the list is the foreground app.
adj
= FOREGROUND_APP_ADJ;
app.adjType
= "top-activity";
}
Android kernel中的low memory killer
Android的Low Memory Killer根據需要(當系統內存短缺時)殺死進程釋放其內存,源代碼在kernel/drivers/misc/lowmemorykiller.c中。簡單說,就是尋找一個最合適的進程殺死,從而釋放它佔用的內存。
最合適的進程是:
• oom_adj越大
• 佔用物理內存越多
一旦一個進程被選中,內核會發送SIGKILL信號將之殺死:
for_each_process(p)
{
……
if(selected
== NULL || p->oomkilladj
> selected->oomkilladj ||
(p->oomkilladj
== selected->oomkilladj && tasksize > selected_tasksize))
{
selected
= p;
}
}
if(selected
!= NULL) {
force_sig(SIGKILL,
selected);
}
查看LRU列表:adb shell mpsys activity
當activitydemo在前台時:
包含Service的進程的優先順序比較高,在computeOomAdjLocked中將其分為了兩小類:
static
final int MAX_SERVICE_INACTIVITY = 30*60*1000;
if
(now < (s.lastActivity+MAX_SERVICE_INACTIVITY)) {
if
(adj > SECONDARY_SERVER_ADJ) {
adj
= SECONDARY_SERVER_ADJ;
app.adjType
= "started-services";
app.hidden
= false;
}
}
if
(adj > SECONDARY_SERVER_ADJ) {
app.adjType
= "started-bg-services";
}
完全讓進程不被kill是不可能的,我們可以通過一些操作,使進程被kill的幾率變小:
1)
提高進程的優先順序:
*
後台操作採用運行於前台的Service形式,因為一個運行著service的進程比一個運行著後台activity的等級高;
*
按back鍵使得進程中的activity在後台運行而不是destory,需重載back按鍵(沒有任何activity在運行的進程優先被殺).
*
依賴於其他優先順序高的進程;
2)
強制修改進程屬性:
*
在進程中設置:setPersistent(true);
*
在Manifest文件中設置(如上)。
『捌』 為什麼 12G 內存的 Android 手機依舊會被殺後台
不知不覺間 Android 陷入了一個關於「後台」的怪圈:一邊各大廠商陸續推出了 12G RAM 的手機,另一邊你剛剛放到後台的下載任務沒有如預期那樣後台掛機下載,打開微信發現還得陪啟動畫面的孤獨小人共賞藍色星球、按照教程辛辛苦苦做了半個小時的 Tasker 規則、卻沒有按照計劃自動執行……
於是一個耳熟能詳的句子開始在我們腦海中成型—— 我的後台又被「殺」了 。
應用開發者的「控訴」
遇到上述問題的人不止你一個,很多人選擇向這些應用的開發者反饋問題,殊不知問題其實不在應用本身。
Android 平台著名睡眠追蹤應用 Sleep as Android 的開發團隊 Urbandroid Team 不堪其擾,索性上線了一個名為「別『殺』我應用」的網站,矛頭直指手機廠商糟糕的後台管理機制。
以三星為例,Urbandroid Team 稱,三星的部分機型在升級到基於 Android 9 的 One UI 後「殺後台」現象變得尤為嚴重,自適應電池(Adaptive Battery)機制相比原生 Android 變得尤為激進,3 天內沒有啟動過的應用甚至無法從後台再次啟動。最為糟糕的情況是,如果你安裝了一個可以自動跳過周末的第三方鬧鍾,那這個鬧鍾應用很有可能不會像系統鬧鍾那樣在下周一早上准時響起……
正如「別『殺』我應用」網站上控訴的那樣,擁有類似機制的還包括華為、一加、小米、華碩等等手機廠商的定製版 Android 系統,它們管理後台的方式大同小異,但都秉承著 iOS 上那一套「劃掉就殺掉」的原則——當我們把某款應用的任務卡片從多任務界面劃去,它們也就徹底從手機後台中抹除掉了。
這里你可能會問很多問題:
我們得從一些基礎的原理說起。
Android 的內存回收機制
在 官方文檔 中,Google 將「不受應用自身直接控制的應用進程生命周期」描述為 Android 最為基礎也最為獨特的核心特性,這里我們不妨將「應用進程生命周期」暫時理解為文章開頭和第一部分所說的「後台」或「後台進程(process)」。
所以 Android 應用的後台進程去留本應是由 Android 系統來決定的 。
當可用運行內存空間不足時,Android 系統會自行決定對特定應用後台進程佔用的空間進行回收釋放,這個過程中 Android 揮舞著的那把大刀,叫做 LMK(Low Memory Killer)。那 LMK 又是如何判斷哪些應用可以被「殺」掉、哪些應用又該暫時放過的呢?
每個應用都有各種各樣的組成部分,其中特定組件的運行狀態共同組成了一套供 LMK 進行內存回收的「優先順序」參考,包括:前台進程、可見進程、服務進程和緩存進程。
前台進程、可見進程和服務進程往往與我們正在手機上執行的操作直接或間接相關 ,比如正在前台供我們交互和操作的活動窗口(Activity)、正在通過廣播接收器(BroadcastReceiver)等待觸發的 Tasker 規則、正在後台通過 Wi-Fi 網路自動上傳備份照片的 Google Photos 以及前面提到的有待觸發的鬧鍾等等。這些進程優先順序從高到低依次遞減,LMK 一般不會觸及。
緩存進程則是那些暫時放在運行內存中的部分,也是和本文探討話題主要相關的重點 。
只有在極端情況下 ,比如 Android 系統在回收掉所有緩存進程後發現空閑內存依然不夠用(比如在低內存的「老爺機」上運行《崩壞 3》),這時 LMK 才會根據優先順序繼續對服務進程、可見進程和前台進程採取回收策略。 而當這些我們在正常使用中能夠直觀感受到的進程都不得不被被回收時 ,文章開頭提到的微信重載、音樂中斷、下載消失等等現象也就出現了。
誰動了你的後台
在可用內存充裕的情況下遭遇「殺後台」現象,一方面可能是 LMK 這把「大刀」出了問題(常見於 Android 9 時期的 Pixel 3 用戶),另一方面則有可能是其它規則額外干預了 Android 系統正常的內存回收機制。
這里提到的「其它規則」主要有兩種形式,一種類似部分華為設備上預裝的「省電精靈」,它會將所有沒有加入後台白名單中的應用後台統統清除,另一種則依託於 Google 推出的 後台檢查 、 後台限制 和 自適應電池 等功能進行「魔改」,讓這些功能的實際效果遠超預期,甚至達到意料之外的負面效果。
根據 Don't kill my app! 的統計,第二種後台干預機制在三星、一加和早期的諾基亞機型中常見,這里廠商們通常會用到一種類似「白名單」的方法來進行過濾。
以三星手機基於 Android 9 的 One UI 為例,除了微信、QQ 等國內常見應用,One UI 默認會為所有第三方應用關閉「允許後台活動」這一選項,同時開啟「優化電池使用量」這一功能。
部分搭載氫 OS 的一加機型則將上面提到的應用進程進行拆分,除了基於原生 Android 的後台限制、電池優化,還有一套名為「自啟動管理」的設置來對應用的自啟動進行管理以及一套名為「深度優化」的電池優化機制,後者會造成很多智能手錶、手環設備在一段時間後丟失與手機的藍牙連接,最終導致睡眠追蹤、運動記錄等等功能的失效。
問題在於上述功能埋藏較深,一般用戶在安裝應用後往往不會第一時間前往設置,一加的氫 OS 更是以系統更新之後自動重置部分用戶設置聞名,那些需要在後台正常工作的應用,因此也被都被直接扔進了原生 Android 中用來限制「毒瘤」應用的「黑箱」里。
換句話說,國內大部分定製 ROM 在後台管理這件事情上都選擇採用一種「 寧肯錯殺一千不肯放過一個 」的做法。
關聯閱讀: 控制頻繁啟動的「毒瘤」,Android 9.0 用這些方法讓你的手機更省電
多任務管理還是後台管理?
從某種程度上來說,國產手機廠商在 Android 後台管理上的做法雖然偏激,但它們都是國內特殊生態下的產物 。
一方面,盡管 Google 為 Android 設想了一套非常理想化的應用運行與後台管理機制 ,但大多數於原生 Android 中行之有效的後台管理機制在國內似乎都會變成「雞肋」。
如果 Google 有 100 種提升 Android 應用運行效率,保證後台綠色、純凈的方法,國內毒瘤應用開發商就有 101 種繞過這些限制的方法。
藉助共用的第三方推送服務實現鏈式喚醒、藉助透明的懸浮窗保證後台存活、通過不斷獲取定位的方式來避免進程被系統回收……不管是出於實現消息推送這樣單純的目的還是為了不斷喚醒用戶設備以實現 KPI 目標這種下作的行為,在國內 Android 生態中均有出現。
雖然國內外的具體環境有所不同,但這類設計不規范的 Android 應用帶來的問題卻是一樣的,這類應用放在後台不僅不會為我們帶來便利,反而還會因為頻繁喚醒設備帶來不小的耗電問題。待機續航問題作為懸在國產 Android 機頭頂的幾把利劍之一,手機廠商不得不各自從系統層面推出自家的應對機制——這就有了上面提到的各種偏激式的後台管理方法。
另一方面,這里還涉及到一個非常重要的概念區分 :多任務管理和後台管理究竟是不是一回事?
國內 Android 生態由於早期受 iOS 影響較深,無論是開發商還是用戶都更傾向於把「將應用卡片從多任務列表裡劃掉」的行為理解為清除對應用的後台進程。在上面提到的特殊生態環境的影響之下,這里被清除的後台進程往往又包括那些用於保證應用後台運行的可見進程、服務進程乃至前台進程在內。
在酷安應用市場,甚至還有得以在原生 Android 上實現類似「劃掉卡片即停止運行」效果的應用,iOS 的後台管理理念在國內有多麼深入人心可見一斑。
但這種後台管理理念卻與 Google 對 Android 的多任務管理設計方式相悖。Google 一直以來都將 Android 手機上呼出任務卡片的那個界面叫做 Recents,最近幾個版本的 Android 系統更是將其本地化為「概覽」。結合 Google 在 Android 9 和 Android 10 手勢交互上的變革,注重多任務管理而非後台管理的意圖也越發明顯。
當最近運行的應用以一張張卡片的形式呈現在我們面前時,Google 想要呈現的是一個能夠讓我們在不同任務間快速切換的多任務交互,而在理想狀態下,後台管理則是交由系統處理、完全不應被用戶感知的。
至於如何理性看待 Android 平台的後台管理,這里我們不妨借用綠色守護開發者 @OasisFeng 在「Android 多任務界面的劃除交互」這個話題上的 答疑 來回答這個問題:
換句話說, 今後絕大部分需要在海外市場搭載 Google 服務上市的手機都必須滿足這個要求 。
小結
就在上周三(9 月 25 日),醞釀已久的安卓統一推送聯盟正式宣布收到華為、OPPO、一加和 realme 四家公司的進度確認,雖然 Google 的缺席也讓國內 Android 生態也變得異常復雜,但國內 Android 設備也能用上的統一推送服務也算是終於邁出了具有實際意義的第一步。
只是距離轉變人們對 Android「殺後台」這件事的看法依然還有很長的路要走。事實上,國內早在四五年前就出現過一次對「Android 需不需要『殺後台』」問題的科普,但收效甚微,盲從 iOS 設計風格和交互邏輯國內 Android 廠商要負很大一部分責任。
希望靠譜、省電的統一推送系統能成為改觀的第一步,也希望 @OasisFeng 口中那個甚至可以跨越設備重啟恢復「後台狀態」的理想化生態早日到來——至於當下,我們依然只能見招拆招,遇到應用無法正常執行後台任務時打開手機設置仔細翻找、設置,把它們扔進白名單或是給它們的後台卡片套個「鎖」……
下載、安裝了一款非白名單應用,該如何確保它不被「殺後台」呢?歡迎在評論區把你的設置方法分享給大家。