通常,在系統的短信發生變化,比如有短信來了,或者要發短信的時候,系統會產生一個廣播,然後廣播出去,今天主要探討一下如何監控是否有新的短信接收到,然後如何處理。
網上有很多如下的處理:
當系統收到短信時,會發出一個action名稱爲android.provier.Telephony.SMS_RECEIVED的廣播Intent,該Intent存放了接收到的短信內容,使用名稱 “pdus”即可從Intent中獲取短信內容。
但是,經過實驗,該方法理論上雖然可以,但是實際操作非常的難。爲何?
原因在於,短信到來的廣播屬於一個有序廣播,所謂有序廣播,指的是系統在發送該廣播時,是使用sendOrderedBroadcast() 進行發送,處理方式是,優先級高的先進行處理,優先級低的後進行處理,同時,優先級高的可以中斷掉該廣播,不讓其向下傳播。所以,一般在安裝有安全類軟件的手機,安全類軟件會以最高優先級獲得該廣播,在其處理後會中斷該廣播,導致我們的程序不能夠對短信的變化做出響應。所以,上面的方法不可行,那麼怎麼樣纔可以穩定運行?這就是我今天要討論的問題。
Android爲了管理短信彩信等,都是建立在數據庫的基礎上,發送箱和接受箱都有對應的數據庫,當接受到短信時,會將接受的短信寫入數據庫,當要發送短信時,只需要將要發送的短信寫入發送數據庫就可以。同時,系統爲用戶暴漏了一個接口,就是,應用程序可以通過觀察者ContentObserver,去監聽短信數據的變化:
//註冊一個observer進行觀察
getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SmsRecevier(new Handler())); //當觀察的對象變化是調用SmsReceiver進行處理。
private class SmsRecevier extends ContentObserver{
public SmsRecevier(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null, null);
while(cursor.moveToNext()){
StringBuilder sb = new StringBuilder();
int isRead ;
sb.append("id=").append(cursor.getInt(cursor.getColumnIndex("_id"))); //獲取短信的內容,關於短信數據庫中都有哪些內容,可以參考官方文檔,查看其都實現了哪些接口。
sb.append(",address=").append(cursor.getString(cursor.getColumnIndex("address")));
sb.append(";body=").append(cursor.getString(cursor.getColumnIndex("body")));
sb.append(";time=").append(cursor.getLong(cursor.getColumnIndex("date")));
isRead = cursor.getInt(cursor.getColumnIndex("read"));
if(isRead == 0){
System.out.println("sb="+sb.toString());
}
}
System.out.println("sms database changed");
super.onChange(selfChange);
}
}