LoginSignup
103
101

More than 5 years have passed since last update.

スリープ時にもBroadcastを処理する方法

Last updated at Posted at 2014-08-12

スリープとBroadcast

端末がスリープ状態の場合でもBroadcastReceiver.onReceive()の呼び出しは通常どおり行われる。
ただし、onReceive()からServiceを呼び出して処理させる場合、その処理が中断されてしまう可能性がある。
確実にバックグラウンド処理を行うためには、Wakelockによってスリープ状態を制御する必要がある。

この処理は通常、ServiceWakelockを扱う場合、PowerManagerを使って以下の様に記述する。

AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
PowerManager powerManager =  (PowerManager)getSystemService(POWER_SERVICE); 
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK , "MyWakelockTag"); 
// wakeLock開始
wakeLock.acquire();

// 処理

// wakeLock解除
wakeLock.release();

これでも問題なく動くのだが、Androidではスリープ時にBroadcastを扱うための便利な仕組みが用意されている。

WakefulBroadcastReceiver

WakefulBroadcastReceiverはSupport Libraryに含まれるBroadcastReceiverのサブクラスである。
スリープ状態でServiceを扱うためのメソッドが二つ追加されている。
https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html

Manifest記述は通常のBroadcastReceiverと変わらない。
当然、Manifestへのuses-permission記述も必要となる。

AndroidManifest.xml
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver android:name=".MyBroadcastReceiver">
...
</receiver>
<service android:name=".MyService" />

サービスの起動にはstartServiceではなくstartWakefulServiceを使用する。
このメソッドは内部でstartServiceを呼んだあとWakelock.acquire()でスリープ制御を行っている。

MyBroadcastReceiver.java
public class MyBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Intent serviceIntent = new Intent(context,MyService.class);
        // サービス起動
        startWakefulService(context,serviceIntent);
    }
}

サービス側では処理の終了時に必ずWakefulBroadcastReceiver.completeWakefulIntent()を呼ぶ。
また、startWakefulService()ではIntent.putExtra()でwakelock制御IDをIntentに追記しているため、Service起動時のIntentを引数に入れること。

MyService.java
public class MyService extends IntentService {

    public MyService() {
        super("MyService");
    }

    @Override
    protected void onHandleIntent(final Intent intent) {
        try {
             // サービス内部の処理
        } finally {
            // Wakelockの解除処理が必ず呼ばれるようにしておく
            WakefulBroadcastReceiver.completeWakefulIntent(intent);                    
        }
    }
}

まとめ

コード量を大幅に削減できてID管理とかも裏でやってくれるのは楽だ。
スリープ時にBroadcastを処理することはよくあるので、ぜひ覚えておきたい。

103
101
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
103
101