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種類だけだ。
引数が多いが、第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);
}
まとめ
便利そうだけど使い道が思いつかない。
システムならともかく、アプリでどう使うべきなんだろう。