android廣播和短信廣播詳解----使用廣播接收者竊聽短信

當系統收到短信時,會發出一個action名稱爲android.provier.Telephony.SMS_RECEIVED的廣播Intent,該Intent存放了接收到的短信內容,使用名稱 「pdus」便可從Intent中獲取短信內容。 java

pdus是一個object類型的數組,每個object都是一個byte[]字節數組,每一項爲一條短信。 android

Object[] pduses= (Object[])intent.getExtras().get("pdus"); 數組

for(Objectpdus: pduses){ app

byte[] pdusmessage = (byte[])pdus; 異步

SmsMessage sms = SmsMessage.createFromPdu(pdusmessage); ide

String mobile = sms.getOriginatingAddress();//發送短信的手機號碼 spa

String content = sms.getMessageBody(); //短信內容 .net

Date date = new Date(sms.getTimestampMillis()); 線程

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); code

String time = format.format(date); //獲得發送時間

}

廣播接收者(BroadcastReceiver)用於接收廣播Intent,廣播Intent的發送是經過調用Context.sendBroadcast()、Context.sendOrdeedBroadcast()、context.sendStickyBroadcast()來實現的,一般一個廣播Intent能夠被訂閱了此Intent的多個廣播接收者所接收,這個特性跟JMS中的Topic消息接收者相似,要實現一個廣播接收者方法以下:

第一步,繼承BroadcastReceiver,並重寫onReceive()方法

public class SMSBroadcastReceiver extends BroadcastReceiver{

@Override

public void onReceive(Context context, Intent intent) {

}

}

onReceive的生命週期爲10秒,因此裏面的操做不能超過10秒

第二步,訂閱感興趣的廣播Intent,訂閱方法有兩種:

第一種:使用代碼進行訂閱

SMSBroadcastReceiver receiver = new SMSBroadcastReceiver();

IntentFilter filter = new IntentFilter();

filter.addAction("android.provider.Telephony.SMS_RECEIVED");

context.registerReceiver(receiver,filter);

第二種:在AndroidManifest.xml文件中的<application>節點裏進行訂閱

<receiver android:name=".SMSBroadcastReceiver">

<intent-filter>

<action android:name="android.provider.Telephony.SMS_RECEIVED"/>

</intent-filter>

</receiver>

第三步,增長接收短信權限

<uses-permission android:name="android.permission.RECEIVE_SMS">

</uses-permission>

廣播被分爲兩種不一樣的類型,「普通廣播(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

接收電池電量變化廣播:

<action android:name="android.intent.action.BATTERY_CHANGED"/>

接收開機啓動廣播

<action android:name="android.intent.action.BOOT_COMPLETED"/>

並在進行權限聲明

<uses-permission android:name=」android.permission.RECEIVE_BOOT_COMPLETED」/>

在Android中,程序的響應(Responsive)被活動管理器(Activity Manager)和窗口管理器(Window Manager)這兩個系統服務所監視,當BroadcastReceiver在10秒內沒有執行完畢,Android會認爲該程序無響應,因此在BroadcastReceiver裏不能作一些比較耗時的操做,不然會彈出ANR(Application No Response)的對話框。若是須要完成一項比較耗時的工做,應該經過發送Intent給Service,由Service來完成,而不是使用子線程的方法來解決,由於BroadcastReceiver的生命週期很短(在onReceive()執行後BroadcastReceiver的實例就會被銷燬),子線程可能尚未結束BroadcastReceiver就先結束了。若是BroadcastReceiver結束了,它的宿主進程還在運行,那麼子線程還會繼續執行。但宿主進程此時很容易在系統須要內在時被優先殺死。由於它屬於空進程(沒有任何活動組件的進程)。

每次廣播消息到來時,都會建立BroadcastReceiver實例來執行onReceive()方法。


事例:

  1. package com.king.sms;
  2. import java.text.SimpleDateFormat;
  3. import java.util.Date;
  4. import android.content.BroadcastReceiver;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.telephony.SmsMessage;
  8. public class SMSBroadcastReceiver extends BroadcastReceiver{
  9. @Override
  10. public void onReceive(Context context, Intent intent) {
  11. Object[] pduses= (Object[])intent.getExtras().get("pdus");
  12. for(Object pdus: pduses){
  13. byte[] pdusmessage = (byte[])pdus;
  14. SmsMessage sms = SmsMessage.createFromPdu(pdusmessage);
  15. String mobile = sms.getOriginatingAddress();//發送短信的手機號碼
  16. String content = sms.getMessageBody(); //短信內容
  17. Date date = new Date(sms.getTimestampMillis());
  18. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  19. String time = format.format(date); //獲得發送時間
  20. }
  21. }
  22. }
package com.king.sms;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;



public class SMSBroadcastReceiver extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		Object[] pduses= (Object[])intent.getExtras().get("pdus");
		for(Object pdus: pduses){
			byte[] pdusmessage = (byte[])pdus;
			SmsMessage sms = SmsMessage.createFromPdu(pdusmessage);
			String mobile = sms.getOriginatingAddress();//發送短信的手機號碼
			String content = sms.getMessageBody(); //短信內容
			Date date = new Date(sms.getTimestampMillis());
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String time = format.format(date);  //獲得發送時間
			
		}
	}

}


// AndroidManifest.xml


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.king.sms"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <uses-sdk android:minSdkVersion="8" />
  7. <SPAN style="COLOR: #ff0000"><uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission></SPAN>
  8. <application android:icon="@drawable/icon" android:label="@string/app_name">
  9. <receiver android:name=".SMSBroadcastReceiver">
  10. <intent-filter>
  11. <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
  12. </intent-filter>
  13. </receiver>
  14. </application>
  15. </manifest>
相關文章
相關標籤/搜索