ブロードキャストの概要

Android アプリは、Android システムとブロードキャスト メッセージを送受信できます。 他の Android アプリと同様に、 publish-subscribe 必要があります。これらのブロードキャストは、対象のイベントが発生すると送信されます。 たとえば、Android システムは、さまざまなシステム イベントが システムの起動時やデバイスの充電開始時などに発生します。アプリ カスタム ブロードキャストを送信することもできます。たとえば、 関心を持ちそうなもの(たとえば、新しいデータに ダウンロードされます)。

システムはブロードキャストの配信を最適化して 最適なシステム健全性を確保できます。そのため、ブロードキャストの配信時間は 保証されています。低レイテンシのプロセス間通信を必要とするアプリでは バインドされたサービスを検討してください。

アプリは特定のブロードキャストを受信するように登録できます。ブロードキャストが送信されると システムは、サブスクリプションを登録したアプリに、自動的にブロードキャストをルーティングします。 受信します。

一般的には、ブロードキャストはアプリ間のメッセージング システムとして使用できます。 通常のユーザーフローから外れますただし、こうしたルールを不正使用しないよう ブロードキャストに応答し、バックグラウンドで システムパフォーマンスの低下につながる 可能性があります

システム ブロードキャストについて

さまざまなシステム イベントが発生すると、システムが自動的にブロードキャストを送信します。 機内モードのオンとオフが切り替わったときなどです。システム ブロードキャストは、ブロードキャストが受信されるようにサブスクライブしているすべてのアプリ イベントです。

ブロードキャスト メッセージ自体は Intent でラップされます。 そのアクション文字列が、発生したイベント(例: android.intent.action.AIRPLANE_MODE)。インテントには、 追加フィールドに格納する追加情報ですたとえば、飛行機 mode インテントには、機内モードのインテントに モードがオンになっています。

インテントを読み取り、アクション文字列を取得する方法について詳しくは、 詳しくは、インテントとインテント フィルタ

システム ブロードキャスト アクションの完全なリストについては、 Android SDK の BROADCAST_ACTIONS.TXT ファイル。各ブロードキャスト アクションには、 これに関連する定数フィールドがあります。たとえば、定数の値は ACTION_AIRPLANE_MODE_CHANGEDandroid.intent.action.AIRPLANE_MODE。各ブロードキャスト アクションのドキュメント 対応する定数フィールドで取得できます。

システム ブロードキャストの変更

Android プラットフォームが進化するにつれて、システム ブロードキャストの方法が定期的に変更されています。 確認します。すべてのバージョンの Android をサポートするため、次の変更に留意してください。

Android 14

アプリがキャッシュに保存されている 状態では、ブロードキャスト配信は システムの健全性を重視して最適化されています。たとえば、あまり重要でないシステム ブロードキャスト、 ACTION_SCREEN_ON として アプリがキャッシュされた状態の間は遅延します。アプリがキャッシュから アクティブなプロセスに ライフサイクル全体の中では 防ぐことができます。

モジュールで宣言されている重要なブロードキャストは、 マニフェストを使用して、キャッシュからアプリを一時的に削除する 配信の状態を表します。

Android 9

Android 9(API レベル 28)以降、 NETWORK_STATE_CHANGED_ACTION ブロードキャストは、ユーザーの現在地や個人に関する情報を受信しない 保護します。

また、Android 9 以降を搭載したデバイスにアプリがインストールされている場合は、 Wi-Fi からのシステム ブロードキャストに SSID、BSSID、接続 スキャン結果などですこの情報を入手するには、 getConnectionInfo() してください。

Android 8.0

Android 8.0(API レベル 26)以降では、追加の 制限事項があります。

Android 8.0 以降をターゲットとするアプリの場合、マニフェストを使用して以下の操作を行うことはできません。 ほとんどの暗黙的なブロードキャスト(ターゲットとならないブロードキャスト)の あります。引き続き コンテキスト登録されたレシーバ。 把握するのに役立ちます

Android 7.0

Android 7.0(API レベル 24)以降では、以下のシステムを送信しません。 ブロードキャスト:

また、Android 7.0 以降を対象とするアプリでは、CONNECTIVITY_ACTION ブロードキャストを登録する必要があります。 registerReceiver(BroadcastReceiver, IntentFilter) を使用します。 マニフェストでレシーバーを宣言することはできません。

ブロードキャストの受信

アプリは、マニフェストで宣言されたレシーバを使用する方法の 2 つの方法でブロードキャストを受信できます。 コンテキスト登録されたレシーバです。

マニフェストで宣言されたレシーバー

マニフェストでブロードキャスト レシーバを宣言すると、システムにより (アプリがまだ実行されていない場合)は、ブロードキャストが送信されたときに受信されます。

マニフェストでブロードキャストのレシーバーを宣言する手順は、次のとおりです。

  1. <receiver> を指定します。 要素を宣言する必要があります。

    <!-- If this receiver listens for broadcasts sent from the system or from
         other apps, even other apps that you own, set android:exported to "true". -->
    <receiver android:name=".MyBroadcastReceiver" android:exported="false">
        <intent-filter>
            <action android:name="APP_SPECIFIC_BROADCAST" />
        </intent-filter>
    </receiver>
    

    インテント フィルタで、レシーバーが登録するブロードキャスト アクションを指定します。

  2. サブクラス BroadcastReceiveronReceive(Context, Intent) を実装します。「 ブロードキャスト レシーバを設定して、内容をログに記録し、 :

    Kotlin

    private const val TAG = "MyBroadcastReceiver"
    
    class MyBroadcastReceiver : BroadcastReceiver() {
    
        override fun onReceive(context: Context, intent: Intent) {
            StringBuilder().apply {
                append("Action: ${intent.action}\n")
                append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
                toString().also { log ->
                    Log.d(TAG, log)
    
                    val binding = ActivityNameBinding.inflate(layoutInflater)
                    val view = binding.root
                    setContentView(view)
    
                    Snackbar.make(view, log, Snackbar.LENGTH_LONG).show()
                }
            }
        }
    }
    

    Java

    public class MyBroadcastReceiver extends BroadcastReceiver {
            private static final String TAG = "MyBroadcastReceiver";
            @Override
            public void onReceive(Context context, Intent intent) {
                StringBuilder sb = new StringBuilder();
                sb.append("Action: " + intent.getAction() + "\n");
                sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");
                String log = sb.toString();
                Log.d(TAG, log);
    
                ActivityNameBinding binding =
                        ActivityNameBinding.inflate(layoutInflater);
                val view = binding.root;
                setContentView(view);
    
                Snackbar.make(view, log, Snackbar.LENGTH_LONG).show();
            }
        }
    

    ビュー バインディングを有効にするには、次の操作を行います。 モジュール レベルで viewBinding を構成する 追加します。

システム パッケージ マネージャーは、アプリのインストール時にレシーバーを登録します。 レシーバーはアプリへの個別のエントリ ポイントになります。つまり、 アプリが起動していない場合は、アプリが起動してブロードキャストを配信できるようにする。 確認できます。

システムが新しい BroadcastReceiver コンポーネントを作成する 受信する各ブロードキャストを処理します。このオブジェクトは、 onReceive(Context, Intent) への呼び出しの間。コードが このメソッドは、そのコンポーネントが アクティブです。

コンテキスト登録されたレシーバー

コンテキスト登録されたレシーバは、登録されている限り、ブロードキャストを受信する 検証します。たとえば、 Activity アクティビティが破棄されていない限り、ブロードキャストを受信します。もし 登録すると、アプリが動作している限り、ブロードキャストを受信します。 されます。

コンテキストを使用してレシーバーを登録する手順は、次のとおりです。

  1. アプリのモジュール レベルのビルドファイルに、バージョン 1.9.0 以降の AndroidX Core ライブラリ:

    Groovy

    dependencies {
        def core_version = "1.15.0"
    
        // Java language implementation
        implementation "androidx.core:core:$core_version"
        // Kotlin
        implementation "androidx.core:core-ktx:$core_version"
    
        // To use RoleManagerCompat
        implementation "androidx.core:core-role:1.0.0"
    
        // To use the Animator APIs
        implementation "androidx.core:core-animation:1.0.0"
        // To test the Animator APIs
        androidTestImplementation "androidx.core:core-animation-testing:1.0.0"
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation "androidx.core:core-performance:1.0.0"
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation "androidx.core:core-google-shortcuts:1.1.0"
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation "androidx.core:core-remoteviews:1.1.0"
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation "androidx.core:core-splashscreen:1.2.0-alpha02"
    }

    Kotlin

    dependencies {
        val core_version = "1.15.0"
    
        // Java language implementation
        implementation("androidx.core:core:$core_version")
        // Kotlin
        implementation("androidx.core:core-ktx:$core_version")
    
        // To use RoleManagerCompat
        implementation("androidx.core:core-role:1.0.0")
    
        // To use the Animator APIs
        implementation("androidx.core:core-animation:1.0.0")
        // To test the Animator APIs
        androidTestImplementation("androidx.core:core-animation-testing:1.0.0")
    
        // Optional - To enable APIs that query the performance characteristics of GMS devices.
        implementation("androidx.core:core-performance:1.0.0")
    
        // Optional - to use ShortcutManagerCompat to donate shortcuts to be used by Google
        implementation("androidx.core:core-google-shortcuts:1.1.0")
    
        // Optional - to support backwards compatibility of RemoteViews
        implementation("androidx.core:core-remoteviews:1.1.0")
    
        // Optional - APIs for SplashScreen, including compatibility helpers on devices prior Android 12
        implementation("androidx.core:core-splashscreen:1.2.0-alpha02")
    }
  2. インスタンスを BroadcastReceiver:

    Kotlin

    val br: BroadcastReceiver = MyBroadcastReceiver()
    

    Java

    BroadcastReceiver br = new MyBroadcastReceiver();
    
  3. インスタンスを IntentFilter:

    Kotlin

    val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
    

    Java

    IntentFilter filter = new IntentFilter(APP_SPECIFIC_BROADCAST);
    
  4. ブロードキャスト レシーバをエクスポートして表示するかどうかを選択します デバイス上の他のアプリこのレシーバが送信されたブロードキャストをリッスンしているかどうか 他のアプリから(所有する他のアプリであっても)は、 RECEIVER_EXPORTED フラグ。代わりに、このレシーバーが 1 対 1 の 送信する場合は、RECEIVER_NOT_EXPORTED フラグを使用します。

    Kotlin

    val listenToBroadcastsFromOtherApps = false
    val receiverFlags = if (listenToBroadcastsFromOtherApps) {
        ContextCompat.RECEIVER_EXPORTED
    } else {
        ContextCompat.RECEIVER_NOT_EXPORTED
    }
    

    Java

    boolean listenToBroadcastsFromOtherApps = false;
    if (listenToBroadcastsFromOtherApps) {
        receiverFlags = ContextCompat.RECEIVER_EXPORTED;
    } else {
        receiverFlags = ContextCompat.RECEIVER_NOT_EXPORTED;
    }
    
  5. 以下を呼び出してレシーバを登録する registerReceiver():

    Kotlin

    ContextCompat.registerReceiver(context, br, filter, receiverFlags)
    

    Java

    ContextCompat.registerReceiver(context, br, filter, receiverFlags);
    
  6. ブロードキャストの受信を停止するには、unregisterReceiver(android.content.BroadcastReceiver) を呼び出します。 不要になった場合は必ず受信側の登録を解除してください。 無効になりました。

    以下の目的で受信者の登録と登録解除を行う場所には注意してください。 たとえば、アクティビティのコンテキストを使用して onCreate(Bundle) にレシーバを登録すると、 onDestroy() の登録を解除して、 アクティビティのコンテキストからレシーバーが漏洩しないようにします。登録した場合 onResume() のレシーバーを使用する場合は、 onPause() で登録を解除して 複数回登録する(ブロードキャストを受信したくない場合に これにより、不要なシステムのオーバーヘッドを削減できます)。禁止事項 onSaveInstanceState(Bundle)の登録を解除し、 これは、ユーザーが履歴スタックに戻ったときに呼び出されないためです。

プロセス状態への影響

BroadcastReceiver が その中のプロセスに影響が及ばなかった場合に、そのプロセスが 攻撃を受ける可能性が高まります。フォアグラウンド プロセスはレシーバの onReceive() メソッドを実行します。「 メモリ負荷が極端な場合を除いて、プロセスが実行されます。

BroadcastReceiver は onReceive() の後、無効になります。受信側のホスト 重要性はアプリ コンポーネントによって決まります。このプロセスが マニフェストで宣言されたレシーバー(ユーザーが初めて使用するアプリで頻繁に発生します) (最近やり取りしていない)場合は、onReceive() の後にシステムによって強制終了され、 リソースを節約できます。

したがって、ブロードキャスト レシーバは、長時間実行されるバックグラウンド スレッドを開始すべきではありません。 onReceive() の後、いつでもプロセスを停止して再利用できます。 作成されたスレッドを終了します。プロセスを継続するには、 JobService JobScheduler を使用して受信側から プロセスがまだ機能していることをシステムに知らせる必要があります。 詳しくは、バックグラウンド処理の概要をご覧ください。

ブロードキャストの送信

Android では、アプリがブロードキャストを送信する 3 つの方法が用意されています。

  • sendOrderedBroadcast(Intent, String) メソッドは一度に 1 つのレシーバにブロードキャストを送信します。各レシーバは その結果を次のレシーバに伝播するか、 ブロードキャストを完全に中止して、他のモジュールに渡されないように 受信します。レシーバが実行されるオーダーは、 一致するインテント フィルタの android:Priority 属性。新しいレシーバと 任意の順序で実行されます。
  • sendBroadcast(Intent) メソッドは 未定義の順序ですべてのレシーバにブロードキャストします。これを通常の ブロードキャスト。この方法はより効率的ですが、レシーバは読み取りや書き込みを ブロードキャストから受信したデータを伝播したり、他のレシーバからの結果を ブロードキャストを中止します。

次のコード スニペットは、 インテントと sendBroadcast(Intent) の呼び出し。

Kotlin

Intent().also { intent ->
    intent.setAction("com.example.broadcast.MY_NOTIFICATION")
    intent.putExtra("data", "Nothing to see here, move along.")
    sendBroadcast(intent)
}

Java

Intent intent = new Intent();
intent.setAction("com.example.broadcast.MY_NOTIFICATION");
intent.putExtra("data", "Nothing to see here, move along.");
sendBroadcast(intent);

ブロードキャスト メッセージは Intent オブジェクトでラップされます。 インテントのアクション文字列では、アプリの Java パッケージ名の構文と、 ブロードキャスト イベントを一意に識別する ID を指定します。追加の情報を添付できます putExtra(String, Bundle) を使用してインテントに追加します。 同じ組織内の一部のアプリにブロードキャストを制限することもできます。 インテントで setPackage(String) を呼び出す。

権限の設定によるブロードキャストの制限

権限を使用すると、ブロードキャストを、アプリを保持している一連のアプリ ユーザーに付与します。送信者または受信者のいずれかに対して制限を ブロードキャストのレシーバに送られます。

権限を設定した送信

sendBroadcast(Intent, String) を呼び出すか、 sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle) には、 権限パラメータを指定します。権限のリクエストを行った受信者のみが、 マニフェストの タグ(その後、この API に ブロードキャストを受信できることを意味します。たとえば、 ブロードキャストを送信するコードは次のようになります。

Kotlin

sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND),
              Manifest.permission.BLUETOOTH_CONNECT)

Java

sendBroadcast(new Intent(BluetoothDevice.ACTION_FOUND),
              Manifest.permission.BLUETOOTH_CONNECT)

ブロードキャストを受信するには、受信側のアプリが次のように権限をリクエストする必要があります。 下に示します。

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

環境変数には、既存のシステム権限、 BLUETOOTH_CONNECT カスタム権限を定義するか、 <permission> 要素。対象 セキュリティに関する一般的な情報については、システム 権限

権限を設定した受信

ブロードキャスト レシーバの登録時に権限パラメータを指定する場合 (registerReceiver(BroadcastReceiver, IntentFilter, String, Handler) を使用するか、 <receiver> タグ( マニフェストで指定)、その権限で権限をリクエストした放送局のみが <uses-permission> タグ 含まれている場合(その後、権限があればその権限が付与されます) dangerous)は、インテントをレシーバに送信できます。

たとえば、受信側のアプリに、マニフェストで宣言されているレシーバーが 下に示します。

<receiver android:name=".MyBroadcastReceiver"
          android:permission="android.permission.BLUETOOTH_CONNECT">
    <intent-filter>
        <action android:name="android.intent.action.ACTION_FOUND"/>
    </intent-filter>
</receiver>

または、受信アプリにコンテキスト登録されたレシーバーがあるとします。

Kotlin

var filter = IntentFilter(Intent.ACTION_FOUND)
registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null )

Java

IntentFilter filter = new IntentFilter(Intent.ACTION_FOUND);
registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null );

次に、これらのレシーバにブロードキャストを送信できるようにするため、送信アプリは 次のように権限をリクエストします。

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

セキュリティに関する考慮事項とおすすめの方法

ここでは、送信と送信を行う際のセキュリティ上の考慮事項と ブロードキャストを受信します。

  • 複数のアプリがそれぞれのデバイスで同じブロードキャストを受信するよう登録している場合は、 システムが多くのアプリを起動し、その結果、 デバイスのパフォーマンスとユーザー エクスペリエンスの両方に大きく影響します。避けるべきこと マニフェスト宣言よりもコンテキスト登録を使用します。 場合によっては、Android システム自体が、コンテキスト登録された 受信します。たとえば、CONNECTIVITY_ACTION ブロードキャストは コンテキスト登録されたレシーバのみに配布できます。

  • 暗黙的なインテントを使用して機密情報をブロードキャストしないでください。「 ブロードキャストを受信するために登録したアプリで情報を読み取ることができます。 ブロードキャストを受信できるレシーバーを制御するには、次の 3 つの方法があります。

    • ブロードキャストの送信時に権限を指定できます。
    • Android 4.0 以降では、 package を次のように置き換えます。 送信すると、setPackage(String) あります。ブロードキャストの対象は、指定した一連のアプリ 一致します。
  • レシーバを登録すると、あらゆるアプリが悪意のある可能性のある アプリのレシーバにブロードキャストできます。検出ルールのしきい値を 受信するブロードキャスト:

    • ブロードキャストのレシーバーを登録する際に、権限を指定できます。
    • マニフェストで宣言されたレシーバの場合、 android:exported 属性を「false」に設定使用します。受信側のデバイスが アプリ外のソースからのブロードキャストに 対応できます
  • ブロードキャスト アクションの名前空間はグローバルです。アクション名は 他の文字列は、ユーザーが所有する名前空間に記述するか、 誤って他のアプリと競合する場合があるためです。

  • レシーバの onReceive(Context, Intent) メソッドは 実行して結果を返す必要があります。必要に応じて 実行する場合は、スレッドの生成や起動に関する注意を バックグラウンド サービスが停止すると、システムがプロセス全体を強制終了できるため、 返品可能(返品手数料: onReceive())。詳細については、プロセスへの影響 長時間実行される処理を実行するには、 次のことをおすすめします。

    • goAsync() に発信: レシーバの onReceive() メソッドを呼び出し、BroadcastReceiver.PendingResult をバックグラウンド スレッドに渡します。 これにより、onReceive() から返された後もブロードキャストがアクティブな状態が維持されます。 ただし、この方法であっても、システムにより、 10 秒未満に短縮できます。Kubernetes では、 処理を別のスレッドに移すこともおすすめします。
    • JobScheduler を使用して、ジョブのスケジュール設定を行います。詳細 詳しくは、インテリジェントなジョブ スケジュール設定をご覧ください。
  • ブロードキャスト レシーバからアクティビティを開始しないでください。ユーザー エクスペリエンスは 不快感を与える受信者が複数ある場合には特にそうです代わりに 通知を表示する。