http://blog.csdn.net/zhongnan09/article/details/6552632
廣播接收器:
廣播接收者(broadcastreceiver)用于監聽系統事件或應用程式事件,通過調用context.sendbroadcast()、context.sendorderedbroadcast()可以向系統發送廣播意圖,通過廣播一個意圖(intent)可以被多個廣播接收者所接收,進而可以在不用修改原始的應用程式的情況下,讓你對事件作出反應。
其中context.sendbroad()主要是用來廣播無序事件(也被稱為有序廣播 normal broadcast),即所有的接收者在理論上是同時接收到事件,同時執行的,對消息傳遞的效率而言這是比較好的做法。而context.sendorderedbroadcast()方法用來向系統廣播有序事件(ordered broadcast),接收者按照在manifest.xml檔案中設定的接收順序依次接收intent,順序執行的,接收的優先級可以在系統配置檔案中設定(聲明在intent-filter元素的android:priority屬性中,數值越大優先級别越高,其取值範圍為-1000到1000。當然也可以在調用intentfilter對象的setpriority()方法進行設定)。對于有序廣播而言,前面的接收者可以對接收到得廣播意圖(intent)進行處理,并将處理結果放置到廣播意圖中,然後傳遞給下一個接收者,當然前面的接收者有權終止廣播的進一步傳播。如果廣播被前面的接收者終止後,後面的接收器就再也無法接收到廣播了。
廣播接收器(broadcaset)運作的線程:
無論對于有序廣播還是無序廣播,廣播接收器預設都是運作在主線程中的(main線程,即ui線程)。可以通過在程式中使用registerreceiver(receiver, filter, broadcastpermission, scheduler)方法中的最後一個參數指定要運作的廣播接收器的線程。也可以在manifest.xml檔案中設定(intent-filter标簽中設定android:process)。
無序廣播(normal broadcast)
基本步驟:寫一個類繼承broadcastreceiver,并重寫onreceive方法,而後在androidmanifest.xml文中中進行配置,或者直接在代碼中注冊。
下面是一個廣播接收器的demo(用于發送和接收短信):
import android.content.broadcastreceiver;
import android.content.context;
import android.content.intent;
import android.os.bundle;
import android.telephony.smsmessage;
import android.util.log;
public class receivingsmsreceiver extends broadcastreceiver
{
private static final string sms_received ="android.provider.telephony.sms_received";
private static final string tag = "receivingsmsreceiver";
@override
public void onreceive(context
context, intent intent) {
if (intent.getaction().equals(sms_received))
bundle bundle = intent.getextras();
if (bundle != null)
object[] pdus = (object[]) bundle.get("pdus");
smsmessage[] messages = new smsmessage[pdus.length];
for (int i
= 0; i < pdus.length; i++)
messages[i] = smsmessage.createfrompdu((byte[]) pdus[i]);
for (smsmessage message : messages) {
string msg = message.getmessagebody();
log.i(tag, msg);
string to = message.getoriginatingaddress();
log.i(tag, to);
}
}
}
}
}
在androidmanifest.xml檔案中的<application>節點裡對接收到短信的廣播intent進行注冊:
<receiver android:name=". receivingsmsreceiver">
<intent-filter>
<action android:name="android.provider.telephony.sms_received"/>
</intent-filter>
</receiver>
在androidmanifest.xml檔案中添加以下權限:
<uses-permission android:name="android.permission.receive_sms"/><!-- 接收短信權限 -->
該廣播接收器将首先得到本機收到的短信,可以對短信内容進行過濾。
在模拟器中運作該工程。
建立一個新的android工程,建立一個activity用來發送短信:
import android.app.activity;
import android.app.pendingintent;
import android.content.intentfilter;
import android.telephony.smsmanager;
import android.view.view;
import android.widget.button;
import android.widget.edittext;
import android.widget.toast;
public class smssender extends activity
private static final string tag = "smssender";
button send = null;
edittext address = null;
edittext content = null;
private mservicereceiver mreceiver01, mreceiver02;
private static string send_actioin = "sms_send_action";
private static string delivered_action = "sms_delivered_action";
protected void oncreate(bundle
savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.main);
address = (edittext) findviewbyid(r.id.address);
content = (edittext) findviewbyid(r.id.content);
send = (button) findviewbyid(r.id.send);
send.setonclicklistener(new view.onclicklistener()
@override
public void onclick(view
v) {
// todo auto-generated method
stub
string maddress = address.gettext().tostring().trim();
string mcontent = content.gettext().tostring().trim();
if ("".equals(maddress)
|| "".equals(mcontent)) {
toast.maketext(smssender.this, "發送位址為空或内容為空!",
toast.length_long).show();
return;
smsmanager smsmanager = smsmanager.getdefault();
try {
intent send_intent = new intent(send_actioin);
intent deliver_intent = new intent(delivered_action);
pendingintent msend = pendingintent.getbroadcast(
getapplicationcontext(), 0, send_intent, 0);
pendingintent mdeliver = pendingintent.getbroadcast(
getapplicationcontext(), 0, deliver_intent, 0);
smsmanager.sendtextmessage(maddress, null, mcontent, msend,
mdeliver);
} catch (exception e) {
e.printstacktrace();
});
protected void onresume()
// todo auto-generated method stub
intentfilter mfilter01;
mfilter01 = new intentfilter(send_actioin);
mreceiver01 = new mservicereceiver();
registerreceiver(mreceiver01, mfilter01);
mfilter01 = new intentfilter(delivered_action);
mreceiver02 = new mservicereceiver();
registerreceiver(mreceiver02, mfilter01);
super.onresume();
protected void onpause()
unregisterreceiver(mreceiver01);
unregisterreceiver(mreceiver02);
super.onpause();
public class mservicereceiver extends broadcastreceiver
@override
public void onreceive(context
// todo auto-generated method stub
if (intent.getaction().equals(send_actioin))
switch (getresultcode()) {
case activity.result_ok:
break;
case smsmanager.result_error_generic_failure:
case smsmanager.result_error_radio_off:
case smsmanager.result_error_null_pdu:
}
e.getstacktrace();
} else if (intent.getaction().equals(delivered_action))
界面布局:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<textview android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="發送短信" />
<textview android:text="收信人位址:" android:id="@+id/textview1"
android:layout_width="wrap_content" android:layout_height="wrap_content"></textview>
<edittext android:text="" android:layout_width="match_parent"
android:id="@+id/address" android:layout_height="wrap_content"></edittext>
<textview android:text="短信内容:" android:id="@+id/textview2"
android:id="@+id/content" android:layout_height="wrap_content"></edittext>
<button android:text="發送" android:id="@+id/send"
android:layout_width="wrap_content" android:layout_height="wrap_content"></button>
</linearlayout>
在androidmanifest.xml檔案中增加對該activity的配置:
<activity android:name=".smssender" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.main" />
<category android:name="android.intent.category.launcher" />
</intent-filter>
</activity>
<uses-permission android:name="android.permission.send_sms"/><!—發送短信權限 -->
在另一個模拟器中運作該工程。
由于本文的重點内容并不是發送和接收短信,是以,對短信發送和接收的内容并沒有詳細解釋。如果對短信收發内容不熟悉的朋友,可以查閱相關文檔。
有序廣播:
接收器1:
public class broadcasttest2 extends broadcastreceiver
arg0, intent arg1) {
system.out.println("運作線程: " +
thread.currentthread().getid() + " "
+ thread.currentthread().getname());
system.out.println("廣播意圖的動作: " +
arg1.getaction());
bundle bundle = new bundle();
bundle.putstring("test", "zhongnan");
setresultextras(bundle);
接收器2:
public class broadcasttest1 extends broadcastreceiver
bundle bundle = getresultextras(false);
if (bundle == null)
system.out.println("沒有得到上次傳遞的資料");
} else {
system.out.println("測試: " +
bundle.getstring("test"));
主activity,用來發送廣播:
public class mainactivity extends activity
/** called when the activity is first created. */
public void oncreate(bundle
this.sendorderedbroadcast(new intent(
"android.provier.zhongnan.broadcast"), null);
androidmanifest.xml檔案:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zhongnan.bc" android:versioncode="1" android:versionname="1.0">
<uses-sdk android:minsdkversion="8" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".mainactivity" android:label="@string/app_name">
<receiver android:name=".broadcasttest1">
<action android:name="android.provier.zhongnan.broadcast"
android:priority="400" />
</receiver>
<receiver android:name=".broadcasttest2">
android:priority="500" />
</application>
</manifest>
在mainactivity中發送有序廣播context.sendorderedbroadcast(),由于broadcasttest2中設定的接收優先級比較高,是以在broadcasttest2中将首先接收到廣播意圖,可以在broadcasttest2中對該廣播意圖進行處理,可以加入處理後的資料給後面的接收器使用,也可以在該接收器中終止廣播的進一步傳遞。在廣播中加入處理後的資料使用setresultextras(bundle
bundle)方法,關于bundle類,類似于hashmap,不熟悉的朋友可以參考文檔,或者檢視我的另一篇部落格。在後面的接收器中使用getresultextras(boolean
flag)接收前面的接收器存放的資料,其中的boolean參數含義為:true代表如果前面的接收器沒有存放資料,則自動建立一個空的bundle對象,false則表示如果前面的接收器如果沒有存放任何資料則傳回null。
廣播接收器中權限的定義:
在發送廣播時,無論是無序廣播(normal broadcast)還是有序廣播(ordered broadcast)都有類似的方法:sendbroadcast (intent intent, string receiverpermission), sendorderedbroadcast (intent intent, string receiverpermission)。其中第二個參數是設定權限,即接收器必須具有相應的權限才能正常接收到廣播。
下面是在上述例子的基礎上添加自定義權限的例子:
接收器1:
"android.provier.zhongnan.broadcast"), "xzq.zhongnan.test");
代碼中與上述例子最大的差别在于mainactivity中發送廣播的代碼: this.sendorderedbroadcast(new intent(
"android.provier.zhongnan.broadcast"), "xzq.zhongnan.test")增加了自定義的一個權限。
在androidmanifest檔案中配置自定義的權限:
<permission android:protectionlevel="normal" android:name="xzq.zhongnan.test"></permission>
關于如何在工程中自定義權限請查閱相關文檔,或檢視我的另一篇部落格。
相應的,接收器中必須設定接收權限:
<uses-permission android:name="xzq.zhongnan.test"></uses-permission>
這樣,接收器就可以正确接收到廣播了。
另外,上述程式已講到,broadcastreceiver是允許在主線程中的,是以,在onreceive方法中執行的代碼,運作時間不能超過5s,否則将報出程式沒有相應的異常,如果要執行的代碼運作的時間比較長,可以使用service元件。