2011年12月30日金曜日

Android Service を自動的に再起動する方法

Androidで常駐するアプリを作るときはサービスを用いて基本的にはずっと起動させておく。ところが以下の場合にはサービスが停止されてしまう。その場合に再起動させる方法を以下に示す。


1) Android OSがメモリ等リソースが少なくなると強制的に停止する場合がある。
Service.onStartCommandの戻り値を START_STICKY 又は START_REDELIVER_INTENT にすることで、OSが勝手に再起動してくれる。


2) 電源が落とされた場合。
Intent.ACTION_BOOT_COMPLETED ブロードキャストを受けるレシーバを作成しそこからサービスを起動する。

Manifestには

<receiver android:name=".BootUpReceiver"
    android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
     </intent-filter>
</receiver>

等と記述。注意点としてRECEIVE_BOOT_COMPLETEDのパーミッションを取る必要がある。

このブロードキャストを受けるクラスとして

public class BootUpReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            context.startService(new Intent(context, SomeService.class));
        }
    }
}

等としてサービスを起動しましょう。


***** 2012-10-21追記 *****
Android 4.04のスマフォ(XPERIA GXです)でテストしたところ、Intent.ACTION_BOOT_COMPLETED ブロードキャストが受け取れなくなっていた。
Manifestに


  <uses-permission
    android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>


を追加することで解決した。


3) アプリケーションをアップデートした場合。
Intent.ACTION_PACKAGE_REPLACED ブロードキャストを受けるレシーバを作成しそこからサービスを起動する。

Manifestには

<receiver android:name=".PackageReplacedReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_REPLACED" />
        <data android:scheme="package" android:path="your.package.path" />
    </intent-filter>
</receiver>

等と記述。自分のものだけ受け他のアプリのものは除くようにandroid:pathを設定すること。

このブロードキャストを受けるクラスとして

public class PackageReplacedReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
             context.startService(new Intent(context, SomeService.class));
        }
    }
}

等としてサービスを起動しましょう。


***** 2012-1-17追記 *****
どうもandroid:pathを設定しても全てのアプリのアップデートを受けてしまう様子。PackageReplacedReceiverクラスの方で



public class PackageReplacedReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
         if (intent.getAction().equals(Intent.ACTION_PACKAGE_REPLACED)) {
             if (intent.getDataString().equals("package:your.package.path")) {
                context.startService(new Intent(context, SomeService.class));
             }
        }
    }
}

とIntentのDataをチェックしてからサービスを起動しましょう。


0 件のコメント:

コメントを投稿