web-dev-qa-db-ja.com

マニフェストとアクティビティのブロードキャストレシーバー登録

実行中のアクティビティまたはサービスから登録するのではなく、マニフェストに登録したばかりのときにブロードキャストレシーバーが動作することを期待できるときを理解するための助けが必要です。

したがって、たとえば、次のインテントフィルターでスタンドアロンレシーバーを登録すると、サービス/アクティビティへの参照がなくても機能します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    package="com.blk_burn.standalonereceiver"
    Android:versionCode="1"
    Android:versionName="1.0" >

    <uses-sdk Android:minSdkVersion="10" />
    <uses-permission Android:name="Android.permission.WAKE_LOCK"/>

    <application
        Android:icon="@drawable/ic_launcher"
        Android:label="@string/app_name" >

        <receiver Android:name="TestReceiver">
            <intent-filter>
                <action Android:name="Android.media.AUDIO_BECOMING_NOISY"/>
            </intent-filter>
        </receiver>

    </application>

</manifest>

ただし、Android.media.AUDIO_BECOMING_NOISYAndroid.intent.action.HEADSET_PLUGに置き換えても、レシーバーはトリガーされません( Android Documentation

このサイトで見つけたものから、このレシーバーを動作させるために既に実行されているアクティビティまたはサービスからこのレシーバーを登録する必要があります( Post )。

  • マニフェストでインテントフィルターを調整するだけでこれが機能しない理由と、レシーバーを参照/登録するサービスをバックグラウンドで実行する必要がある理由を教えてください。

  • Android.intent.action.HEADSET_PLUGを含むインテントフィルターを使用して、アプリのマニフェストにレシーバーを登録するだけの回避策はありますか?

  • Androidドキュメント からどのブロードキャストアクションを識別することができますか?マニフェストに適切なフィルターを設定するのではなく、サービスまたはアクティビティに登録させる必要がありますか?

67
Arnab C.

受信者がマニフェストに登録されていて、アプリが実行されていない場合、ブロードキャストを処理するための新しいプロセスが作成されます。コードで登録する場合、登録したアクティビティ/サービスのライフに関連付けられます。一部のブロードキャストでは、新しいアプリプロセスが存在しない場合、または新しいアプリプロセスが存在する場合、それを作成しても意味がありません。セキュリティ、パフォーマンスなどの影響。したがって、コードでのみレシーバーを登録できます。

HEADSET_PLUGブロードキャスト、アイデアは、すでに実行中のアプリがUI、音量などのアプリ固有の調整を行うためにこれを取得できるという考えのようです。

知る限り、この情報がすべてのブロードキャストについて要約されている単一の場所はありませんが、各IntentはJavaDocにそれを登録して使用する方法についてコメントを付ける必要がありますが、明らかにそれは場所に欠けています。 Intent.FLAG_RECEIVER_REGISTERED_ONLY のAndroidソースツリーをgrepすると、リストをコンパイルできるはずです。

90
Nikolay Elenkov

通常どおり、マニフェストファイルAndroidManifest.xmlでブロードキャストレシーバーを構成できます。このように構成されたBroadcastReceiverは、静的に登録されたと呼ばれます。

要素を使用して、レシーバをマニフェストファイルに登録できます。

<receiver
   Android:name=".ConnectivityChangeReceiver">
   <intent-filter>
      <action Android:name="Android.net.conn.CONNECTIVITY_CHANGE" />
   </intent-filter>
</receiver>

ネストされた要素は、レシーバーが反応するイベントを指定するために使用されます。

ダイナミックな放送受信機

別の方法として、BroadcastReceiver実装をコードに動的に登録できます。 ContextオブジェクトでregisterReceiver()メソッドを呼び出すだけです。

RegisterReceiver()メソッドは2つのパラメーターを取ります。

RegisterReceiver()メソッドの引数

  • receiver:登録するBroadcastReceiver
  • filter:受信者がリッスンするイベントを指定するIntentFilterオブジェクト。

この方法でレシーバーを登録すると、コンポーネントが存続する限り存続しますAndroid作成コンポーネント自体が破壊されるまでこのレシーバーにイベントを送信します。

ライフサイクルを正しく処理するのはあなたの仕事です。したがって、レシーバーを動的に追加するときは、アクティビティのonPause()メソッドで同じレシーバーを登録解除するように注意してください!

アクティビティのonResume()メソッドでレシーバーを登録し、onPause()メソッドでレシーバーの登録を解除することをお勧めします。

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

@Override
protected void onResume() {
   this.mReceiver = new ConnectivityChangeReceiver();
   registerReceiver(
         this.mReceiver, 
         new IntentFilter(
               ConnectivityManager.CONNECTIVITY_ACTION));
   super.onResume();
}

どのメソッドを使用して登録するか

BroadcastReceiverの登録に使用する方法は、アプリがシステムイベントで何を行うかによって異なります。基本的に、アプリがシステム全体のイベントについて知りたい理由は2つあると思います。

  • アプリはこれらのイベントに関する何らかのサービスを提供します
  • アプリは状態の変化に丁寧に対応したい

最初のカテゴリの例は、デバイスの起動後すぐに動作する必要があるアプリ、または何らかの種類の起動が必要なアプリですアプリがインストールされるたびに動作します。 Battery Widget ProまたはApp2SDは、これらの種類のアプリの良い例です。このタイプの場合、BroadcastReceiverをマニフェストファイルに登録する必要があります。

2番目のカテゴリの例は、アプリが依存する可能性のある状況の変化を知らせるイベントです。アプリが確立されたBluetooth接続に依存しているとします。状態の変化に対応する必要があります-ただし、アプリがアクティブな場合のみです。この場合、静的に登録されたブロードキャストレシーバーは必要ありません。動的に登録されたものがより合理的です。

また、静的に登録することさえ許可されていないイベントもいくつかあります。この例は、毎分ブロードキャストされるIntent.ACTION_TIME_TICKイベントです。静的な受信機が不必要にバッテリーを消耗するため、これは賢明な決定です。

19