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