廣播介紹
廣播被分為兩種不同的類型,“普通廣播(Normal broadcasts)”和“有序廣播(Ordered broadcasts)”。普通廣播是完全非同步,可以在同一時刻(邏輯上)被所有接收者接收到,訊息傳遞的效率比較高,但缺點是:接收者不能將處理結果傳遞給下一個接收者,並且無法終止廣播Intent的傳播;然而有序廣播是按照接收者聲明的優先順序別(聲明在intent-filter元素的android:priority屬性中,資料大優先順序別越高,取值範圍:-1000到1000也可以調用IntentFilter對象的setPriority()進行設定),被接收者依次接收廣播。如:A的層級高於B,B的層級高於C,那麼,廣播先傳給A,再傳給B,最後傳給C。A得到廣播後,可以往廣播裡存入資料,當廣播傳給B時,B可以從廣播中得到A存入的資料。
Context.sendBroadcast()發送的是普通廣播,所有訂閱者都有機會獲得並進行處理。
Context.sendOrderedBroadcast()發送的是有序廣播,系統會根據接收者聲明的優先順序別按順序逐個執行接收者,前面的接收者有權終止廣播(BroadcastReceiver.abortBroadcast() ),如果廣播被前面的接收者終止,後面的接收者就再也無法擷取到廣播。對於有序廣播,前面的接收者可以將處理結果存進廣播Intent,然後傳給下一個接收者。
sendStickyBroadcast() 意思只要是如果發送廣播之後才執行registerReceiver(BroadcastReceiver,IntentFilter).這個方法依然可以接受到。換句話說,在ReceiverActivity裡是通過代碼來註冊Recevier而不是在Manifest裡面註冊的。sendStickyBroadcast發出的最後一個Intent會被保留,當下次Recevier處於活躍的時候,又會接受到它。需要加BROADCAST_STICKY許可權,否則會拋SecurityException
安卓手機中的簡訊適合用廣播來監測,需要註冊廣播。此外還可以用來過濾簡訊,可根據內容和電話號碼來過濾簡訊
把主要代碼傳上來存檔,方便以後忘記時上來取
首先:訂閱感興趣的廣播 Intent ,訂閱者法有兩種:
第一種:使用代碼進行訂閱
Java代碼
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerClass receiver = new registerClass();
registerReceiver(receiver, filter);
第二種:在 AndroidManifest.xml 檔案中的 <application> 節點裡進行訂閱 :
Html代碼
<receiver android:name=".IncomingSMSReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
我用第二種
package com.lan.www;
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 SmsReciver extends BroadcastReceiver {
private final String MagicString = "lan";
//onReceive的生命週期為10秒,所以裡面的操作不能超過10秒
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
if((intent.getAction()!=null)&&(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED"))) //這個action是系統簡訊專屬
{
StringBuffer sb = new StringBuffer();
Bundle bundle = intent.getExtras(); //如果有簡訊過來,Android系統其實就是用一個Bundle來存簡訊的
if(bundle!=null)
{
//簡訊頭是一個pdus
Object[] pdus = (Object[]) bundle.get("pdus"); //一條簡訊(中文是70個字元左右,英文是140左右,都包括了標點符號),可能不只一條,但每一條都有pdus
SmsMessage[] msgs = new SmsMessage[pdus.length]; //有多少條簡訊就有多少條簡訊
for (int i = 0; i < msgs.length; i++) {
//簡訊內容
msgs[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
//得到電話號碼,一般取第一條簡訊的電話號碼就可以了,要想嚴謹就應該每條簡訊都應該進行取電話號碼,因為這時可能其他人也在發簡訊過來,
String telnumber = msgs[0].getOriginatingAddress();
for (SmsMessage smsMessage : msgs) {
sb.append(smsMessage.getMessageBody());
}
if(smgs.length() >0){
Date date = new Date(smgs[0].getTimestampMillis());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date); //得到發送時間
}
Log.i("lan", "SMS telnumber="+telnumber+" info="+sb.toString());
//過濾簡訊
if(sb.indexOf(MagicString)!=-1)
{
//有過濾的簡訊內容在裡面就清除
sb = null;
//阻止廣播播出
this.abortBroadcast();
}
if(sb!=null&&sb.length()!=0)
{
Intent it = new Intent(context, SMS1Activity.class).putExtra("info", sb.toString()).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(it);//我這裡傳給另一個介面了
}
}
//這個方法有時不好用,不好用就加在這裡試試
// this.abortBroadcast();
}
}
}
在AndroidManifest.xml檔案中進行配置:
<receiver android:name="SmsReciver">
<intent-filter android:priority="1000"> //許可權越高,才能確保執行,目前最高是int 類型,
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收簡訊許可權 -->
<uses-permission android:name="android.permission.SEND_SMS"/><!-- 傳送簡訊許可權 -->
另傳送簡訊
SmsManager sms = SmsManager.getDefault(); //得到系統的簡訊管理器
ArrayList<String> texts = sms.divideMessage(text.toString()); //分成若干條簡訊
PendingIntent pi = PendingIntent.getBroadcast( //不一定發生時,用此類
SendNotify.this,
0,
new Intent(),
0);
for (String string : texts) {
for (int i = 0; i < phones.length; i++) {
sms.sendTextMessage(phones[i], null, string, pi, null); //傳送簡訊
}
}
如果想在播出的電話加上特殊提示或者預設加上區號,12593優惠號等,那麼就需要監聽撥出的電話,並進行處理:
向撥出打電話時系統會發出一個有序廣播,雖然該廣播最終會被拔號器裡的廣播接收者所接收並實現電話拔打,但我們可以在廣播傳遞給拔號廣播接收者之前先得到該廣播,然後清除傳遞給拔號廣播接收者的電話號碼,在拔號廣播接收者接收到該廣播時,由於電話號碼為null,因此取消電話拔打。
public class OutgoingCallReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
setResultData(null); //清除電話,廣播被傳給系統的接收者後,因為電話為null,取消電話拔打
// 同樣如果你想修改外拔的電話號碼,可以這樣做
// String phone = getResultData();//得到外拔電話
// setResultData(“12593”+ phone);//在電話前面加上12593
}
}
接收外拔電話廣播Intent,在AndroidManifest.xml檔案中的<application>節點裡訂閱此Intent:
<receiver android:name=".OutgoingCallReceiver">
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
並且要進行許可權聲明:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>