android防止被殺
❶ Android如何避免Service被殺掉,如果被殺掉應如何處理。
service 如果你不是bind綁定啟動的話,你不執行stop應該不會被輕易的殺死. 但是如果你遇上了像360等等手機助手的話,他們會直接的殺死在後台運行的serice,這個是沒法避免的.
至於Service被殺掉 ,你只能打開程序重新啟動一下.舉個例子就是你在後台放歌,你清理的一下手機,如果沒有特殊的設置,放歌的軟體和服務都會被清楚,你只能重新打開軟體
❷ 怎樣使一個Android應用不被殺死
除非你把程序放到 /system/app 目錄下,這樣安卓就會當它是系統應用了
但是這是需要root許可權才可以的
通常情況下,為了防止程序被kill 一般的做法是注冊一堆的廣播,例如開機,網路,等狀態廣播
一收到廣播就去Intent 一下service,也就是說,即便程序被kill 一會又會重啟了
❸ Android防止殺進程
1.在service中重寫下面的方法,這個方法有三個返回值, START_STICKY是service被kill掉後自動重寫創建 [代碼]java代碼: @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; }---------------- @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub Log.v("TrafficService","startCommand"); flags = START_STICKY; return super.onStartCommand(intent, flags, startId); // return START_REDELIVER_INTENT; } 2.在Service的onDestroy()中重啟Service. public void onDestroy() { Intent localIntent = new Intent(); localIntent.setClass(this, MyService.class); //銷毀時重新啟動Service this.startService(localIntent); } 用qq管家殺掉進程的時候,調用的是系統自帶的強制kill功能(即settings里的),在kill時,會將應用的整個進程停掉,當然包括service在內,如果在running里將service強制kill掉,顯示進程還在。不管是kill整個進程還是只kill掉進應用的 service,都不會重新啟動service。不知道你是怎麼實現重啟的,實在是不解。 在eclipse中,用stop按鈕kill掉進程的時候,倒是會重啟service KILL問題: 1. settings 中stop service onDestroy方法中,調用startService進行Service的重啟。 2.settings中force stop 應用 捕捉系統進行廣播(action為android.intent.action.PACKAGE_RESTARTED) 3. 藉助第三方應用kill掉running task 提升service的優先順序 service開機啟動 今天我們主要來探討android怎麼讓一個service開機自動啟動功能的實現。Android手機在啟動的過程中會觸發一個Standard Broadcast Action,名字叫android.intent.action.BOOT_COMPLETED(記得只會觸發一次呀),在這里我們可以通過構建一個廣播接收者來接收這個這個action.下面我就來簡單寫以下實現的步驟: 第一步:首先創建一個廣播接收者,重構其抽象方法 onReceive(Context context, Intent intent),在其中啟動你想要啟動的Service或app。 [代碼]java代碼: import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; public class BootBroadcastReceiver extends BroadcastReceiver { //重寫onReceive方法 @Override public void onReceive(Context context, Intent intent) { //後邊的XXX.class就是要啟動的服務 Intent service = new Intent(context,XXXclass); context.startService(service); Log.v("TAG", "開機自動服務自動啟動....."); //啟動應用,參數為需要自動啟動的應用的包名 Intent intent = getPackageManager().getLaunchIntentForPackage(packageName); context.startActivity(intent ); } } 第二步:配置xml文件,在re ceiver接收這種添加intent-filter配置 [代碼]java代碼: <receiver android:name="BootBroadcastReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"></action> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </receiver> 第三步:添加許可權 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 如何實現一個不會被殺死的進程 看Android的文檔知道,當進程長期不活動,或系統需要資源時,會自動清理門戶,殺死一些Service,和不可見的Activity等所在的進程。 但是如果某個進程不想被殺死(如數據緩存進程,或狀態監控進程,或遠程服務進程),應該怎麼做,才能使進程不被殺死。 add android:persistent="true" into the <application> section in your AndroidManifest.xml 切記,這個 不可濫用,系統中用這個的service,app一多,整個系統就完蛋了。 目前系統中有phone等非常有限的,必須一直活著的應用在試用。 提升service優先順序的方法 Android 系統對於內存管理有自己的一套方法,為了保障系統有序穩定的運信,系統內部會自動分配,控製程序的內存使用。當系統覺得當前的資源非常有限的時候,為了保 證一些優先順序高的程序能運行,就會殺掉一些他認為不重要的程序或者服務來釋放內存。這樣就能保證真正對用戶有用的程序仍然再運行。如果你的 Service 碰上了這種情況,多半會先被殺掉。但如果你增加 Service 的優先順序就能讓他多留一會,我們可以用 setForeground(true) 來設置 Service 的優先順序。 為什麼是 foreground ? 默認啟動的 Service 是被標記為 background,當前運行的 Activity 一般被標記為 foreground,也就是說你給 Service 設置了 foreground 那麼他就和正在運行的 Activity 類似優先順序得到了一定的提高。當讓這並不能保證你得 Service 永遠不被殺掉,只是提高了他的優先順序。 從Android 1.5開始,一個已啟動的service可以調用startForeground(int, Notification)將service置為foreground狀態,調用stopForeground(boolean)將service置為 background狀態。 我們會在調用startForeground(int, Notification)傳入參數notification,它會在狀態欄里顯示正在進行的foreground service。background service不會在狀態欄里顯示。 在Android 1.0中,將一個service置為foreground狀態: setForeground(true); mNM.notify(id, notification); 將一個service置為background狀態: mNM.cancel(id); setForeground(false); 對比看出,在1.0 API中調用setForeground(boolean)只是簡單的改變service的狀態,用戶不會有任何覺察。新API中強制將 notification和改變service狀態的動作綁定起來,foreground service會在狀態欄顯示,而background service不會。 Remote service controller & binding 跨進程調用Service。暫時不研究。 如何防止Android應用中的Service被系統回收? 很多朋友都在問,如何防止Android應用中的Service被系統回收?下面簡單解答一下。 對於Service被系統回收,一般做法是通過提高優先順序可以解決,在AndroidManifest.xml文件中對於intent-filter可以通過 android:priority = "1000"這個屬性設置最高優先順序,1000是最高值,如果數字越小則優先順序越低,同時實用於廣播,推薦大家如果你的應用很重要,可以考慮通過系統常用intent action來觸發。
❹ android 怎麼保證服務不被殺死
1: 正常 stop service的時候會執行生命周期的 onDestory() 可以在銷毀方法中執行再次 startService();
2: 當收到內存影響的時候,out-of-memory killer會銷毀掉一些優先順序低的app:
相較於/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操作,再次情況下,發現4.1.2的程序在設置裡面的應用裡面,程序沒有禁止掉停止。
在此情況下還要應用上1的重新啟動。
3: force stop service 的時候,則不執行 onDestory(),
還有一種情況是 第三方任務管理器清理掉整個程序的時候;
google 管方就有,ForegroundService 前台服務,讓服務一直以前台任務的方式運行,可以在service 的oncreate來實現前台服務, 通過這個方法必須發送一個通知欄,讓用戶知道服務在運行。我們可以把service修改成前台運行方式,只不過讓通知notification不去顯示就OK了。
❺ 想讓android應用常駐後台,不被殺死,各位大神有什麼高招
方法: 對於一個service,可以首先把它設為在前台運行: public void MyService.onCreate() { super.onCreate(); Notification notification = new Notification(android.R.drawable.my_service_icon, "my_service_name", System.currentTimeMillis()); PendingIntent p_intent = PendingIntent.getActivity(this, 0, new Intent(this, MyMainActivity.class), 0); notification.setLatestEventInfo(this, "MyServiceNotification, "MyServiceNotification is Running!", p_intent); Log.d(TAG, String.format("notification = %s", notification)); startForeground(0x1982, notification); // notification ID: 0x1982, you can name it as you will. } 重要設置------------------------------- 相較於/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 設置後的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_SYSTEMApplicationInfo.FLAG_PERSISTENT)) == (ApplicationInfo.FLAG_SYSTEMApplicationInfo.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文件中設置(如上)。
❻ 請問android APP 如何防止被系統殺死和用戶卸載
這個有點流氓軟體的味道了……
如果是防止被殺,參照一下這里吧(Android開發之如何保證Service不被殺掉)
如果要防止用戶卸載,可以用輔助功能監聽用戶是否點開了軟體卸載頁面,如果點開了,查找頁面文字或ID,檢測一下是不是你的軟體,如果是就點取消。但是需要引導用戶把輔助功能打開。
建議不要這么做,防止被殺可以,但是防止卸載如果被舉報會招到官司的。
❼ android開發怎麼讓個推服務不被手機系統殺掉
服務是一個應用程序組件,可以在後台執行長時間運行的操作,不提供用戶界面。一個應用程序組件可以啟動一個服務,它將繼續在後台運行,即使用戶切換到另一個應用程序。此外,一個組件可以綁定到一個服務與它交互,甚至執行進程間通信(IPC)。例如,一個服務可能處理網路通信,播放音樂,執行文件I/O,或與一個內容提供者交互,都在後台執行。
一個服務本質上講有兩種形式:
Started 啟動的
started 形式的服務是指當一個應用組件(比如 activity )通過startService()方法開啟的服務。一旦開啟,該服務就可以 無限期 地在後台運行,哪怕開啟它的組件被銷毀掉。
通常,開啟的服務執行一個單獨的操作且並不向調用者返回一個結果。
比如,可能從網路進行下載或者上傳一個文件。當任務完成,服務就該自我停止。
Bound 綁定的
bound 形式的服務是指一個應用組件通過調用 bindService() 方法與服務綁定。一個綁定的服務提供一個客戶-服務端介面,以允許組件與服務交互,發送請求,獲得結果,甚至執行進程間通信。一個綁定的服務只和與其綁定的組件同時運行。多個組件可以同時綁定到一個服務,但當全部接觸綁定後,服務就被銷毀。
雖然分這兩類,但是一個服務可以同時使用這兩種方式——可以用 started 無限期的運行,同時允許綁定。只需要在服務中實現兩個回調方法: onStartCommand() 允許組件開啟服務, onBind() 允許綁定。
不論應用程序是怎麼起服務的, 任何 應用程序都可以用這個服務。同樣的,任何組件可以使用一個 Activity 通過傳遞 Intent 開啟服務。你也可以在配置文件設置服務為私有來防止其他應用訪問該服務。
注意: 一個服務在進程中的主線程運行——一個服務 不會 創建自己的線程,也 不會 在另外的進程運行(除非另外指定)。這意味著,如果服務需要做一些頻繁佔用CPU的工作或者會發生阻塞的操作,你需要在服務中另開線程執行任務。這可以降低產生ANR的風險,提高用戶體驗。
基礎
創建一個服務需要建立一個 Service 相關的子類,然後需要實現一些回調方法,好在不同的生命周期內做對應處理和綁定服務,比較重要的方法如下:
onStartCommand()
當其他組件,如 activity 請求服務啟動時,系統會調用這個方法。一旦這個方法執行,服務就開始並且無限期的執行。如果實現這個方法,當這個服務完成任務後,需要你來調用 stopSelf() 或者 stopService() 停掉服務。如果只想提供綁定,不需要自己實現這個方法。
onBind()
當有其他組件想通過 bindService() 方法綁定這個服務時系統就會調用此方法。在實現的方法裡面,必須添加一個供客戶端使用的介面通過返回一個 IBinder 來與服務通信,這個方法必須實現。當然不想允許綁定的話,返回 null 即可。
onCreate()
服務第一次建立的時候會調用這個方法,執行一次性設置程序,在上面2個方法執行前調用。如果服務已存在,則不執行該方法。
onDestroy()
服務不再使用則使用該方法。服務應該實現這個方法來清理諸如線程,注冊的監聽器等資源。這是最後調用的方法。
安卓系統只會在內存佔用很高,必須恢復系統資源供當前運行程序的情況下強制停掉一個運行中的服務。如果服務綁定在當前運行的程序中,就幾乎不會被殺掉,如果服務聲明了在前台運行(其實在後台,只是給系統一個錯的信息來提高優先順序),就幾乎不會被殺掉。另外,如果一個服務正在運行,且運行了很久,系統就會根據運行時間把其排在後台任務列表的後面,則這個服務很容易被殺掉。根據onStartCommand() 的返回值設置,服務被殺掉後仍可以在資源充足的條件下立即重啟。
是用一個服務好還是開一個線程好
一個服務就是一個可以忽略交互,在後台獨立運行的組件,如果你需要這樣就用服務
如果你需要在用戶與程序交互時在主線程外執行任務,那就開個線程吧。
比如想播放音樂,但只在程序運行時播放,你可能在 onCreate() 開一個線程,在 onStart() 中開啟它,在 onStop() 停止它。也可以考慮使用 AsyncTask 或者HandlerThread 取代一般的線程。
記住,如果使用一個服務,它還是默認在主線程中運行,如果會發生阻塞,還是要在服務中另開線程的。
在 manifest 文件聲明服務
要使用服務就必須在 manifest 文件聲明要用的所有服務,只用在<application> 標簽內添加子標簽 <service> 即可。
<manifest ...>
...
<application ...>
<service android:name=".ExampleService"
android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:isolatedProcess=["true" | "false"]
android:label="string resource"
android:icon="drawable resource"
android:permission="string"
android:process="string" >
...
</service>
</application>
</manifest>
下面對 service 標簽屬性做說明
android:name
你所編寫的服務類的類名,可填寫完整名稱,包名+類名,如com.example.test.ServiceA ,也可以忽略包名,用 . 開頭,如 .ServiceA,因為在 manifest 文件開頭會定義包名,它會自己引用。
一旦你發布應用,你就不能改這個名字(除非設置 android:exported="false"),另外 name 沒有默認值,必須定義。
android:enabled
是否可以被系統實例化,默認為 true
因為父標簽 <application> 也有 enable 屬性,所以必須兩個都為默認值true 的情況下服務才會被激活,否則不會激活。
android:exported
其他應用能否訪問該服務,如果不能,則只有本應用或有相同用戶ID的應用能訪問。當然除了該屬性也可以在下面 permission 中限制其他應用訪問本服務。
這個默認值與服務是否包含意圖過濾器 intent filters 有關。如果一個也沒有則為 false
android:isolatedProcess
設置 true 意味著,服務會在一個特殊的進程下運行,這個進程與系統其他進程分開且沒有自己的許可權。與其通信的唯一途徑是通過服務的API(binding and starting)。
android:label
可以顯示給用戶的服務名稱。如果沒設置,就用 <application> 的 lable 。不管怎樣,這個值是所有服務的意圖過濾器的默認 lable 。定義盡量用對字元串資源的引用。
android:icon
類似 label ,是圖標,盡量用 drawable 資源的引用定義。
android:permission
是一個實體必須要運行或綁定一個服務的許可權。如果沒有許可權,startService() , bindService() 或 stopService() 方法將不執行,Intent 也不會傳遞到服務。
如果屬性未設置,會由 <application> 許可權設置情況應用到服務。如果兩者都未設置,服務就不受許可權保護。
android:process
服務運行所在的進程名。通常為默認為應用程序所在的進程,與包名同名。<application> 元素的屬性 process 可以設置不同的進程名,當然組件也可設置自己的進程覆蓋應用的設置。
如果名稱設置為冒號 : 開頭,一個對應用程序私有的新進程會在需要時和運行到這個進程時建立。如果名稱為小寫字母開頭,服務會在一個相同名字的全局進程運行,如果有許可權這樣的話。這允許不同應用程序的組件可以分享一個進程,減少了資源的使用。
創建「啟動的」服務
啟動的(started)服務由 startService(Intent) 方法啟動,在服務中的onStartCommand() 方法里獲得 Intent 信息。關閉則由服務自己的方法 stopSelf() 或者由啟動服務的地方調用 stopService(Intent) 方法來關閉。並不會因為啟動服務的應用程序銷毀而關閉。
示例,一個應用需要保存數據到遠程資料庫,這時啟動一個服務,通過創建啟動的服務給服務傳遞數據,由服務執行保存行為,行為結束再自我銷毀。因為服務跟啟動它的應用在一個進程的主線程中,所以對於耗時的操作要起一個新的線程去做。
//activity中
Intent intent = new Intent(MainActivity.this, ServiceA.class);
intent.putExtra("name", strName);
startService(intent);
//service中
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
// 獲取數據
String strName = intent.getStringExtra("name");
// ... 資料庫操作
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
耗時的操作
}
}).run();
return Service.START_STICKY;
}
寫服務有2種,繼承 service 或者 IntentService 。後者是前者的子類。前者包含上面介紹的各種方法,用於普通的服務。後者可以自己開一個工作線程一個接一個處理多個請求。
繼承IntentService
大多數服務不需要同時處理多個請求,繼承 IntentService 是最好的選擇
IntentService處理流程
創建默認的一個 worker 線程處理傳遞給 onStartCommand() 的所有 intent ,不佔據應用的主線程
創建一個工作隊列一次傳遞一個 intent 到你實現的 onHandleIntent() 方法,避免了多線程
在所以啟動請求被處理後自動關閉服務,不需要調用 stopSelf()
默認提供 onBind() 的實現,並返回 null
默認提供 onStartCommand() 的實現,實現發送 intent 到工作隊列再到你的onHandleIntent() 方法實現。
這些都加入到 IntentService 中了,你需要做的就是實現構造方法和onHandleIntent() ,如下:
public class HelloIntentService extends IntentService {
/**
* A constructor is required, and must call the super IntentService(String)
* constructor with a name for the worker thread.
*/
public HelloIntentService() {
super("HelloIntentService");
}
/**
* The IntentService calls this method from the default worker thread with
* the intent that started the service. When this method returns, IntentService
* stops the service, as appropriate.
*/
@Override
protected void onHandleIntent(Intent intent) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
long endTime = System.currentTimeMillis() + 5*1000;
while (System.currentTimeMillis() < endTime) {
synchronized (this) {
try {
wait(endTime - System.currentTimeMillis());
} catch (Exception e) {
}
}
}
}
}
如果需要重寫其他回調方法,如 onCreate() , onStartCommand() 等,一定要調用super() 方法,保證 IntentService 正確處理 worker 線程,只有 onHandleIntent()和 onBind() 不需要這樣。如:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent,flags,startId);
}
繼承Service
繼承 Service 就可以實現對請求多線程的處理,前面介紹了 service 的生命周期,可以按照生命周期實現方法。就不放示例了。
onStartCommand() 的返回值
返回一個整型值,用來描述系統在殺掉服務後是否要繼續啟動服務,返回值有三種:
START_NOT_STICKY
系統不重新創建服務,除非有將要傳遞來的 intent 。這是最安全的選項,可以避免在不必要的時候運行服務。
START_STICKY
系統重新創建服務並且調用 onStartCommand() 方法,但並不會傳遞最後一次傳遞的 intent ,只是傳遞一個空的 intent 。除非存在將要傳遞來的 intent ,那麼就會傳遞這些 intent 。這個適合播放器一類的服務,不需要執行命令,只需要獨自運行,等待任務。
START_REDELIVER_INTENT
系統重新創建服務並且調用 onStartCommand() 方法,傳遞最後一次傳遞的intent 。其餘存在的需要傳遞的intent會按順序傳遞進來。這適合像下載一樣的服務,立即恢復,積極執行。
如果想從服務獲得結果,可以用廣播來處理
創建「綁定的」服務
用 bindService() 方法將應用組件綁定到服務,建立一個長時間保持的聯系。
如果需要在 activity 或其他組件和服務交互或者通過進程間通信給其他應用程序提供本應用的功能,就需要綁定的服務。
建立一個綁定的服務需要實現 onBind() 方法返回一個定義了與服務通信介面的IBinder 對象。其他應用程序組件可以調用 bindService() 方法獲取介面並且調用服務上的方法。
創建一個綁定的服務,第一件事就是定義一個說明客戶端與服務通信方式的介面。這個介面必須是 IBinder 的實現,並且必須要從 onBind() 方法返回。一旦客戶端接收到了 IBinder ,就可以通過這個介面進行交互。
多個客戶端可以綁定到一個服務,可以用 unbindService() 方法解除綁定,當沒有組件綁定在服務上,這個服務就會被銷毀。
//activity中
private ServiceConnection connB = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
Log.v(tag, "Service B disconnected");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
Log.v(tag, "Service B connected");
MyBinderB binder = (MyBinderB) service;
ServiceB SB = binder.getService();
SB.showLog();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent a = new Intent(MainActivity.this, ServiceB.class);
bindService(a, connB, BIND_AUTO_CREATE);
}
}
//ServiceB
public class ServiceB extends Service {
public void showLog() {
Log.i(tag, "serviceB-->showLog()");
}
public class MyBinderB extends Binder {
public ServiceB getService() {
return ServiceB.this;
}
}
private MyBinderB myBinderB = new MyBinderB();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return myBinderB;
}
}
啟動前台服務
前台服務是被認為是用戶已知的正在運行的服務,當系統需要釋放內存時不會優先殺掉該進程。前台進程必須發一個 notification 在狀態欄中顯示,直到進程被殺死。因為前台服務會一直消耗一部分資源,但不像一般服務那樣會在需要的時候被殺掉,所以為了能節約資源,保護電池壽命,一定要在建前台服務的時候發notification ,提示用戶。當然,系統提供的方法就是必須有 notification 參數的,所以不要想著怎麼把 notification 隱藏掉。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification noti = new Notification.Builder(this)
.setContentTitle("Title")
.setContentText("Message")
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(pendingIntent)
.build();
startForeground(12346, noti);
return Service.START_STICKY;
}
startForeground() 方法就是將服務設為前台服務。參數12346就是這個通知唯一的id,只要不為0即可。
❽ android後台服務保持,不被殺死
作者:閉關寫代碼
鏈接:https://www.hu.com/question/29826231/answer/71207109
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。
強烈建議不要這么做,不僅僅從用戶角度考慮,作為Android開發者也有責任去維護Android的生態環境。現在很多Android開發工程師,主力機居然是iPhone而不是Android設備,感到相當悲哀。
從技術角度概括一下現在普遍的防殺方法
Service設置成START_STICKY,kill 後會被重啟(等待5秒左右),重傳Intent,保持與重啟前一樣
通過 startForeground將進程設置為前台進程,做前台服務,優先順序和前台應用一個級別,除非在系統內存非常缺,否則此進程不會被 kill
雙進程Service:讓2個進程互相保護,其中一個Service被清理後,另外沒被清理的進程可以立即重啟進程
QQ黑科技:在應用退到後台後,另起一個只有 1 像素的頁面停留在桌面上,讓自己保持前台狀態,保護自己不被後台清理工具殺死
在已經root的設備下,修改相應的許可權文件,將App偽裝成系統級的應用(Android4.0系列的一個漏洞,已經確認可行)
Android系統中當前進程(Process)fork出來的子進程,被系統認為是兩個不同的進程。當父進程被殺死的時候,子進程仍然可以存活,並不受影響。鑒於目前提到的在Android-Service層做雙守護都會失敗,我們可以fork出c進程,多進程守護。死循環在那檢查是否還存在,具體的思路如下(Android5.0以下可行)
用C編寫守護進程(即子進程),守護進程做的事情就是循環檢查目標進程是否存在,不存在則啟動它。
在NDK環境中將1中編寫的C代碼編譯打包成可執行文件(BUILD_EXECUTABLE)。
主進程啟動時將守護進程放入私有目錄下,賦予可執行許可權,啟動它即可。
聯系廠商,加入白名單
------------------------------------------------------
TIP: 面對各種流氓軟體後台常駐問題,建議使用「綠色守護」來解決,可是殺掉那些第三方清理工具難以清除的後台程序
❾ 如何讓android app不被後台很快殺死
這個可不好說了,具體關閉程序是由Framework決定的。 一般按照如下規律。 1、內存緊張、先關閉沒有SERVICE、ACTIVITY堆棧時間最長的。 2、內存緊張、有SERVICE,不活動時間最長的。佔用內存比較大的。 3、內存緊張、有大內存程序切換到前台,釋放內存依舊不夠的。依次殺死不活動時間最長的。 4、內存緊張、有大內存程序切換到前台,釋放內存依舊不夠的。殺死帶有android:persistent="true"標記的。(備注Phone模塊有此標記,所以最難殺) 這個是我的經驗。
❿ 如何防止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文件中設置(如上)。