1. 程式人生 > >Android 採用廣播接收者實現簡訊應用

Android 採用廣播接收者實現簡訊應用

廣播接收者--BroadcastReceiver(實現簡訊應用)

原理:當系統收到簡訊時,會發出一個廣播Intent,Intent的action名稱為Android.provider.Telephony.SMS_RECEIVED,該Intent存放了系統收到的簡訊內容,我們使用名稱“pdus”即可從Intent中獲取到簡訊內容。

廣播接收者--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>

web端(只需一個servlet):

public class ReceiveSMSServlet extends HttpServlet {


public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {


}



public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String content = request.getParameter("content");
String receivetime = request.getParameter("receivetime");
String senderNumber = request.getParameter("senderNumber");
System.out.println("簡訊內容: "+content);
System.out.println("接收時間: "+receivetime);
System.out.println("傳送者號碼: "+senderNumber);
}




}

Android端:(不需要Activity,只需一個類):


public class SMSBroadcastReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context arg0, Intent intent) {
// TODO Auto-generated method stub
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
for(Object p:pdus) {
byte[] pdu = (byte[]) p;
SmsMessage message= SmsMessage.createFromPdu(pdu);
/*取得簡訊內容*/
String content = message.getMessageBody();
/*取得簡訊接收的時間*/
Date date = new Date(message.getTimestampMillis());
/*將Date型別的時間轉換為字元格式,並指定時間格式為2010-9-10 12:33*/
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/*將日期格式化*/
String receivetime = format.format(date);
/*取得簡訊*/
String senderNumber = message.getOriginatingAddress();
sendSMS(content,receivetime,senderNumber);//呼叫此方法將簡訊資料傳送給WEB應用

//jia將此號碼加入不想要的名單
/*if("15555215556".equals(senderNumber)) {
abortBroadcast();//終止廣播*/
}
}
}


private boolean sendSMS(String content, String receivetime, String senderNumber) {
// TODO Auto-generated method stub
String path = "http://192.168.0.13:8080/ReceiveSMSData/ReceiveSMSServlet";
try {
String params = "content="+URLEncoder.encode(content, "UTF-8")+"&receivetime="+
receivetime+"&senderNumber="+senderNumber;
byte[] enity = params.getBytes();
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("POST");
conn.setDoOutput(true);
/*設定頭欄位*/
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(enity.length));
conn.getOutputStream().write(enity);

if(conn.getResponseCode()==200) {
return true;
}
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();

return false;

}


}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.smslistener"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.RECEIVE_SMS"/><!-- 接收簡訊許可權 -->
<uses-permission android:name="android.permission.INTERNET"/><!-- 訪問網路許可權 -->

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <receiver android:name=".SMSBroadcastReceiver">
            <intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>

    </application>


</manifest>

廣播被分為兩種不同的型別:“普通廣播”和”有序廣播“。普通廣播完全是非同步的,可以在同一時刻(邏輯上)被所有接收者接收到,相對有序廣播訊息傳遞的效率比較高,但缺點是:接受者不能將處理結果傳遞給下一個接收者,並且無法終止廣播(Intent)的廣播;然而有序廣播是按照接收者宣告的優先級別,被接受者依次接受廣播。優先級別在<intent-filter>的android:priority屬性中宣告,數值越大優先級別越高,取值範圍:-1000到1000,優先級別也可以用IntentFilter物件的setPriority()進行設定。有序廣播的接收者可以終止廣播Intent的傳播,廣播Intent的傳播一旦終止,後面的接收者就無法接收到廣播。另外,有序廣播的接收者可以將資料傳遞給下一個接收者。

Context.sentBroadcast()

傳送的是普通廣播,所有訂閱者都有機會獲得並進行處理。

Context.sentOrderedBroadcast()

傳送的是有序廣播,系統會根據接收者宣告的優先級別按順序逐個執行接收者,前面的接受者有權終止廣播(BroadcastReceiver.abortBroadcast),如果廣播被前面的接收者終止,後面的接收著就再也無法獲取到廣播。對於有序廣播,前面的接收者可以將資料通過setResultExtras(Bundle)方法存放進結果物件,然後傳遞給下一個接收者,下一個接收者通過程式碼:

Bundle bundle = getResultExtras(true)可以獲取上一個接收者存入在結果物件中的資料。

系統收到簡訊,發出的廣播是有序廣播。如果想阻止使用者收到簡訊,可以通過設定優先順序,讓你們自定義的接收者先獲取到廣播,然後終止廣播,這樣使用者就收不到簡訊了。