如何讓service被管理器殺死後自動重啓

歡迎轉載,轉載請註明出自:www.androidkaifa.com    安卓開發網
    筆者最近在一項目開發中遇到這樣一個需求,要在本身應用中啓動了一個service,這個service用來監聽服務器發過來的推送信息並彈出一個對話框顯示信息,因此須要保證這個service時時運行着,且不能被任務管理或是系統的設置等工具殺掉,若是services是被殺死,則須要自動重啓這service,筆者在網上查詢一下,找到一些相似的問題文章,如今把它在www.androidkaifa.com總結記錄下來,以方便須要實現像我這樣的要求的朋友有幫助,但願你們都能寫永遠不會被KILL掉的進程/服務,也就是不受系統垃圾回收機制(內存管理)影響。
網絡對此問題的解決建議:
     (1)
           在service中重寫onStartCommand方法,這個方法有三個返回值, START_STICKY是service被kill掉後自動重寫建立@Override    public int onStartCommand(Intent intent, int flags, int startId) {        return START_STICKY;    }
     (2)
      在Service的onDestroy()中重啓Service.
      public void onDestroy() {   
        Intent localIntent = new Intent();
        localIntent.setClass(this, MyService.class);  //銷燬時從新啓動Service
        this.startService(localIntent);
    } 
      對於(2)此解決方案,筆者本身寫了一個代碼測試了一下,1:若是是在系統的settings中的DOWNLOADED關閉整個應用(Force stop),則這個services類中的onDestory方法沒有監聽到(services類的onDestory方法的log沒有打印日誌),若是是在系統裏的setting中的RUNNING殺掉項目services,則onDestory方法則會監聽到(services類的onDestory方法的log有打印日誌),因此對於此解決方案並非必定適用,2:或是經過別的應用,直接kill掉個人應用時,也是不會調用services類的onDestory方法的,
     (3)
      再寫另一個apk,用一個廣播來監聽這個APK是否被關閉,若是是關閉了則重啓這個APK,而這裏咱們爲何要用另一個APK?由於被關閉的應用程序不能檢測到本身被關閉的事件,只能接收到其餘應用被關閉的廣播。這個action的recever
public class ProtectorHelperReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
                String pkg = "com.innofidei.myprotector";// 被kill的應用的包名
                String action = pkg + ".action.START_SERVICE";// 重啓service的acition
                String str = intent.getData().toString().toLowerCase().replace("package:", "");
                String data = intent.getAction();  
                if (str != null && str.equals(pkg)) {
                        if (data != null && data.equals("android.intent.action.PACKAGE_REMOVED")) {
                                File file = new File("/sdcard/" + context.getPackageName() + "/ProtectorHelper.apk");
                                file.delete();
                                file.getParentFile().delete();
                                Intent intent2 = new Intent(context, UninstallActivity.class);
                                intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                context.startActivity(intent2);
                        } else {
                                context.sendBroadcast(new Intent(action));// 通知應用重啓service
                        }
                }
        }
}
    (4)
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       android:sharedUserId="android.uid.system">
    <application android:icon="@drawable/icon" android:label="@string/app_name"
                android:allowClearUserData="false" android:process="system"
                android:killAfterRestore="false"
>
    
      這樣應該能夠了,我也是仿照那些不能被殺死的系統應用的AndroidManifest.xml寫的,可是若要這樣寫,則須要源碼環境編譯能經過,eclipse是沒有這權限編譯的這項目的,
(5)
      項目的功能配置文件AndroidManifest.xml 中添加:
       android:persistent="true" //在<application>節點下面
(6)提升Android Service 優先級的方法:
咱們先看一下系統一些的進程級別:
進入 $SDK/tools 運行命令:# adb shell dumpsys activity|grep oom_adj 代碼:  Running Norm Proc # 6: oom_adj=  0ProcessRecord{43635cf0 12689:com.roiding.netraffic/10028}   Running Norm Proc # 5: oom_adj=  7 ProcessRecord{436feda012729:com.android.browser/10006}   Running Norm Proc # 4: oom_adj=  8 ProcessRecord{4367e83812761:android.process.acore/10016}   Running Norm Proc # 3: oom_adj=  8 ProcessRecord{43691cd812754:com.google.process.gapps/10000}   Running PERS Proc # 1: oom_adj=-12 ProcessRecord{435067505941:com.android.phone/1001}   Running PERS Proc # 0: oom_adj=-100 ProcessRecord{4348fde0 5908:system/1000}  返 回的一大堆東西,觀察 oom_adj 的值,若是是大於 8 通常就是屬於 backgroud 隨時可能被幹掉,數值越小證實優先級
越高,被幹掉的時間越晚。你看phone的程序是 -12 說明電話就是電話,其餘什麼都幹了了,也的能接電話對吧。
另外還有一個 -100 的,更邪乎由於是 system 若是他也完蛋了,你得系統也就掛了,


   Android 系統對於內存管理有本身的一套方法,爲了保障系統有序穩定的運信,系統內部會自動分配,控制程序的內存使用。
當系統以爲當前的資源很是有限的時候,爲了保 證一些優先級高的程序能運行,就會殺掉一些他認爲不重要的程序或者
服務來釋放內存。這樣就能保證真正對用戶有用的程序仍然再運行。若是你的 Service 碰上了這種狀況,多半會先被殺掉。
但若是你增長 Service 的優先級就能讓他多留一會,咱們能夠用 setForeground(true) 來設置 Service 的優先級。爲何是 foreground ? 默認啓動的 Service 是被標記爲 background,當前運行的 Activity 通常被標記爲 foreground,
也就是說你給 Service 設置了 foreground 那麼他就和正在運行的 Activity 相似優先級獲得了必定的提升。
當讓這並不能保證你得 Service 永遠不被殺掉,只是提升了他的優先級。
(7)
       請參看個人另外一篇文章《怎樣使一個Android應用不被系統或第三方應用殺死》,
(8) 
        @Override
        public IBinder onBind(Intent arg0) {
                // TODO Auto-generated method stub
                Log.v("TrafficService", "Bind");        
                state = BINLD;
                //使用線程,該線程不會被銷燬
                return myBinder;
        }
        
        
        class TrafficBinder extends Binder {  
                public float his = history;
                TrafficService getService(){
                        return TrafficService.this;
                 }
        }
        
         @Override
         public void onCreate() {
                 // TODO Auto-generated method stub
                 receiver = new NetReceiver();
                 IntentFilter nfilter=new IntentFilter();        
                 nfilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
                 this.registerReceiver(receiver, nfilter);
                 dealBuffer();
                 handler.post(createBrod);
                 Log.v("TrafficService", "Create "+history+" "+todayTraffic+" "+tempTraffic);
                 super.onCreate();
                 
         }
         @Override
         public boolean onUnbind(Intent intent) {
                 // TODO Auto-generated method stub
                 state = UNBINLD;
                 Log.v("TrafficService", "Unbind");
                 return true;
         }
         
         @Override
         public void onRebind(Intent intent) {
                 // TODO Auto-generated method stub
                 Log.v("TrafficService", "Rebind");
                 state = BINLD;;
                 super.onRebind(intent);
                 
         }
         
         @Override
        public void onDestroy() {
                // TODO Auto-generated method stub
                 handler.removeCallbacks(updateBrod);
                 momorybuffer();
                 nManger.cancel(R.layout.notifi);
                 unregisterReceiver(receiver);
                 
                 Log.v("TrafficService", "destroy "+history+" "+todayTraffic+" "+tempTraffic);
                 super.onDestroy();
        }
         
        @Override
        public boolean stopService(Intent name) {
                // TODO Auto-generated method stub
                momorybuffer();
                nManger.cancel(R.layout.notifi);
                Log.v("TrafficService",name.getAction());
                Log.v("TrafficService", "stop "+history+" "+todayTraffic+" "+tempTraffic);
                return super.stopService(name);
        }

        
        
        @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;
        }
//在以上代碼中的onstartCommand返回START_STICKY,同時在destory的最後重啓了服務,這樣就OK了,php

相關文章
相關標籤/搜索