Android四大組件----BroadcastReceiver

一、什麼是BroadcastReceiver?

就是廣播接收者,用於接收廣播的Intent,可以接收應用程序發出的廣播,也可以是系統發出的,如電量變化、插拔耳機、開機完成等等,然後再做相應的事件處理,其廣泛應用於應用程序間的信息傳輸。

二、有哪幾種廣播?

1、普通廣播

對於多個接收者來說是完全異步的,通常每個接收者都無需等待即可以接收到廣播,接收者相互之間不會有影響。對於這種廣播,接收者無法終止廣播,即無法阻止其他接收者的接收動作。

2、有序廣播

按照接收者的優先級順序接收廣播 , 優先級別在 intent-filter 中的 priority 中聲明, 也可以在代碼中設定,-1000 到1000 之間 ,值越大,優先級越高 。可以終止廣播意圖的繼續傳播,接收者可以篡改內容。

3、常駐廣播

異步廣播在發送者發出後,會一直存放在系統中,任何後續註冊的BroadcastReceiver都可以繼續處理該broadcast。廣播發送者可以去除該廣播。

三、生命週期

生命週期只有十秒左右,如果在 onReceive() 內做超過十秒的事情,就會報錯 。每次廣播到來時 , 會重新創建 BroadcastReceiver 對象 , 並且調用 onReceive() 方法 , 執行完以後 , 該對象即被銷燬 。當 onReceive() 方法在 10 秒內沒有執行完畢, Android 會認爲該程序無響應。所以在BroadcastReceiver 裏不能做一些比較耗時的操作。

四、發送廣播需要註冊,如何註冊?

1、靜態註冊

在AndroidManifest.xml中用標籤聲明註冊,並在標籤內用標籤設置過濾器,這種註冊方式是常駐型的。

                 <receiverandroid:name=".StaticReceiver">
                     <intent-filter>
                         <actionandroid:name="com.example.print"></action>
                     </intent-filter>
                 </receiver>

2、動態註冊

動態註冊方式在activity或service裏面調用函數來註冊,和靜態的內容差不多,一個形參是receiver,另一個是IntentFilter,其中裏面是要接收的action。

                     IntentFilter filter = newIntentFilter();
                     filter.addAction(ACTION_PRINT);
                     registerReceiver(myReceiver,filter);

去註冊

         unregisterReceiver(myReceiver);

一般:在onStart中註冊,onStop中取消unregisterReceiver

五、廣播的發送

1、普通廣播

sendBroadcast(intent),該函數有多種構造,我們已最簡單的做介紹,下同

                             Intentintent = new Intent();
                             intent.setAction(ACTION_PRINT);
                             sendBroadcast(intent);

2、有序廣播

sendOrderedBroadcast(intent, receiverPermission),receiverPermission是權限,一個接收器必須持有該權限才能接收到廣播,可以爲null。

                Intent intent = new Intent();
                             intent.setAction(ACTION_PRINT);
                             sendOrderedBroadcast(intent,null);

3、常駐廣播

sendStickyBroadcast(intent),該廣播需要權限android.permission.BROADCAST_STICKY才能發送,去除廣播用removeStickyBroadcast(intent),同樣也需要權限,不再舉例。

另外,sendStickyOrderedBroadcast這個廣播既有常駐廣播的特性也具有有序廣播的特性,我們可以稱爲常駐有序廣播

六、廣播的接收和處理

創建BroadcastReceiver對象,並且實現onReceive方法,然後可以在onReceive方法中根據不同的廣播事件進行相應的處理。

16.      

package com.example.broadcastreceiverdemo;
        
       import android.content.BroadcastReceiver;
       import android.content.Context;
       import android.content.Intent;
       import android.os.Bundle;
       import android.util.Log;
        
       public class StaticReceiver extendsBroadcastReceiver {
          privatestatic final String TAG = "kingfong";
          privatestatic final String ACTION_PRINT = "com.example.print";
        
          @Override
          publicvoid onReceive(Context context, Intent intent) {
                   //TODO Auto-generated method stub
                   StringintentAction = intent.getAction();
                   if(intentAction.equals(ACTION_PRINT)){
                             Bundleb = intent.getExtras();
                             Log.d(TAG,"StaticReceiver:Ihave received the boradcast");
                   }
          }
      }

1、普通廣播

各個BroadcastReceiver對象處理廣播順序並不固定,和註冊廣播的順序有關係,相互之間互不影響。在onReceive中做一些簡單的處理,但不要太耗時。如果需要做大量的工作,需要啓動service來處理。這裏不能使用子線程來解決 , 因爲 BroadcastReceiver 的生命週期很短 , 子線程可能還沒有結束BroadcastReceiver 就先結束了,BroadcastReceiver 一旦結束,此時 BroadcastReceiver 的所在進程很容易在系統需要內存時被優先殺死 ,因爲它屬於空進程 ( 沒有任何活動組件的進程 ),如果它的宿主進程被殺死,那麼正在工作的子線程也會被殺死 . 所以採用子線程來解決是不可靠的。

2、有序廣播

有序廣播發送時一般需要帶權限參數,如果爲null則表示不要求接收者聲明指定的權限,如果不爲null,則表示接收者若要接收此廣播,需聲明指定權限。接收者會按照優先級大小先後處理該廣播,優先級可以在註冊時IntentFilter的android:priority參數指定,也可以在代碼中設置,這個屬性的範圍在-1000到1000,數值越大,優先級越高。高優先級可以調用以下接口終止該廣播的傳遞。

優先級設定

               <receiverandroid:name=".StaticReceiver">
                   <intent-filterandroid:priority="100">
                       <actionandroid:name="com.example.print"></action>
                   </intent-filter>
               </receiver>

        
                   IntentFilterfilter = new IntentFilter();
                   filter.addAction(ACTION_PRINT);
                   filter.setPriority(200);
                   registerReceiver(myReceiver,filter);

   終止廣播傳遞

                             if(isOrderedBroadcast()){                                
                                      abortBroadcast();
                             }

3、常駐廣播

常駐廣播發送後,在發送者清除之前,任何時候註冊的BroadcastReceiver都可以接收該廣播,並做處理。

七、常用API接口

       public abstract void onReceive(Contextcontext, Intent intent);
       public final void setResultCode(int code)
       public final int getResultCode()
       public final void setResultData(String data)
       public final String getResultData()
       public final void setResultExtras(Bundleextras)
       public final Bundle getResultExtras(booleanmakeMap)
       public final void setResult(int code, Stringdata, Bundle extras)
       public final boolean getAbortBroadcast()
       public final void abortBroadcast()
       public final void clearAbortBroadcast()
       public final boolean isOrderedBroadcast()
       public final boolean isInitialStickyBroadcast()

八、代碼實例

1、MainActivity,設置button事件,註冊發送廣播

<pre name="code" class="java">package com.example.broadcastreceiverdemo;

import android.os.Bundle;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements OnClickListener{
	private static final String TAG = "kingfong";
	private BroadcastReceiver myReceiver;
	private static final String ACTION_PRINT = "com.example.print";
	private Button sendButton;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		sendButton = (Button)findViewById(R.id.send);
		sendButton.setOnClickListener(this);		
		myReceiver = new DynamicReceiver();		
	}
	
	public void onClick(View v){
		switch(v.getId()){
		case R.id.send:
			Intent intent = new Intent();
			intent.setAction(ACTION_PRINT);//設置廣播action
			intent.putExtra("msg", "Hello,I am comming");//intent可攜帶數據
			sendBroadcast(intent);//發送普通廣播
			sendOrderedBroadcast(intent, null);//發送有序廣播
		}
	}
	
	@Override
	protected void onStart() {
		// TODO Auto-generated method stub
		super.onStart();
		IntentFilter filter = new IntentFilter();
		filter.addAction(ACTION_PRINT);//添加廣播過濾條件,意思是說可以接受到發送的ACTION_PRINT廣播,可以添加多條action
		filter.setPriority(200);//設置廣播優先級
		registerReceiver(myReceiver, filter);//廣播註冊
	}	

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		unregisterReceiver(myReceiver);//去註冊
	}
	
}

2、StaticReceiver接收靜態註冊的廣播

</pre><pre name="code" class="java">package com.example.broadcastreceiverdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class StaticReceiver extends BroadcastReceiver {
	private static final String TAG = "kingfong";
	private static final String ACTION_PRINT = "com.example.print";

	@Override
	public void onReceive(Context context, Intent intent) {//在onReceive中處理接收的廣播
		// TODO Auto-generated method stub
		String intentAction = intent.getAction();//獲取action	
		if(intentAction.equals(ACTION_PRINT)){//根據接受到的action做不同的處理(此處只有一個action)
			Bundle b = intent.getExtras();//獲取廣播攜帶的數據
			String str = b.getString("msg");
			Log.d(TAG,"StaticReceiver:I have received the boradcast"+str);
		}
	}
}

3、DynamicReceiver接收動態註冊的廣播

</pre><pre name="code" class="java">package com.example.broadcastreceiverdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class DynamicReceiver extends BroadcastReceiver {
	private static final String TAG = "kingfong";
	private static final String ACTION_PRINT = "com.example.print";

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String intentAction = intent.getAction();
		if(intentAction.equals(ACTION_PRINT)){
			Log.d(TAG,"DynamicReceiver have received the boradcast");
			if(isOrderedBroadcast()){//判斷是否爲有序廣播
				abortBroadcast();//終止廣播
			}
		}
	}
}

4、AndroidManifest.xml註冊了StaticReceiver用於接收靜態註冊廣播

<pre name="code" class="java"><?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcastreceiverdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.broadcastreceiverdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 註冊靜態廣播  -->
        <receiver android:name=".StaticReceiver"> 
            <intent-filter android:priority="100"> 
                <action android:name="com.example.print"></action> 
            </intent-filter> 
        </receiver> 
    </application>

</manifest>

點擊send鍵,log打印結果如下

D/kingfong( 9370): DynamicReceiver havereceived the boradcast

D/kingfong( 9370): StaticReceiver:I havereceived the boradcastHello,I am comming

D/kingfong( 9370): DynamicReceiver havereceived the boradcast

我們看到StaticReceiver只接收了一次廣播,這是因爲DynamicReceiver在接收有序廣播後將廣播終止了,所以StaticReceiver就接收不到了。

 

 

 


發佈了35 篇原創文章 · 獲贊 10 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章