BroadcastReceiverの処理結果が取れる?
ある日、BroadcastReceiver.setResult()
があることに気がついた。
ずっとBroadcastの結果は取れないものだと思っていたが、Context.sendOrderedBroadcast()
を使用することでその結果を受け取ることができるようだ。
概要
大まかな処理手順はこうだ。
まず、sendOrderedBroadcast()
ではBroadcastReceiver
がその優先順位にしたがって呼び出される。
それぞれのBroadcastReceiver
はonReceive()
の最後にsetResult()
によって処理結果を追記する。
sendOrderedBroadcast()
では一番最後に処理を行うBroadcastReceiver
を直接指定することができるため、そのonReceive()
の中でgetResultCode()
,getResultData()
,getResultExtras()
を参照することですべてのBroadcastの最終的な処理結果を受け取ることができる。
優先順位設定
Broadcastの優先順位はIntentFilter.setPriority()
で行う。
数字の大きいものが優先度が高く、デフォルトは0。
おそらくIntentFilter.SYSTEM_HIGH_PRIORITY
からIntentFilter.SYSTEM_LOW_PRIORITY
の間で設定したほうが良いと思う。
BroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(MY_ACTION);
// 優先度を高めに設定
intentFilter.setPriority(100);
registerReceiver(receiver, intentFilter);
BroadcastReceiverの実装
BroadcastReceiver
側の処理はsetResult
系の処理をする事以外は何もしなくて良い。
先に実行されたBroadcastReceiver
の処理結果はgetResultCode()
,getResultData()
,getResultExtras()
で取得できる。
setResult()した場合、値はすべて上書きされることに注意
@Override
public void onReceive(Context context, Intent intent)
{
// onReceive処理
// 前のBroadcastReceiverの判定を引き継ぐ
setResultCode(getResultCode());
// Extrasに何か入れてみる
// 引数をtrueにするとnullの場合自動生成してくれる
Bundle extras = getResultExtras(true);
extras.putString("key", "value");
setResultExtras(extras);
}
何らかの理由で以降のBroadcastReceiver
を実行しないようにするにはabortBroadcast()
で以降のBroadcastに処理が伝達されないようにすれば良い。
ただし、確実に止められるのは自分より優先度が低いBroadcastReceiver
のみとなる。
優先度が等しいBroadcastReceiver
は自分より前に実行されている可能性があるため。
@Override
public void onReceive(Context context, Intent intent)
{
// onReceive処理
if(FAILED){
// 失敗したのでこのReceiverで処理を終了したい
// RESULT_CANCELEDにするのが良いかも?
setResultCode(Activity.RESULT_CANCELED);
// これより優先順位が低いBroadcastReceiverは実行されない
abortBroadcast();
}
}
Broadcastの送信
Context.sendOrderedBroadcast()
は2種類あるが、処理結果を扱えるのは[1種類](http://developer.android.com/reference/android/content/Context.html#sendOrderedBroadcast(android.content.Intent, java.lang.String, android.content.BroadcastReceiver, android.os.Handler, int, java.lang.String, android.os.Bundle))だけだ。
引数が多いが、第3引数のresultReceiver
が最後に実行されるBroadcastReceiver
になる。initial〜
系の引数は処理結果のデフォルト値を格納する。
public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)
結果は当然、resultReceiver
に指定したBroadcastReceiver
で受け取る。
abortBroadcast()
された場合でもresultReceiver
は実行されるようだ。
(IntentFilter
でBroadcastを受信しているわけではないので当然か)
@Override
public void onReceive(Context context, Intent intent)
{
// 処理結果
getResultCode();
getResultData();
getResultExtras(false);
}
まとめ
便利そうだけど使い道が思いつかない。
システムならともかく、アプリでどう使うべきなんだろう。