BroadcastReceiver
クラス内でService
を拡張する内部クラスがある場合、BroadcastReceiver
クラスがService
クラス?または別の言い方をすると、BroadacstReceiver
のonReceive()
メソッドは追加のスレッドで開始されますか?
OnReceive()メソッドは、registerReceiver()バリアントを使用して別のスレッドでスケジュールするように要求しない限り、常にメインスレッド(「UIスレッド」とも呼ばれます)で呼び出されます。
Context.registerReceiver(BroadcastReceiver receiver,
IntentFilter filter,
String broadcastPermission,
Handler scheduler)
AndroidのBroadcastReceiversは新しいスレッドで開始されますか?
通常は必ずというわけではありませんが、すべて登録方法によって異なります。
BroadcastReceiver
を登録する場合:
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
メインアクティビティスレッド(別名UIスレッド)で実行されます。
別のスレッドで実行されている有効なBroadcastReceiver
を使用してHandler
を登録する場合:
registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)
Handler
のコンテキストで実行されます
例えば:
HandlerThread handlerThread = new HandlerThread("ht");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
context.registerReceiver(receiver, filter, null, handler); // Will not run on main thread
onReceive()メソッドはメインスレッドで呼び出されます。 したがって、サービスクラスへのすべてのアクセスがメインスレッド内から行われる場合、同期は必要ありません。
また、AndroidManifest.xmlで「Android:process」レシーバー要素属性を指定できます。 こちら を参照してください。これにより、レシーバーが別のプロセスとして実行され、メインのUIスレッドに関連付けられないように指定できます。
RegisterReceiver(broadcastReceiver, intentFilter).
を使用すると、AndroidブロードキャストレシーバーはデフォルトでGUIスレッド(メインスレッド)で開始されます
ただし、次のようにワーカースレッドで実行できます。
HandlerThreadを使用する場合は、BroadcastReceiverの登録を解除した後、必ずスレッドを終了してください。そうでない場合、Linuxレベルでファイル記述子(FD)リークが発生し、登録/登録解除を続行すると、最終的にアプリケーションがクラッシュします。
unregisterReceiver(...);
次に、looper.quit();またはlooper.quitSafely();
private Handler broadcastReceiverHandler = null;
private HandlerThread broadcastReceiverThread = null;
private Looper broadcastReceiverThreadLooper = null;
private BroadcastReceiver broadcastReceiverReadScans = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
}
}
private void registerForIntents() {
broadcastReceiverThread = new HandlerThread("THREAD_NAME");//Create a thread for BroadcastReceiver
broadcastReceiverThread.start();
broadcastReceiverThreadLooper = broadcastReceiverThread.getLooper();
broadcastReceiverHandler = new Handler(broadcastReceiverThreadLooper);
IntentFilter filterScanReads = new IntentFilter();
filterScanReads.addAction("ACTION_SCAN_READ");
filterScanReads.addCategory("CATEGORY_SCAN");
context.registerReceiver(broadcastReceiverReadScans, filterScanReads, null, broadcastReceiverHandler);
}
private void unregisterIntents() {
context.unregisterReceiver(broadcastReceiverReadScans);
broadcastReceiverThreadLooper.quit();//Don't forget
}