Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之旅十七 android中的廣播使用

Android之旅十七 android中的廣播使用

編輯:關於Android編程

廣播是一種廣泛運用在應用程序之間傳輸信息的機制,android中的廣播用於監聽系統事件或應用程序事件!android中的廣播包括普通廣播、有序廣播以及異步廣播(粘性廣播)!

廣播又有常駐型廣播和非常駐型廣播,常駐型廣播是在xml中進行注冊的,當應用程序關閉後,如果有對應的廣播發送過來,廣播接收器還是能夠被激活;非常駐型廣播是在代碼中進行注冊的,當應用程序關閉,廣播也就取消了,我們可以在Activity中的onCreate或者onResume方法中注冊廣播,然後在onDestory或者onPause方法中取消注冊廣播;

注意:如果是非常駐型廣播,應用程序關閉後,必須取消注冊廣播,否則會拋出異常!!

普通廣播的發送

普通廣播的發送使用方式:

sendBroadcast(Intent intent):intent表示意圖,所有匹配該廣播的意圖都能收到該廣播信息

sendBroadcast(intent, String receiverPermission);intent與上面一樣,receiverPermission表示權限,與之匹配權限的廣播才能接收到相應的廣播,如果為null,表示不經許可的要求!

一、使用sendBroadcast(Intent intent)發送廣播

1)通過代碼注冊非常駐型廣播:

	
	//定義兩個廣播接收者
	BroadcastReceiver receiver1=new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			System.out.println("receiver1 started!");
		}
	};
	BroadcastReceiver receiver2=new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			System.out.println("receiver2 started!");
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		//注冊廣播
		IntentFilter filter=new IntentFilter();
		filter.addAction("com.xin.action.broadcast");
		registerReceiver(receiver1, filter);
		registerReceiver(receiver2, filter);
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		//取消注冊廣播
		unregisterReceiver(receiver1);
		unregisterReceiver(receiver2);
	}
代碼注冊屬於非常駐型廣播,我們需在Activity相應的生命周期中取消注冊廣播:unregisterReceiver

2)通過xml文件注冊常駐型廣播,此時的MyBroadcast1、MyBroadcast2為兩個廣播類:

public class MyBroadcast1 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		System.out.println("MyBroadcast1 started!");
	}
}
public class MyBroadcast2 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		System.out.println("MyBroadcast2 started!");
	}
}

在AndroidManifest.xml中的application中添加:

        
            
                
            
        
        
            
                
            
        
代碼中的IntentFilter和xml文件中的intent-filter是一樣的,都是Intent意圖,表示Intent(String actionName)發送出去的廣播能被哪些廣播接收者所接收!

3)廣播的發送:與之匹配的intent意圖的廣播將被激活

			Intent intent=new Intent("com.xin.action.broadcast");
			sendBroadcast(intent);
輸出結果為:MyBroadcast1 started,MyBroadcast2 started!!

二、使用sendBroadcast(intent, String receiverPermission)發送廣播

第二個參數的介紹如上面所示,指的是一個權限,我們需在AndroidManifest.xml中聲明一個權限:

裡面還有很多的屬性可供我們選擇,大家可以去自己去了解一下;

然後我們的發送廣播方和接收廣播方都需要該權限定義:

發送廣播方使用該權限:

通過方法發送廣播:sendBroadcast(intent,"com.xin.permission");其中第二個參數表示我們定義的權限name

接收方聲明廣播權限:

        
            
                
            
        
這樣,使用帶權限的廣播就定義好了,我們在發送方和接收方都需要給權限進行定義,否則消息發送不過去!

注意,通過sendBroadcast(intent,"com.xin.permission");發送的廣播,並不一定需要在receiver中添加android:permission才能接收到,測試發現,沒有添加這個也能接收到:

        
            
                
            
        

有序廣播的發送

顧名思義,有序廣播就是廣播的發送是按照順序進行的,它根據優先級別的定義android:priority的高低來進行有序發送,一個接受完發給下一個接收,優先級越高,表示它接收到的廣播級別高,android:priority的范圍一般是在-1000到1000之間;
有序廣播和普通廣播之間的區別:

有序廣播和無序廣播的區別:我們發送完無序廣播之後,我們不知道誰先接收誰後接收,更不要說當這個接收了之後不要再發給另外的了。而有序廣播就可以做到這一點,它通過設置優先級可以決定廣播接受者的順序。

有序廣播的發送方式:

sendOrderedBroadcast(intent, receiverPermission);

sendOrderedBroadcast(intent, receiverPermission, resultReceiver,

scheduler, initialCode, initialData, initialExtras)

意圖,廣播,所有匹配的這一意圖將接收機接收廣播。

receiverPermission 這是權限,一個接收器必須持以接收您的廣播。如果為 null ,不經許可的要求。
resultReceiver 您自己 BroadcastReceiver 來當作最後的廣播接收器。
調度自定義處理程序,用以安排 resultReceiver 回調 ; 如果為 null 將語境中的主線程舉行。
initialCode 一種結果代碼的初始值。通常為 Activity.RESULT_OK 。這個值是 -1 ;為其他 int 型 也可以,如 0,1,2;
initialData 一種結果數據的初始值。通常情況下為空 , 是 String 類型 ;
initialExtras 一種結果額外的初始值。通常情況下為空 , 是 Bundle;

有序廣播需注意方面:

1, 該廣播的級別有級別之分,級別數值是在 -1000 到 1000 之間 , 值越大 , 優先級越高;
2, 同級別接收是先後是隨機的,再到級別低的收到廣播;
3, 同級別接收是先後是隨機的,如果先接收到的把廣播截斷了,同級別的例外的接收者是無法收到該廣播的,截斷廣播的方式:abortBroadcast() ;
4 ,能截斷廣播的繼續傳播,高級別的廣播收到該廣播後,可以決定把該鐘廣播是否截斷掉。
5 ,實驗現象,在這個方法發來的廣播中,代碼注冊方式中,收到廣播先後次序為:注明優先級的、代碼
代碼演示:

下面給大家演示一下發送有序廣播,並且通過Intent在廣播之間傳遞數據,因為關於權限那塊上面已經說了,所以在有序廣播這裡就不再描述了,通過sendOrderedBroadcast(intent, receiverPermission);方法發送有序廣播,第二個參數就設置為null了:這裡我們通過xml注冊廣播

1)定義廣播

public class MyBroadcast2 extends BroadcastReceiver{
	@Override
	public void onReceive(Context context, Intent intent) {
		System.out.println("MyBroadcast2 started!");
		//接收sendOrderedBroadcast傳遞過來的Intent中的參數
		System.out.println(intent.getStringExtra("test"));
		//添加另一個參數
		Bundle bundle=new Bundle();
		bundle.putString("test2", "我是從MyBroadcast2中存儲的數據");
		//將其封裝為Bundle對象,讓下一個廣播接收
		setResultExtras(bundle);
	}
}
public class MyBroadcast1 extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		System.out.println("MyBroadcast started!");
		//接收sendOrderedBroadcast傳遞過來的Intent中的參數
		System.out.println(intent.getStringExtra("test"));
		//得到從上一個廣播中攜帶過來的另一個數據
		Bundle bundle=getResultExtras(true);
		System.out.println(bundle.getString("test2"));
	}
}
2)在AndroidManifest.xml中聲明廣播:

        
            
                
            
        
        
            
                
            
上面聲明的廣播中,MyBroadcast2比Mybroadcast1的優先級高!

3)發送有序廣播

			Intent intent=new Intent("com.xin.action.broadcast");
			intent.putExtra("test", "我是sendOrderedBroadcast發送過來的數據!");
			sendOrderedBroadcast(intent,null);
測試結果:

\

因為Mybroadcast2的優先級(1000)比Mybroadcast1(900)的高,所以廣播通過sendOrderedBroadcast發送出去後,首先被Mybroadcast2接收,然後再Mybroadcast2中通過setResultExtras設置了另一些參數一起傳到Mybroadcast1,然後Mybroadcast1接收到廣播,也通過getResultExtras(true)接收從Mybroadcast2中攜帶過來的數據,所以出現上面的結果!<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+vq2y4srUt6LP1qOs1NrKudPDc2VuZEJyb2FkY2FzdMqxuvKjrMjnufvU2kJyb2FkY2FzdFJlY2VpdmVy1tDKudPDc2V0UmVzdWx0RXh0cmFzu/LV32dldFJlc3VsdEV4dHJhc6Oss8zQ8rvhsai07aOs0vLOqsv8t6LLzbXEsrvKx9PQ0PK547KlITwvcD4KPHA+16LS4qO6PGJyPgoxoaLI57n7ysfU2rT6wuvW0NeisuG1xKOsztLDx7/J0tTNqLn9ZmlsdGVyLnNldFByaW9yaXR5KDEwMDApO8C0yejWw8bk08XPyLy2o6zV4sDvvs2yu77ZwP3LtcP3wcshPC9wPgo8cD4yoaLI57n7ztLDx8/ryMPT0NDyueOypdTa0ru49kJyb2FkY2FzdFJlY2VpdmVy1tC908rVuvOjrLK71NnN+c/C0ru49rnjsqXWtNDQo6y/ydLUtffTw8bkYWJvcnRCcm9hZGNhc3QoKTvW0LbPueOypbXEt6LLzaOsuvPD5rXEueOypb2rvdPK1bK7tb0hPC9wPgo8cD48YnI+CjwvcD4KPHA+1bPQ1LnjsqUo0uyyvbnjsqUptcS3osvNPC9wPgo8cD7U2s34yc/XqNK1w/uzxrj3srvSu9H5o6zT0MjLvbLL/MrH1bPQ1LnjsqWjrNKy09DIy8u1y/zKx9Lssr2547Klo6zPyLK7zNbC28v8tcTXqNK1w/u0yrXEzsrM4sHLo6zPyMC0yMPO0sPHwcu94sv809DKssO008Msy/zT68bVzai547KltcTH+LHwvs3Kx7WxueOypcihz/vXorLhuvOjrMi7uvO3osvN0ru49tWz0NS547Klo6y547Kl1tjQwteisuG688jUyLvE3L3TytW1vdWz0NS547Klt6LLzbn9wLS1xM/7z6IhPC9wPgo8cD7G1c2oueOypdPr1bPQ1LnjsqXX7rTztcTH+LHwo7o8L3A+CjxwPs7Sw8fWqrXAo6zO0sPHz8jXorLhueOypaOsyLu687eiy82547Klo6zEx8O0zt7C28rHyrLDtLnjsqW2vMTcsbu908rVtb2jrMTHw7TI57n7ztLDx8/It6LLzbnjsqWjrLrz16Ky4bnjsqXE2KO6PC9wPgo8cD7G1c2oueOypaO6zrTXorLhueOypS0tPreiy82547KlLS0+16Ky4bnjsqUtLT6908rVsru1vbnjsqU8L3A+CjxwPtWz0NS547Klo7rOtNeisuG547KlLS0+t6LLzbnjsqUtLT7XorLhueOypS0tPsTcvdPK1bW9ueOypaOssqLH0sTcvdPK1bW9tuC0zreiy82547KltcTX7rrz0rvM9bnjsqXQxc+iPC9wPgo8cD7V4r7NysfBvdXf1q685LXEx/ix8KOsz8LD5s7Sw8fNqLn9tPrC67XEt73Kvbj4tPO80r7Z0ru49sD919OjrM7Sw8e1xLnjsqXKx9TatPrC69bQ16Ky4bXEt8ezo9ek0M2547KlOjwvcD4KPHA+0rPD5ta7sPy6rMj9uPay4srUsLTFpaO6PC9wPgo8cD48aW1nIHNyYz0="/uploadfile/Collfiles/20140823/2014082309213077.jpg" alt="\">

我們在注冊廣播的Activity中注冊廣播:RegisterActivity,在其生命周期的onPause方法中取消注冊廣播unregisterBr

	 
	//定義廣播
	BroadcastReceiver receiver=new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action=intent.getAction();
			int count=intent.getIntExtra("count", 0);
			System.out.println("action="+action+",count="+count);
		}
	};
	
	//注冊廣播
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.register);
		IntentFilter filter=new IntentFilter();
		//添加廣播Action
		filter.addAction("com.xin.action.broadcast");
		filter.addAction("com.xin.action.sticky.broadcast");
		registerReceiver(receiver, filter);
	}

	//取消注冊廣播
	@Override
	protected void onPause() {
		super.onPause();
		System.out.println("RegisterBroadActivity onPause!");
		unregisterReceiver(receiver);
	}
在MainActivity中發送廣播:

    //定義一個變量,來統計點擊發送粘性廣播的次數,然後測試粘性廣播的接收是不是最後一條廣播
    private int count;
	@Override
	public void onClick(View v) {
		Intent intent=null;
		switch(v.getId()){
		case R.id.btn_send1://發出廣播sendBroadcast
			intent=new Intent("com.xin.action.broadcast");
			sendBroadcast(intent);
			break;
		case R.id.btn_send2://發出粘性廣播sendStickyBroadcast
			count++;
			intent=new Intent("com.xin.action.sticky.broadcast");
			intent.putExtra("count", count);
			sendStickyBroadcast(intent);
			break;
		case R.id.register://啟動注冊廣播頁面
			intent=new Intent(MainActivity.this,RegisterBroadActivity.class);
			startActivity(intent);
			break;
		}
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		count=0;
		System.out.println("MainActivity onResume!");
	}
注意,發送粘性廣播,我們需要在AndroidManifest.xml中添加能夠發送粘性廣播的權限,否則會報錯:

測試及結論:

當我們點擊發送sendBroadcast按鈕3次--點擊注冊按鈕,控制台無輸出結果

當我們點擊發送sendStickyBroadcast按鈕4次--點擊注冊按鈕,控制台輸出結果:action=com.xin.action.sticky.broadcast,count=4

這就是普通廣播和粘性廣播的區別
sendBroadcast發送出去的廣播,如果沒有廣播進行注冊,那麼該廣告也就接收不到了,當重新注冊廣播後,也接收不到
sendStickyBroadcast發送出去的廣播,如果沒有廣播進行注冊,那麼該廣告此時也就接收不到了,當重新注冊廣播後,會接收到,並且會接受sendStickyBroadcast發出去的最後一條廣播,所以上面的輸出結果中點擊發送stickybroadcast 4次,count變為4,那麼當重新注冊廣播後,控制台會輸出結果count=4;
sendStickyBroadcast發出的最後一個Intent會被保留,下次當Recevier處於活躍的 時候,又會接受到它。

當我們需要移除掉粘性廣播的時候,調用方法:removeStickyBroadcast(intent);即可清除掉粘性廣播

還有一個發送廣播的方式:sendStickyOrderedBroadcast (),測試在這個方法發來的廣播,代碼注冊方式中,收到廣播先後次序為:注明優先級的、代碼注冊的、沒有優先級的;如果都沒有優先級,代碼注冊收到為最先。

上面給大家介紹了廣播操作中的幾種方式:

發送廣播:sendBroadcast(Intent intent)、sendBroadcast(Intent intent,String receiverPermission);

發送有序廣播:sendOrderedBroadcast(Intent intent,String receiverPermission);

發送粘性廣播:sendStickyBroadcast(Intent intent);

還有一種方式:sendStickyOrderedBroadcast();(未研究,不知道用的多不多)


在Android的廣播操作中,我們還應該知道:

1、無論對於有序廣播還是無序廣播,廣播接收器默認都是運行在主線程中的(main線程,即UI線程)。可以通過在程序中使用registerReceiver(receiver, filter, broadcastPermission, scheduler)方法中的最後一個參數指定要運行的廣播接收器的線程。也可以在Manifest.xml文件中設置(Intent-filter標簽中設置android:process)。

2、我們在代碼中注冊廣播registerBroadcast十次,那麼廣播發送過來的時候會接收十次,注銷廣播只需一次!

3、每次廣播到來時 , 會重新創建 BroadcastReceiver 對象 , 並且調用 onReceive() 方法 , 執行完以後 , 該對象即被銷毀 . 當 onReceive() 方法在 10 秒內沒有執行完畢, Android 會認為該程序無響應 . 所以在BroadcastReceiver 裡不能做一些比較耗時的操作 , 否側會彈出 ANR(Application NoResponse) 的對話框,如果需要完成一項比較耗時的工作 , 應該通過發送 Intent 給 Service, 由 Service 來完成 . 這裡不能使用子線程來解決 , 因為 BroadcastReceiver 的生命周期很短 , 子線程可能還沒有結束BroadcastReceiver 就先結束了 .BroadcastReceiver 一旦結束 , 此時 BroadcastReceiver 的所在進程很容易在系統需要內存時被優先殺死 , 因為它屬於空進程 ( 沒有任何活動組件的進程 ). 如果它的宿主進程被殺死 , 那麼正在工作的子線程也會被殺死 . 所以采用子線程來解決是不可靠的 .

4、耗時的操作應該通過廣播啟動service來執行操作

	BroadcastReceiver receiver=new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			Intent intent=new Intent(context,TestService.class);
			startService(intent);
		}
	};

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved