android短信和廣播機制

廣播介紹

廣播被分為兩種不同的類型,“普通廣播(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.pideMessage(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"/>

 

 

You May Also Like