android 廣播接收者--BroadcastReceiver (實現短信竊聽)

廣播接收者--BroadcastReceiver

廣播接收者(BroadcastReceiver)用於接收廣播Intent,廣播Intent的發送是通過調用Context.sendBroadcast()、Context.sendOrderedBroadcast()來實現的。通常一個廣播Intent可以被訂閱了此Intent的多個廣播接收者所接收,這個特性跟JMS中的Topic消息接收者類似。要實現一個廣播接收者方法如下:
第一步:繼承BroadcastReceiver,並重寫onReceive()方法。
public class IncomingSMSReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
}
}
第二步:訂閱感興趣的廣播Intent,訂閱方法有兩種:
第一種:使用代碼進行訂閱
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomingSMSReceiver();
registerReceiver(receiver, filter);
第二種:在AndroidManifest.xml文件中的<application>節點裏進行訂閱:
<receiver android:name=".IncomingSMSReceiver">
    <intent-filter>
         <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
    </intent-filter>
</receiver>

使用廣播接收者竊聽短信

如果你想竊聽別人接收到的短信,達到你不可告人的目的,那麼本節內容可以實現你的需求。
當系統收到短信時,會發出一個廣播Intent,Intent的action名稱爲android.provider.Telephony.SMS_RECEIVED,該Intent存放了系統接收到的短信內容,我們使用名稱“pdus”即可從Intent中獲取到短信內容。
public class IncomingSMSReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
@Override public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(SMS_RECEIVED)) {
SmsManager sms = SmsManager.getDefault();
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();
String to = message.getOriginatingAddress();
sms.sendTextMessage(to, null, msg, null, null);
}}}}}
在AndroidManifest.xml文件中的<application>節點裏對接收到短信的廣播Intent進行訂閱:
<receiver android:name=".IncomingSMSReceiver">
<intent-filter><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>
在AndroidManifest.xml文件中添加以下權限:
<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收短信權限 -->
<uses-permission android:name="android.permission.SEND_SMS"/><!-- 發送短信權限 -->

廣播接收者的響應

在Android中,每次廣播消息到來時都會創建BroadcastReceiver實例並執行onReceive() 方法, onReceive() 方法執行完後,BroadcastReceiver 的實例就會被銷燬。當onReceive() 方法在10秒內沒有執行完畢,Android會認爲該程序無響應。所以在BroadcastReceiver裏不能做一些比較耗時的操作,否側會彈出ANR(Application No Response)的對話框。如果需要完成一項比較耗時的工作,應該通過發送Intent給Service,由Service來完成。這裏不能使用子線程來解決,因爲BroadcastReceiver的生命週期很短,子線程可能還沒有結束BroadcastReceiver就先結束了。BroadcastReceiver一旦結束,此時BroadcastReceiver的所在進程很容易在系統需要內存時被優先殺死,因爲它屬於空進程(沒有任何活動組件的進程)。如果它的宿主進程被殺死,那麼正在工作的子線程也會被殺死。所以採用子線程來解決是不可靠的。
public class IncomingSMSReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
            //發送Intent啓動服務,由服務來完成比較耗時的操作
            Intent service = new Intent(context, XxxService.class);
            context.startService(service);
}
}


除了短信到來廣播Intent,Android還有很多廣播Intent,如:開機啓動、電池電量變化、時間已經改變等廣播Intent。
l 接收電池電量變化廣播Intent ,在AndroidManifest.xml文件中的<application>節點裏訂閱此Intent:
<receiver android:name=".IncomingSMSReceiver">
    <intent-filter>
         <action android:name="android.intent.action.BATTERY_CHANGED"/>
    </intent-filter>
</receiver>
l 接收開機啓動廣播Intent,在AndroidManifest.xml文件中的<application>節點裏訂閱此Intent:
<receiver android:name=".IncomingSMSReceiver">
    <intent-filter>
         <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
並且要進行權限聲明:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

廣播被分爲兩種不同的類型:“普通廣播(Normal broadcasts)”和“有序廣播(Ordered broadcasts)”。普通廣播是完全異步的,可以在同一時刻(邏輯上)被所有接收者接收到,消息傳遞的效率比較高,但缺點是:接收者不能將處理結果傳遞給下一個接收者,並且無法終止廣播Intent的傳播;然而有序廣播是按照接收者聲明的優先級別,被接收者依次接收廣播。如:A的級別高於B,B的級別高於C,那麼,廣播先傳給A,再傳給B,最後傳給C 。優先級別聲明在intent-filter元素的android:priority屬性中,數越大優先級別越高,取值範圍:-1000到1000,優先級別也可以調用IntentFilter對象的setPriority()進行設置 。有序廣播的接收者可以終止廣播Intent的傳播,廣播Intent的傳播一旦終止,後面的接收者就無法接收到廣播。另外,有序廣播的接收者可以將數據傳遞給下一個接收者,如:A得到廣播後,可以往它的結果對象中存入數據,當廣播傳給B時,B可以從A的結果對象中得到A存入的數據。
Context.sendBroadcast()
   發送的是普通廣播,所有訂閱者都有機會獲得並進行處理。
Context.sendOrderedBroadcast()
   發送的是有序廣播,系統會根據接收者聲明的優先級別按順序逐個執行接收者,前面的接收者有權終止廣播(BroadcastReceiver.abortBroadcast()),如果廣播被前面的接收者終止,後面的接收者就再也無法獲取到廣播。對於有序廣播,前面的接收者可以將數據通過setResultExtras(Bundle)方法存放進結果對象,然後傳給下一個接收者,下一個接收者通過代碼:Bundle bundle = getResultExtras(true))可以獲取上一個接收者存入在結果對象中的數據。
系統收到短信,發出的廣播屬於有序廣播。如果想阻止用戶收到短信,可以通過設置優先級,讓你們自定義的接收者先獲取到廣播,然後終止廣播,這樣用戶就接收不到短信了。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章