2013年4月24日水曜日

Serviceの強制終了

Serviceは、Androidシステムによって、終了させられてしまうことがあります。
bindしているActivityが全ていなくなったとか、Low Memoryになったとか。

Serviceには、onDestroy()も、onLowMemory()も存在してますので、
終了させられても、この2つをちゃんと実装しておけば良い・・・

と思いきや、

そんなの呼ばれずにKillされてしまうシチュエーションがあります。
ちょっとググれば、LowMemoryでは、そうなってしまうことがあるようなことがわかりますが、それだけではありません。

だれもそのServiceにbindしてない状態ですと、LowMemoryとか関係なく、一定時間経つとKillされます。
定期的に処理を行っていたとしても、本当に、Killされちゃいます。
onDestroyとか一切呼ばれません。

ServiceがKillされちゃうあたりで、"No longer want xx.service (pid xxxxx): hidden #xx"といったLogが出てきますが、このLogがあるのがframework/base/services/ActivityManagerService.java です。

コードを覗いてみると(12/24版のGingerBread)、
12170行目に、このLogをだしてます。そのちょっと下、12175行目で、やはり、います。
ProcessのKillが。


if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
if (!app.killedBackground) {
numHidden++;
if (numHidden > MAX_HIDDEN_APPS) {
Slog.i(TAG, "No longer want " + app.processName
+ " (pid " + app.pid + "): hidden #" + numHidden);
EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
app.processName, app.setAdj, "too many background");
app.killedBackground = true;
Process.killProcessQuiet(app.pid);
}
}
}


これでは、onDestroyも呼ばれないのも納得・・・
この動作を避けるためには、Service::startForeground()を、必要なタイミングで呼べばいいです。
実際、ActivityManagerServiceでも、Foreground ServiceはKillしないようにしてます(※)

(※)正確には、Killされにくくなる、みたいです。どれから順番にKillするかはcomputeOomAdjLocked()を読めば良さそう。


Notification notification = new Notification(R.drawable.icon,
getString(R.string.StartNotification),
System.currentTimeMillis());

Intent t_intent = new Intent(this, Target.class);

t_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent intent = PendingIntent.getActivity(this, 0,
t_intent,0);
notification.setLatestEventInfo(this,
getString(R.string.app_name),
getString(R.string.Notification), intent);
notification.flags = Notification.FLAG_ONGOING_EVENT;

startForeground(FORGROUND_ID, notification);


Notificationが必要なので、それを作って、startForeground()を呼んであげます。startForeground()の第1引数はNotificationに渡す識別用のIDです。


これで、たいていのシチュエーションではKillされないと思います。
が、ServiceのAPI仕様書にもありますが、Critical な Low Memory状態だと、今画面に出てるActivityから
使われてても、ServiceがKillされるようなこともあるらしいので(気にしなくていいらしいけど)、
Killされる可能性があるというのは、頭の片隅においてServiceを設計したほうが良さそうです。

0 件のコメント:

コメントを投稿