ページ

2013/12/14

[Android]端末起動時にサービスを起動する

常駐サービスを実装したい場合は端末起動時に自動的にサービスを起動しておきたいので
端末起動時のイベントを通知する Broadcast Intent を受信できるようにして、
そこからサービスを起動したいと思います。

参考
システムの起動時にサービスを実行する « Tech Booster
App Install Location | Android Developers
AndroidのBOOT_COMPLETEDの受信とテスト | 9ensanのLifeHack

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    android:installLocation="internalOnly"
    …>
android.intent.action.BOOT_COMPLETED は 外部SDが端末にマウントされる前にブロードキャストされるので
外部SDにインストールされている場合、Broadcast Intent を受け取ることができません。
また、アプリが外部SDにインストールされている場合、外部SDがアンマウントされると
Service が kill され、マウントしても再開されません。
Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE | Android Developers
Broadcast Intent を受け取って自分で再開する必要があります。

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver
    android:name=".BootReceiver"
    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>
</receiver>
Manifest とreceiver にそれぞれ Permission が必要なようです。
public class BootReceiver extends BroadcastReceiver {

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

}
上記のように BroadcastReceiver で Service を開始します。

以下のコマンドを実行することで BOOT_COMPLETED のテストが可能です。
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

Android 4.0 以上からはアプリを外部SDに移すことができなくなったようで、
android:installLocation="preferExternal" を指定していても動きましたが
Xperia A が良い感じにしてくれているだけかもしれませんし、
Android 4.0 未満では動かなくなると思うので
android:installLocation="internalOnly" を指定しておいたほうが良いと思います。
最近の端末は内部容量が 24G とかあってもはやアプリのサイズを気にする必要がほとんど無いんですね。