關于短信黑名單 BroadCast
看到Android中有關Broadcast Receiver組件方面的東西,廣播被分為兩種不同的類型:“普通廣播(Normal broadcasts)”和“有序廣播(Ordered broadcasts)”。普通廣播是完全異步的,可以在同一時刻(邏輯上)被所有接收者接收到,消息傳遞的效率比較高,但缺點是:接收者不能將處理結果傳遞給下一個接收者,并且無法終止廣播Intent的傳播;然而有序廣播是按照接收者聲明的優(yōu)先級別,被接收者依次接收廣播。如:A的級別高于B,B的級別高于C,那么,廣播先傳給A,再傳給B,***傳給C 。優(yōu)先級別聲明在intent-filter元素的android:priority屬性中,數越大優(yōu)先級別越高,取值范圍:-1000到1000,優(yōu)先級別也可以調用IntentFilter對象的setPriority()進行設置 。有序廣播的接收者可以終止廣播Intent的傳播,廣播Intent的傳播一旦終止,后面的接收者就無法接收到廣播。另外,有序廣播的接收者可以將數據傳遞給下一個接收者,如:A得到廣播后,可以往它的結果對象中存入數據,當廣播傳給B時,B可以從A的結果對象中得到A存入的數據。
Context.sendBroadcast() 發(fā)送的是普通廣播,所有訂閱者都有機會獲得并進行處理。
Context.sendOrderedBroadcast() 發(fā)送的是有序廣播,系統(tǒng)會根據接收者聲明的優(yōu)先級別按順序逐個執(zhí)行接收者,前面的接收者有權終止廣播(BroadcastReceiver.abortBroadcast()),如果廣播被前面的接收者終止,后面的接收者就再也無法獲取到廣播。對于有序廣播,前面的接收者可以將數據通過setResultExtras(Bundle)方法存放進結果對象,然后傳給下一個接收者,下一個接收者通過代碼:Bundle bundle = getResultExtras(true))可以獲取上一個接收者存入在結果對象中的數據。
系統(tǒng)收到短信,發(fā)出的廣播屬于有序廣播。如果想阻止用戶收到短信,可以通過設置優(yōu)先級,讓你們自定義的接收者先獲取到廣播,然后終止廣播,這樣用戶就接收不到短信了。
因此,可以用廣播來實現一個黑名單的功能:
- package com.broadcastreceiver;
- 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 FirstBroadCastReceiver extends BroadcastReceiver{
- @Override
- public void onReceive(Context context, Intent intent) {
- // TODO Auto-generated method stub
- if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
- Bundle bundle = intent.getExtras();
- StringBuilder phoneNum = new StringBuilder();
- //通過pdus可以獲得接收到的所有信息
- Object[] objArray = (Object[]) bundle.get("pdus");
- //構建短信對象array,并依據收到的對象長度來創(chuàng)建array的大小
- SmsMessage[] messages = new SmsMessage[objArray.length];
- for (int i = 0; i < objArray.length; i++)
- {
- messages[i] = SmsMessage
- .createFromPdu((byte[]) objArray[i]);
- }
- //將送來的短信合并自定義信息于StringBuilder中
- for (SmsMessage currentMessage : messages)
- {
- //獲得發(fā)送短信的電話號碼
- phoneNum.append(currentMessage.getDisplayOriginatingAddress());
- }
- //這里可以添加數據庫查詢語句,用來查詢發(fā)送短信的號碼是否在黑名單中
- //注意,在onReceive()方法最長運行時間是10秒,如果超過10秒Android會認為該程序無響應
- //所以在BroadcastReceiver里不能做一些比較耗時的操作,否側會彈出ANR(Application No Response)的對話框
- //如果需要完成一項比較耗時的工作,應該通過發(fā)送Intent給Service,由Service來完成
- //這里不能使用子線程來解決,因為 BroadcastReceiver的生命周期很短,子線程可能還沒有結束BroadcastReceiver就先結束了
- //BroadcastReceiver一旦結束,此時BroadcastReceiver的所在進程很容易在系統(tǒng)需要內存時被優(yōu)先殺死,
- //因為它屬于空進程(沒有任何活動組件的進程)。如果它的宿主進程被殺死,那么正在工作的子線程也會被殺死。
- //所以采用子線程來解決是不可靠的。
- if(phoneNum.toString().equals("254")){
- //如果在黑名單中,就終止廣播,這樣,系統(tǒng)就不會有任何提示,用戶也就收不到短信了
- abortBroadcast();
- Log.e("msg", "sucess!!");
- }else
- Log.e("msg","fail!");
- }
- }
- }
既然要獲取短信號碼,就涉及到讀短信的權限,同時intent-filter元素的android:priority屬性表示優(yōu)先級,越大說明優(yōu)先級越高。
下面是AndroidManifest.xml代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.broadcastreceiver"
- android:versionCode="1"
- android:versionName="1.0">
- <uses-permission android:name="android.permission.READ_SMS"></uses-permission>
- <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".MainBroadCastReceiver"
- 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=".FirstBroadCastReceiver">
- <intent-filter android:priority="1000">
- <action android:name="android.provider.Telephony.SMS_RECEIVED"></action>
- </intent-filter>
- </receiver>
- </application>
- </manifest
【編輯推薦】