2015年3月17日 星期二

[Android] 關於服務Service - 如何讓Service永遠不被Killed

如前一篇所說([Android] 關於服務Service - Service會被Killed?),
雖然Service被Killed後,通常系統會再重啓它,
但...萬一系統沒有這麼做呢?
我們是否有另外的方法可以保護自己的Service永生不滅?

有一個簡單方式,就是再建一個monitorService,
它的工作就是發現myService不見時,負責把myService再重啓,

如同[Android] 如何在開機後自動載入程式裡的做法,
有一個BootUpReceiverClass.java來接收開機時系統的訊息,
但其實它同時也可以接收Broadcast過來的訊息,
我們需要在AndroidManifest.xml增加一個intent-filter,
<receiver android:enabled="true" android:name="myTest.com.BootUpReceiverClass"
 android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
 <intent-filter>
 <action android:name="android.intent.action.BOOT_COMPLETED" />
 <category android:name="android.intent.category.DEFAULT" />
 </intent-filter>
 <intent-filter>
 <action android:name="myTest.com.BootUpReceiverClass" /> 
 <category android:name="android.intent.category.DEFAULT" />       
 </intent-filter>
</receiver> 
接下來,就是monitorService部份,
假設我們在monitorService裡建了一個monitorThread,
它負責檢查"myTest.com.myServiceClass"有沒有在執行,
如果沒有,就sendBroadcast()給"myTest.com.BootUpReceiverClass"
private boolean isMyServiceRunning(String className) {
  try
  {
      ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
      for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {       
          if (className.equals(service.service.getClassName())) {
              return true;
          }
      }
  }catch (Exception e) {   
   e.printStackTrace();   
  }
     return false;
 }
 private class monitorThread extends Thread {
  @Override
  public void run() {
   super.run();   
   while(!isInterrupted()) {
    try {     
     if(!isMyServiceRunning("myTest.com.myServiceClass"))
     {      
      try
      {
       Intent intent = new Intent("myTest.com.BootUpReceiverClass");
       if(intent!=null)
       {        
           sendBroadcast(intent);
                 Thread.sleep(15000);
       }
      }catch (Exception e) {       
       e.printStackTrace();       
      }
     } 
     else
     {      
      Thread.sleep(3000);
     }     
    } catch (InterruptedException e) {     
     e.printStackTrace();     
    }
   }   
  }
 }
那..如果monitorService也被kill掉了呢?
所以,在myService裡也要一個類似的機制,
一直監視monitorService有沒有在執行,
如果不見了,就把它重啓,
程式碼是類似的,這邊就不貼了,

至於多久去檢查對方在不在呢?
經驗上,2~5秒應該都可以,
你可以去應用程式的執行中列表去看myService和monitorService是不是都在,
並且,試著關掉myService,看看會不會被重啓,
反過來,關掉monitorService,看看會不會被重啓...

那...如果monitorService和myService同時被killed呢?
人工去砍是很難成功的,
因為其中一個被關掉,立刻就會另一個重啓,
除非是系統才有辦法一次關二個,
這也表示,系統loading或記憶體真的無法負荷了,
就算myService仍然活著,也會卡卡的吧...

沒有留言:

張貼留言