不錯(cuò)的文章!
http://weishu.me/2020/01/16/a-keep-alive-method-on-android/
http://www.52im.net/thread-2893-1-1.html
http://weishu.me/2021/01/25/another-keep-alive-method/

還有后臺(tái)CPU消耗過(guò)多也會(huì)導(dǎo)致系統(tǒng)殺進(jìn)程。
總結(jié)了以上被殺死的場(chǎng)景分析,我們得出兩種技術(shù)方案:
Ⅰ. 提升進(jìn)程優(yōu)先級(jí)(降低被殺死的概率)
Ⅱ.進(jìn)程殺死后,拉活進(jìn)程
一 提升進(jìn)程優(yōu)先級(jí)的方法
1像素懸浮層
監(jiān)控手機(jī)鎖屏解鎖事件,在屏幕鎖屏?xí)r啟動(dòng)1個(gè)像素的 Activity,在用戶(hù)解鎖時(shí)將 Activity 銷(xiāo)毀掉。注意該 Activity 需設(shè)計(jì)成用戶(hù)無(wú)感知。
通過(guò)該方案,可以使進(jìn)程的優(yōu)先級(jí)在屏幕鎖屏?xí)r間由4提升為最高優(yōu)先級(jí)1,主要解決第三方應(yīng)用及系統(tǒng)管理工具在檢測(cè)到鎖屏事件后一段時(shí)間(一般為5分鐘以?xún)?nèi))內(nèi)會(huì)殺死后臺(tái)進(jìn)程,已達(dá)到省電的目的問(wèn)題
實(shí)現(xiàn)方案:
首先定義 Activity,并設(shè)置 Activity 的大小為1像素:

其次,從 AndroidManifest 中通過(guò)如下屬性,排除 Activity 在 RecentTask 中的顯示:

最后,控制 Activity 為透明:

2) 將Service設(shè)置為前臺(tái)服務(wù)
Android 中 Service 的優(yōu)先級(jí)為4,通過(guò) setForeground 接口可以將后臺(tái) Service 設(shè)置為前臺(tái) Service,使進(jìn)程的優(yōu)先級(jí)由4提升為2,從而使進(jìn)程的優(yōu)先級(jí)僅僅低于用戶(hù)當(dāng)前正在交互的進(jìn)程,與可見(jiàn)進(jìn)程優(yōu)先級(jí)一致,使進(jìn)程被殺死的概率大大降低。
從 Android2.3 開(kāi)始調(diào)用 setForeground 將后臺(tái) Service 設(shè)置為前臺(tái) Service 時(shí),必須在系統(tǒng)的通知欄發(fā)送一條通知,也就是前臺(tái) Service 與一條可見(jiàn)的通知時(shí)綁定在一起的。
對(duì)于不需要常駐通知欄的應(yīng)用來(lái)說(shuō),該方案雖好,但卻是用戶(hù)感知的,無(wú)法直接使用。
通過(guò)實(shí)現(xiàn)一個(gè)內(nèi)部 Service,在 ?KeepLiveService 和其內(nèi)部 Service 中同時(shí)發(fā)送具有相同 ID 的 Notification,然后將內(nèi)部 Service 結(jié)束掉。隨著內(nèi)部 Service 的結(jié)束,Notification 將會(huì)消失,但系統(tǒng)優(yōu)先級(jí)依然保持為2。
該方案雖好,但卻是用戶(hù)感知的,無(wú)法直接使用。
通過(guò)實(shí)現(xiàn)一個(gè)內(nèi)部 Service,在 ?KeepLiveService 和其內(nèi)部 Service 中同時(shí)發(fā)送具有相同 ID 的 Notification,然后將內(nèi)部 Service 結(jié)束掉。隨著內(nèi)部 Service 的結(jié)束,Notification 將會(huì)消失,但系統(tǒng)優(yōu)先級(jí)依然保持為2。
二 死了被拉起的方法
1 利用android系統(tǒng)支持的能力
1.1 利用Android賬戶(hù)同步機(jī)制拉活進(jìn)程
前在做項(xiàng)目的時(shí)候,為了保證APP可以在手機(jī)長(zhǎng)期存活,我找到了利用Android賬戶(hù)同步機(jī)制來(lái)拉活A(yù)PP的進(jìn)程。在華為6.0、4.4的版本測(cè)試可以拉活,在oppo5.0版本測(cè)試可以拉活,但是在小米6.0下,殺死進(jìn)程后就無(wú)法通過(guò)賬戶(hù)機(jī)制拉活,我猜測(cè)是小米對(duì)賬戶(hù)機(jī)制進(jìn)行了修改。SyncAdapter介紹
Android提供了SyncAdapter類(lèi)用于需要同步本地?cái)?shù)據(jù)和在線(xiàn)賬戶(hù)信息的應(yīng)用,如電子郵件的定時(shí)收取、筆記應(yīng)用的云備份、天氣應(yīng)用的及時(shí)同步等。它的優(yōu)勢(shì)在于可以根據(jù)不同條件自動(dòng)發(fā)起數(shù)據(jù)傳輸,比如數(shù)據(jù)變更,間隔一定時(shí)間,或者是每天定時(shí)。而且,系統(tǒng)會(huì)將暫時(shí)不能運(yùn)行的操作添加到隊(duì)列里,在可能的情況下重新發(fā)起。
漏洞原理:
因?yàn)橘~戶(hù)同步服務(wù)是系統(tǒng)維護(hù)的一個(gè)服務(wù),所以我們的同步的進(jìn)程是跟隨系統(tǒng)的生命周期走,這就意味著只要不關(guān)機(jī),這個(gè)服務(wù)會(huì)一直運(yùn)行,幫我們同步賬號(hào)。我們看一下功能流程圖:

圖是我總結(jié)了Android利用SyncAdapter同步賬戶(hù)的邏輯,而開(kāi)發(fā)者可以隨意重寫(xiě)onPerformSync()的內(nèi)容,因此我們可以在onPerformSync()方法中去開(kāi)啟我們APP的Activity、Service等,一旦啟動(dòng)了Activity、Service之后,就等于拉活了我們APP的進(jìn)程。

由于該機(jī)制可定制度太高,而且比較冷門(mén)的功能,因此google一直沒(méi)有去修補(bǔ)這塊,不過(guò)小米有閹割掉了這里的拉活,而且剛剛用原生Android 8.0系統(tǒng)測(cè)了一下,貌似也是拉活不了。8.0以下都可以拉活。
總結(jié)
Android賬戶(hù)機(jī)制本身意義是google為了方便用戶(hù),不需要總是APP登錄和驗(yàn)證賬戶(hù)信息,由系統(tǒng)來(lái)維護(hù)這些賬戶(hù)的驗(yàn)證。換個(gè)思路,這就是為攻擊者提供了可以利用的提取系統(tǒng)權(quán)限的攻擊點(diǎn)。我們?cè)谥蟮难芯靠梢远嗾艺矣邢到y(tǒng)提供的服務(wù)或者間接調(diào)用了系統(tǒng)服務(wù)的功能,這樣可以讓系統(tǒng)為我們“服務(wù)”。
目前大多數(shù)手機(jī)廠商針對(duì)于賬戶(hù)機(jī)制這些相對(duì)冷門(mén)的功能沒(méi)有太大的關(guān)注,所以在各自品牌手機(jī)的rom包中,對(duì)于這些機(jī)制也未再進(jìn)行認(rèn)真的檢驗(yàn)處理,這樣也就導(dǎo)致很多原生系統(tǒng)存在的漏洞,在各大手機(jī)廠商上面同樣可以進(jìn)行攻擊,所以需要系統(tǒng)開(kāi)發(fā)人員認(rèn)真的關(guān)注這些功能。
1.2 預(yù)裝應(yīng)用會(huì)默認(rèn)授予 ACCESS_NOTIFICATION 權(quán)限
https://stackoverflow.com/questions/31145981/notification-listener-service-for-system-app-without-user-intervention
Notification Listener Service for System app without user intervention
I have a system app. In this app I want to capture Notifications, so I'm using NotificationListenerService. But for this service to start we need to do startActivity(new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS")) and this will get us to the notification access permissions where the user has to check the app and give permission. As my app is a system app is it possible to give permission by default without having the user check the box. I have already tried uses-permission but that is not working. Any help here would be much appreciated.
1.3 Broadcast 拉活:
1.3.1 監(jiān)聽(tīng)一堆系統(tǒng)靜態(tài)廣播
監(jiān)聽(tīng)ACTION_BOOT_COMPLETED
在發(fā)生特定系統(tǒng)事件時(shí),系統(tǒng)會(huì)發(fā)出響應(yīng)的廣播,通過(guò)在 AndroidManifest 中“靜態(tài)”注冊(cè)對(duì)應(yīng)的廣播監(jiān)聽(tīng)器,即可在發(fā)生響應(yīng)事件時(shí)拉活。

但是有如下問(wèn)題:
a. 廣播接收器被管理軟件、系統(tǒng)軟件通過(guò)“自啟管理”等功能禁用的場(chǎng)景無(wú)法接收到廣播,從而無(wú)法自啟。
b. 系統(tǒng)廣播事件不可控,只能保證發(fā)生事件時(shí)拉活進(jìn)程,但無(wú)法保證進(jìn)程掛掉后立即拉活。
c? 極光sdk 通常的廣播拉起
07-07 15:27:39.549 653 728 V ActivityManager: Broadcast: Intent { flg=0x14 cmp=com.sohu.sohuvideo/cn.jpush.android.service.AlarmReceiver (has extras) } ordered=true userid=0
07-07 15:27:39.550? 653? 728 I ActivityManager: Broadcast intent Intent { flg=0x14 cmp=com.sohu.sohuvideo/cn.jpush.android.service.AlarmReceiver (has extras) } on background queue
07-07 15:27:39.552? 653? 669 I BroadcastQueue: Need to start app process [background] com.sohu.sohuvideo from com.sohu.sohuvideo for broadcast BroadcastRecord{bd80fa6 u0 null}
07-07 15:27:39.553? 653? 669 V ActivityManager: startProcess: name=com.sohu.sohuvideo app=null knownToBeDead=true thread=null pid=-1
07-07 15:27:39.555? 653? 669 I ActivityManager: Posting procStart msg for 0:com.sohu.sohuvideo/u0a79
07-07 15:27:39.618? 653? 671 I ActivityManager: Start proc 25681:com.sohu.sohuvideo/u0a79 for broadcast?com.sohu.sohuvideo/cn.jpush.android.service.AlarmReceiver
1.3.2 監(jiān)聽(tīng)第三方應(yīng)用的靜態(tài)廣播
與接收系統(tǒng)廣播類(lèi)似,不同的是該方案為接收第三方應(yīng)用廣播。
通過(guò)反編譯第三方應(yīng)用,如:手機(jī)QQ、微信、支付寶、UC瀏覽器等找出它們外發(fā)的廣播,在應(yīng)用中進(jìn)行監(jiān)聽(tīng),這樣當(dāng)這些應(yīng)用發(fā)出廣播時(shí),就會(huì)將我們的應(yīng)用拉活。
有效程度除與系統(tǒng)廣播一樣的因素外, 第三方應(yīng)用的廣播屬于應(yīng)用私有,當(dāng)前版本中有效的廣播,在后續(xù)版本隨時(shí)就可能被移除或被改為不外發(fā)。
與接收系統(tǒng)廣播類(lèi)似,不同的是該方案為接收第三方應(yīng)用廣播。
通過(guò)反編譯第三方應(yīng)用,如:手機(jī)QQ、微信、支付寶、UC瀏覽器等找出它們外發(fā)的廣播,在應(yīng)用中進(jìn)行監(jiān)聽(tīng),這樣當(dāng)這些應(yīng)用發(fā)出廣播時(shí),就會(huì)將我們的應(yīng)用拉活。
有效程度除與系統(tǒng)廣播一樣的因素外, 第三方應(yīng)用的廣播屬于應(yīng)用私有,當(dāng)前版本中有效的廣播,在后續(xù)版本隨時(shí)就可能被移除或被改為不外發(fā)。
主要是實(shí)現(xiàn)也一個(gè)監(jiān)聽(tīng)開(kāi)機(jī)的廣播,和一個(gè)周期性的鬧鐘,不過(guò)比較致命的是耗電量是很高的。
1.3.3 AlarmManager喚醒
主要是實(shí)現(xiàn)也一個(gè)監(jiān)聽(tīng)開(kāi)機(jī)的廣播,和一個(gè)周期性的鬧鐘,不過(guò)比較致命的是耗電量是很高的。
1.3.4 Native進(jìn)程拉起
原理就是通過(guò) JNI fork出一個(gè) c 進(jìn)程,c 進(jìn)程監(jiān)控主進(jìn)程是否存活,主要通過(guò)管道和文件監(jiān)控的方式實(shí)現(xiàn)監(jiān)控,發(fā)現(xiàn)主進(jìn)程死后,通過(guò)調(diào)起一個(gè) service 將主進(jìn)程拉活
具體的實(shí)現(xiàn)方案:


此方案存在兩個(gè)問(wèn)題:
1.如果直接使用 JNI fork 出一個(gè)子進(jìn)程,這樣會(huì)存在一個(gè)內(nèi)存較大問(wèn)題,也就是主版占用多大內(nèi)存,native 進(jìn)程也占用多大內(nèi)存,因此需要去寫(xiě)一個(gè)獨(dú)立的 c 進(jìn)程來(lái)降低內(nèi)存大小
2.上面講到5.0以上的系統(tǒng)會(huì)將根據(jù) uid 殺進(jìn)程,因此 native 進(jìn)程也會(huì)被殺死,因此在5.0以上此方案失效的。
1.3.5 JobSchedule機(jī)制拉活
Android5.0 以后系統(tǒng)對(duì) Native 進(jìn)程等加強(qiáng)了管理,Native 拉活方式失效。系統(tǒng)在 Android5.0 以上版本提供了 JobScheduler 接口,系統(tǒng)會(huì)定時(shí)調(diào)用該進(jìn)程以使應(yīng)用進(jìn)行一些邏輯操作。

1.3.2? igexin的保活手段
com.igexin.sdk.PushReceiver
1.3.3
后臺(tái)監(jiān)聽(tīng)各種系統(tǒng)信息的廣播、timetick之類(lèi)的
1.4 三方SDK
極光/igexin SDK.
1.5 service拉起
cn.jpush.android.service.DaemonService
1.6??添加Manifest文件屬性值為android:persistent=“true”
app.persistent = true不僅僅標(biāo)志著此apk不能輕易的被kill掉,亦或在被kill掉后能夠自動(dòng)restart,并且還涉及到了進(jìn)程的優(yōu)先級(jí)。將被設(shè)置為CORE_SERVER_ADJ,此值為-12,而核心進(jìn)程init的值為-16。當(dāng)前正在前臺(tái)運(yùn)行的進(jìn)程的值為0。如果應(yīng)用能設(shè)置這個(gè)屬性,那就真的可以做到?;睿?yàn)樗娴目梢詺⒉凰?,像系統(tǒng)的keyguard進(jìn)程,media進(jìn)程,且這些進(jìn)程的adj都是負(fù)數(shù),代表了前臺(tái)activity黑屏了他們也不會(huì)死。但是這個(gè)屬性需要系統(tǒng)shareuid,然后編譯不過(guò),因?yàn)樾枰到y(tǒng)簽名!
因此,要弄這個(gè)屬性需獲取兩個(gè)關(guān)鍵的信息:
(1).在apk的AndroidManifest.xml文件中設(shè)置android:persistent=true
(2).此apk需要放入到system/app目錄下,成為一個(gè)systemapp
最主要的是讓程序成為系統(tǒng)程序,這個(gè)可以做到嗎?如果你技術(shù)過(guò)硬是可以嘗試下的!首先弄個(gè)自動(dòng)root的apk,加殼放到程序中,然后程序運(yùn)行的時(shí)候,自動(dòng)運(yùn)行自動(dòng)root的apk,獲取root權(quán)限,然后在native層中,使用命令的方式把程序移到system/app目錄下,成為系統(tǒng)程序!
1.7? 覆寫(xiě)Service的onDestroy方法
在設(shè)置里面的正在運(yùn)行,注意是正在運(yùn)行里面,點(diǎn)擊關(guān)閉,會(huì)走onDestroy回調(diào)方法,你在這里可以把自己?jiǎn)?dòng)起來(lái)。注意是正常關(guān)閉的時(shí)候是會(huì)自己?jiǎn)?dòng)起來(lái),可是使用第三方的清理軟件360,root過(guò)的360,force close這些來(lái)搞,壓根不會(huì)走到onDestory的方法。
1.8?雙Service守護(hù)進(jìn)程?;睿ㄟ@個(gè)也很流氓,不過(guò)如果不提高優(yōu)先級(jí)(允許被殺),也算稍微良心)
前文我們分析過(guò)Android Binder的訃告機(jī)制:如果Service Binder實(shí)體的進(jìn)程掛掉,系統(tǒng)會(huì)向Client發(fā)送訃告,而這個(gè)訃告系統(tǒng)就給進(jìn)程保活一個(gè)可鉆的空子??梢酝ㄟ^(guò)兩個(gè)進(jìn)程中啟動(dòng)兩個(gè)binder服務(wù),并且互為C/S,一旦一個(gè)進(jìn)程掛掉,另一個(gè)進(jìn)程就會(huì)收到訃告,在收到訃告的時(shí)候,喚起被殺進(jìn)程。邏輯如下下:

首先編寫(xiě)兩個(gè)binder實(shí)體服務(wù)PairServiceA ,PairServiceB,并且在onCreate的時(shí)候相互綁定,并在onServiceDisconnected收到訃告的時(shí)候再次綁定。
ublicclassPairServiceAextendsService{@Nullable@OverridepublicIBinderonBind(Intentintent){returnnewAliveBinder();}@OverridepublicvoidonCreate(){super.onCreate();bindService(newIntent(PairServiceA.this,PairServiceB.class),mServiceConnection,BIND_AUTO_CREATE);}privateServiceConnectionmServiceConnection=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){}@OverridepublicvoidonServiceDisconnected(ComponentNamename){bindService(newIntent(PairServiceA.this,PairServiceB.class),mServiceConnection,BIND_AUTO_CREATE);ToastUtil.show("bind A");}};
與之配對(duì)的B
publicclassPairServiceBextendsService{@Nullable@OverridepublicIBinderonBind(Intentintent){returnnewAliveBinder();}@OverridepublicvoidonCreate(){super.onCreate();bindService(newIntent(PairServiceB.this,PairServiceA.class),mServiceConnection,BIND_AUTO_CREATE);}privateServiceConnectionmServiceConnection=newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamename,IBinderservice){}@OverridepublicvoidonServiceDisconnected(ComponentNamename){bindService(newIntent(PairServiceB.this,PairServiceA.class),mServiceConnection,BIND_AUTO_CREATE);}};}
之后再M(fèi)anifest中注冊(cè),注意要進(jìn)程分離
1.9 通過(guò)START_STICKY與START_REDELIVER_INTENT實(shí)現(xiàn)被殺喚醒
通過(guò)startService啟動(dòng)的Service,如果沒(méi)用唄stopService結(jié)束掉,在進(jìn)程被殺掉之后,是有可能重新啟動(dòng)的,實(shí)現(xiàn)方式:
@OverridepublicintonStartCommand(Intentintent,intflags,intstartId){returnSTART_STICKY;//或者START_REDELIVER_INTENT}'
當(dāng)然,前提是該進(jìn)程可以被殺掉(無(wú)論被AMS還是LMDK),用戶(hù)主動(dòng)殺死(最近任務(wù)列表或者退出應(yīng)用),都一定會(huì)通過(guò)Binder訃告機(jī)制回調(diào):
privatefinalvoidhandleAppDiedLocked(ProcessRecordapp,booleanrestarting,booleanallowRestart){intpid=app.pid;booleankept=cleanUpApplicationRecordLocked(app,restarting,allowRestart,-1);...}
進(jìn)而調(diào)用cleanUpApplicationRecordLocked函數(shù)進(jìn)行一系列清理及通知工作,這里先看Service相關(guān)的工作:
privatefinalbooleancleanUpApplicationRecordLocked(ProcessRecordapp,booleanrestarting,booleanallowRestart,intindex){...// 這里先出處理servicemServices.killServicesLocked(app,allowRestart);...}
這里傳入的allowRestart==true,也就說(shuō):允許重新啟動(dòng)Service:
final void killServicesLocked(ProcessRecord app, boolean allowRestart) { ... ServiceMap smap = getServiceMap(app.userId); // Now do remaining service cleanup. for (int i=app.services.size()-1; i>=0; i--) { ServiceRecord sr = app.services.valueAt(i); if (!app.persistent) { app.services.removeAt(i); } ... if (allowRestart && sr.crashCount >= 2 && (sr.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { bringDownServiceLocked(sr); } else if (!allowRestart || !mAm.mUserController.isUserRunningLocked(sr.userId, 0)) { bringDownServiceLocked(sr); } else {<!--關(guān)鍵點(diǎn)1 先進(jìn)行判定,如果有需要將重啟的消息發(fā)送到消息隊(duì)列等待執(zhí)行-->boolean canceled = scheduleServiceRestartLocked(sr, true); // 受時(shí)間跟次數(shù)的限制 sr.stopIfKilled<!--關(guān)鍵點(diǎn)2 二次確認(rèn),如果不應(yīng)該啟動(dòng)Service,就將重啟Service的消息移除-->if (sr.startRequested && (sr.stopIfKilled || canceled)) { if (sr.pendingStarts.size() == 0) { sr.startRequested = false; if (!sr.hasAutoCreateConnections()) { bringDownServiceLocked(sr); } ... }
先看關(guān)鍵點(diǎn)1:如果允許重新啟動(dòng),并且APP Crash的次數(shù)小于兩次,就視圖將為結(jié)束的Service重新喚起,其實(shí)就是調(diào)用scheduleServiceRestartLocked,發(fā)送消息,等待喚醒,關(guān)鍵點(diǎn)2是二次確認(rèn)下,是不是需要被喚醒,如果不需要就將上面的消息移除,并進(jìn)行一定的清理工作,這里的sr.stopIfKilled,其實(shí)主要跟onStartCommand返回值有關(guān)系:
voidserviceDoneExecutingLocked(ServiceRecordr,inttype,intstartId,intres){booleaninDestroying=mDestroyingServices.contains(r);if(r!=null){if(type==ActivityThread.SERVICE_DONE_EXECUTING_START){r.callStart=true;switch(res){caseService.START_STICKY_COMPATIBILITY:caseService.START_STICKY:{r.findDeliveredStart(startId,true);r.stopIfKilled=false;break;}caseService.START_NOT_STICKY:{r.findDeliveredStart(startId,true);if(r.getLastStartId()==startId){r.stopIfKilled=true;}break;}caseService.START_REDELIVER_INTENT:{ServiceRecord.StartItemsi=r.findDeliveredStart(startId,false);if(si!=null){si.deliveryCount=0;si.doneExecutingCount++;r.stopIfKilled=true;}break;}
所以,如果onStartCommand返回的是Service.START_STICKY,在被殺死后是會(huì)重新啟動(dòng)的,有必要的話(huà),還會(huì)重啟進(jìn)程:
private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) { boolean canceled = false; ...<!--關(guān)鍵點(diǎn)1-->mAm.mHandler.removeCallbacks(r.restarter); mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; return canceled;}
2 與三方應(yīng)用合作
2.1 百度輸入法開(kāi)機(jī)拉起微信
百度輸入法發(fā)送 com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER 廣播拉微信。
3 將同一個(gè)APP的不同Activity在Recent中顯示
如果需要將同一個(gè)APP的不同Activity在Recent中顯示,需滿(mǎn)足如下兩點(diǎn):
LaunchMode設(shè)置為singleInstance。
設(shè)置android:taskAffinity參數(shù)。
4 使用廠商推薦的Push通道
5 注意的保活的過(guò)由不及問(wèn)題
應(yīng)用如果過(guò)度?;钜约霸诤笈_(tái)做過(guò)多的事情,反而會(huì)導(dǎo)致手機(jī)廠商有針對(duì)性的處理,比如到后臺(tái)就會(huì)被殺。
結(jié)果反而起到了反作用。做好的方式是合作。
綜上,常用的方法分為利用系統(tǒng)bug或者機(jī)制、全家桶、徬大款、滅屏下播放。
所有流氓手段的進(jìn)程?;?,都是下策,建議不要使用,本文只是分析實(shí)驗(yàn)用。當(dāng)APP退回后臺(tái),優(yōu)先級(jí)變低,就應(yīng)該適時(shí)釋放內(nèi)存,以提高系統(tǒng)流暢度,依賴(lài)流氓手段提高優(yōu)先級(jí),還不釋放內(nèi)存,保持不死的,都是作死。
提升應(yīng)用的進(jìn)程優(yōu)先級(jí)是?;畹耐醯馈AST_ACTIVITY 級(jí)別就可以搞定大多數(shù)后臺(tái)控制。