AndroidでManifestにIntentFilterを記述してもBroadcast Intentが受け取れない

  • 22
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Androidでは、Intent.ACTION_BOOT_COMPLETEDなど、AndroidManifest.xmlに<intent-filter>を記述するだけでOSや他のアプリが発行するインテントを受け取ることができます。
(PackageManagerのqueryBroadcastReceivers()でリストアップされるようになる)

AndroidManifest.xml
        <receiver android:name=".MyReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BATTERY_LOW"/>
            </intent-filter>
        </receiver>

一方、Intent.ACTION_SCREEN_ONなどはContext.registReceiverで明示的に登録しないと受け取れるようになりません。

MyActivity.java
    @Override
    public void onResume() {
        super.onResume();
        registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
    }

    @Override
    public void onPause() {
        super.onPause();
        unregisterReceiver(mReceiver);
    }

この違いはBroadcast Intentを発行するとき、Intent.FLAG_RECEIVER_REGISTERD_ONLYフラグが付けられているかどうか、のようでした。

【BroadcastReceiverについて】

FLAG_RECEIVER_REGISTERD_ONLYが付与されているIntentを受け取るにはContext.registerReceiverが必要なようです。
ActivityやServiceなどのContextのライフサイクルにそってregisterとunregisterをしなければいけないので少し面倒ですが、余計なBroadcastを受け取らずに済みます。

Context.registerReceiverが必須なシステムのintent

システムが発行しているBroadcast Intentのなかだとどれが当たるんでしょう。。
githubのmasterを検索すれば見つかると思いますが、使いそうなものを自分用メモとして残しておきます。

https://github.com/android/platform_frameworks_base/search?utf8=%E2%9C%93&q=FLAG_RECEIVER_REGISTERED_ONLY

Intent.ACTION_DREAMING_STARTED
Intent.ACTION_DREAMING_STOPPED
Intent.ACTION_SCREEN_ON
Intent.ACTION_SCREEN_OFF
Intent.ACTION_MANAGED_PROFILE_ADDED
Intent.ACTION_BATTERY_CHANGED
Intent.ACTION_POWER_CONNECTED
Intent.ACTION_TIME_TICK
Intent.ACTION_HEADSET_PLUG

AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG
AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG
AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG
AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG
AudioManager.ACTION_HDMI_AUDIO_PLUG

// あまり使わなそうなACTION
DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED
DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED
NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED
DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED  PowerManager.ACTION_POWER_SAVE_MODE_CHANGING
PowerManager.ACTION_POWER_SAVE_MODE_CHANGED
NetworkStatsService.ACTION_NETWORK_STATS_UPDATED    

結構ありますね。。
アプリを起動していないのにManifestに書かれただけで、頻繁に呼ばれることでシステムリソースを無駄に消費しないような工夫かと思います。
Intent.ACTION_BATTERY_CHANGEDやIntent.ACTION_SCREEN_ONなどは時々使いそうです。

Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOTという@hideなフラグもありましたが、端末ブート後には関係なさそうですね。
Intent.ACTION_DATE_CHANGEDなどはmanifestに記述するだけで、ちゃんと受信できていました。