Broadcastは知っているはずだ

10358 ワード

Androidでは、Broadcastはアプリケーション間で情報を転送するメカニズムとして広く使われています.Broadcastの使い方を詳しく学ぶ必要があります.
Broadcastタイプ
一般放送
完全に非同期で、同じ時刻(論理的に)すべての受信者に受信され、メッセージングの効率が高いが、受信者は処理結果を次の受信者に渡すことができず、ブロードキャストIntentの伝播を終了することができないという欠点がある.
ちくじほうそう
受信者によって宣言された優先度(要素の属性で宣言されている場合、数が大きいほど優先度が高くなり、値範囲は-1000~1000です.また、IntentFilterオブジェクトのsetPriority()を呼び出して設定することもできます)に従って、受信者は放送を順次受信します.例えば、AのレベルがBより高く、BのレベルがCより高い場合、放送はまずAに伝達され、Bに伝達され、最後にCに伝達される.Aは放送を得た後、放送にデータを格納することができ、放送がBに伝達されると、Bは放送からAが格納したデータを取得することができる.
Broadcast登録方式
登録方法に関係なく、BroadcastReceiverクラスの実装とonReceiveメソッドの実装を作成します.
public class MyBroadcast extends BroadcastReceiver{
    private static final String TAG = "MyBroadcast";
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG,"broadcast msg ----->" + intent.getStringExtra("name"));
        Log.d(TAG,"broadcastReceiver  ----->");
    }
}


Broadcast静的登録
暗黙的に登録するのはAndroidManifestです.xmlにはラベルで登録し、ラベル内にラベルでフィルタを設定します.登録コードは次のとおりです.

    
        
    


ブロードキャストコードの送信:
Intent intent = new Intent();
intent.putExtra("name","my broadcast");
intent.setAction("com.cfox.boradcast");
sendBroadcast(intent);

Broadcast動的登録
InentFilterオブジェクトを定義して設定し、登録が必要な場所でContextを調整します.registerReceiver()メソッドは、キャンセルするとContextを呼び出す.unregisterReceiver()メソッド.動的に登録されたBroadcastReceiverのContextオブジェクトが破棄されると、BroadcastReceiverは自動的に登録をキャンセルします.
登録コードは次のとおりです.
IntentFilter filter = new IntentFilter();
filter.addAction("com.cfox.boradcastFilter");
MyBroadcast broadcast = new MyBroadcast();
registerReceiver(broadcast,filter);

送信コードは次のとおりです.
Intent intent = new Intent();
intent.putExtra("name","my broadcast");
intent.setAction("com.cfox.boradcastFilter");
sendBroadcast(intent);

一般放送
上で紹介したのはすべて一般放送に基づいているので、ここではあまり言わないで、上のコードを貼り直して、復習しましょう.登録コードは次のとおりです.

    
        
    


ブロードキャストコードの送信:
Intent intent = new Intent();
intent.putExtra("name","my broadcast");
intent.setAction("com.cfox.boradcast");
sendBroadcast(intent);

秩序あるブロードキャストの使用
秩序化されたブロードキャストを使用するには、優先度を設定します.前述したように、ここでは説明しません.登録コード(静態):

    
        
    



    
        
    


登録コード(ダイナミック):
IntentFilter filter1 = new IntentFilter();
filter1.addAction("com.cfox.broadcast");
filter1.setPriority(1000);
MyBroadcastOne broadcastOne = new MyBroadcastOne();
registerReceiver(broadcastOne,filter1);

IntentFilter filter2 = new IntentFilter();
filter2.addAction("com.cfox.broadcast");
filter2.setPriority(999);
MyBroadcastTow broadcastTwo = new MyBroadcastTow();
registerReceiver(broadcastTwo,filter2);

秩序放送を送信
まず、秩序ある放送を送信する方法を見てみましょう.
sendOrderedBroadcast(
        Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
        Handler scheduler, int initialCode, String initialData,
        Bundle initialExtras)

パラメータが多いので、以下に紹介します.
  • パラメータ1:Intent
  • パラメータ2:broadcast権限
  • の設定
  • パラメータ3:これはブロードキャスト(broadcastReceiver)であり、変更ブロードキャストは、シーケンスブロードキャストが終了した後にブロードキャストを呼び出し、シーケンスブロードキャストが実行中に終了した場合、このブロードキャストは実行されない.
  • パラメータ4:Handler、null、nullの場合はメインスレッドのContext
  • が使用されます.
  • パラメータ5:結果コード、常時Activity.RESULT_OK
  • パラメータ6:onReceiveでgetResultData()メソッドを使用して取得できる初期データ.通常nullである.
  • パラメータ7:Bundle、常にnull
  • 次に、秩序あるブロードキャストを送信する方法を見てみましょう.
    Intent intent = new Intent();
    intent.putExtra("name","my broadcast");
    intent.setAction("com.cfox.broadcast");
    sendOrderedBroadcast(intent,null,new Receiver(),null,0,"hello good",null);
    

    コードは多くありません.説明する必要はありません.次に、BroadcastReceiverクラスを継承します.
  • MyBroadcastOne.class
  • public class MyBroadcastOne extends BroadcastReceiver {
        private static final String TAG = "MyBroadcastOne";
        @Override
        public void onReceive(Context context, Intent intent) {
    
            Log.d(TAG,"MyBroadcastOne msg ----->" + intent.getStringExtra("name"));
            Log.d(TAG,"MyBroadcastOne  ----->");
            Log.d(TAG,"receiver--isOrderedBroadcast-->" + isOrderedBroadcast());
    
            if (intent.getStringExtra("name").equals("my broadcast")){
                Log.d(TAG,"ResultData msg ----->" + getResultData());
                setResultData(getResultData() + " good good");
    //            abortBroadcast();//     
            }
        }
    }
    
  • MyBroadcastTow.class
  • public class MyBroadcastTow extends BroadcastReceiver{
        private static final String TAG = "MyBroadcastTow";
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG,"MyBroadcastTow msg ----->" + intent.getStringExtra("name"));
            Log.d(TAG,"MyBroadcastTow  ----->");
            Log.d(TAG,"ResultData msg ----->" + getResultData());
            Log.d(TAG,"receiver--isOrderedBroadcast-->" + isOrderedBroadcast());
        }
    }
    
  • Receiver
  • public class Receiver extends BroadcastReceiver {
        private static final String TAG = "Receiver";
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG,"ResultData msg ----------->" + getResultData());
            Log.d(TAG,"receiver--isOrderedBroadcast-->" + isOrderedBroadcast());
    
        }
    }
    
    

    実行結果
    D/MyBroadcastOne: MyBroadcastOne msg ----->my broadcast
    D/MyBroadcastOne: MyBroadcastOne  ----->
    D/MyBroadcastOne: receiver--isOrderedBroadcast-->true
    D/MyBroadcastOne: ResultData msg ----->hello good
    D/MyBroadcastTow: MyBroadcastTow msg ----->my broadcast
    D/MyBroadcastTow: MyBroadcastTow  ----->
    D/MyBroadcastTow: ResultData msg ----->hello good good good
    D/MyBroadcastTow: receiver--isOrderedBroadcast-->true
    D/Receiver: ResultData msg ----------------------->hello good good good
    D/Receiver: receiver--isOrderedBroadcast-->false
    

    運行結果を見ると、多くのことが明らかになります.もう少し簡単に紹介します.
    順序付き放送の終了
    順序付きブロードキャストでは、onReceiveメソッドの適切な場所でabortBroadcast()メソッドを呼び出してブロードキャストを終了します.
    いくつかの方法の紹介
  • isOrderedBroadcast()は、このBroadcastReceiverが秩序正しく放送されているかどうかを判断する.
  • getResultData()は、ブロードキャストの送信時に6番目のパラメータで初期化設定できるBroadcastReceiver間転送データを取得します.

  • LocalBroadcastManagerによる動的登録
    IntentFilter filter1 = new IntentFilter();
    filter1.addAction("com.cfox.broadcast");
    filter1.setPriority(1000);
    MyBroadcastOne broadcastOne = new MyBroadcastOne();
    
    IntentFilter filter2 = new IntentFilter();
    filter2.addAction("com.cfox.broadcast");
    filter2.setPriority(999);
    MyBroadcastTow broadcastTwo = new MyBroadcastTow();
    
    LocalBroadcastManager.getInstance(this).registerReceiver(broadcastOne,filter1);
    LocalBroadcastManager.getInstance(this).registerReceiver(broadcastTwo,filter2);
    

    異なる登録方式のブロードキャスト受信機コールバックonReceive(context,intent)におけるcontextの具体的なタイプ
    以下の内容は以下のとおりです.http://blog.csdn.net/oonullpointeralex/article/details/48015107
  • 静的に登録されたContextReceiverの場合、コールバックonReceive(context,intent)のcontextは、具体的にはReceiverRestrictedContextを指す.
  • グローバルブロードキャストの動的登録のContextReceiverについて、コールバックonReceive(context,intent)におけるcontextは、具体的にはActivity Contextを指す.
  • LocalBroadcastManagerで動的に登録されているContextReceiverについて、コールバックonReceive(context,intent)のcontextは、具体的にはApplication Contextを指す.
  • 注:LocalBroadcastManager方式で送信されるアプリケーション内ブロードキャストは、LocalBroadcastManagerで動的に登録されているContextReceiverでのみ受信できます(静的登録または他の方式で動的に登録されているContextReceiverでは受信できません).

  • 使用上の注意
    静的に登録する放送受信機は、appが終了しても、主に対応する放送が送信されても受信可能であるが、この記述はAndroid 3.1から成立しない可能性がある.
    Android 3.1開始システムは、Intentで放送関連のflagにパラメータを追加し、それぞれFLAG_INCLUDE_STOPPED_PACKAGESとFLAG_EXCLUDE_STOPPED_PACKAGES.
  • FLAG_INCLUDE_STOPPED_PACKAGES:停止したパケットを含む(停止:パケットが存在するプロセスが終了した)
  • .
  • FLAG_EXCLUDE_STOPPED_PACKAGES:停止したパケットは含まれていません.

  • 主な原因は以下の通りである:Android 3.1から、システム自体は、すべてのappが現在稼働しているかどうかの追跡を追加します.ブロードキャストを送信する場合、どのブロードキャストタイプであっても、システムのデフォルト値はFLAG_に直接増加します.EXCLUDE_STOPPED_PACKAGESのflagは、静的に登録されたブロードキャスト受信機であっても、そのプロセスが終了したappに対してブロードキャストを受信できない.
    これにより、システムブロードキャストについては、システム内部から直接発行されるため、このintent flag値を変更することができないため、3.1静的に登録された受信システムブロードキャストに対するBroadcastReceiverが開始され、Appプロセスが終了するとブロードキャストを受信できなくなる.
    ただし、カスタムブロードキャストでは、このflagをFLAG_に複写することができます.INCLUDE_STOPPED_PACKAGESは、静的に登録されているBroadcastReceiverが、存在するAppプロセスが終了してもブロードキャストを受信してアプリケーションプロセスを開始するようにしているが、このときのBroadcastReceiverは新規である.
    Intent intent = new Intent();
    intent.setAction(BROADCAST_ACTION);
    intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
    intent.putExtra("name", "qqyumidi");
    sendBroadcast(intent);
    

    注意1:動的登録タイプのBroadcastReceiverでは、Activityなどの実際の他のコンポーネントの登録と登録解除が行われるため、この変更の影響を受けません.注2:3.1以前、多くのappが静的登録方式で各種システム放送を傍受し、それによっていくつかの業務上の処理を行う可能性があると信じていた(例えば、インスタントappが終了しても受信でき、サービスを起動することができるなど).3.1以降、静的登録はブロードキャスト方式の変更を受け入れ、このようなスキームが実行できなくなることを直接招く.したがって、サービスとアプリケーション自体を異なるプロセスに設定することで、このようなニーズを実現するための実行可能な代替案となっている.
    BroadcastReceiverでは時間のかかる操作は行わない
    BroadcastReceiverのライフサイクルは短く、時間のかかる操作はonReceiverで行うべきではありません.onReceiver()のメソッドが10秒以内に実行できない場合、プログラムが応答しない、すなわちよく知られているANR(Application not Response)が生成されます.
    ブロードキャスト受信者のオブジェクトは、この関数をコールバックする場合にのみ有効であり、この関数から戻ると、このオブジェクトは終了し、アクティブになりません.onReceive()では、非同期の操作は実行できません.onRecove()という関数から戻って非同期の操作を処理する必要があるため、このブロードキャスト受信者はアクティブにならず、システムは非同期の操作が完了する前にプロセスを終了します.