執行效果圖:
預備知識:
為了監聽指定的ContentProvider的數據的改變,須要通過ContentResolver向指定Uri注冊CotentObserver監聽器。ContentResolver提供了例如以下方法來注冊監聽器:
publicfinal void registerContentObserver(Uriuri, boolean notifyForDescendents, ContentObserver observer)
參數:uri :該監聽器所監聽的ContentProvider的Uri。
notifyForDescendents :為false 表示精確匹配。即僅僅匹配該Uri,為true 表示能夠同一時候匹配其派生的Uri。
observer:ContentObserver派生的監聽器實例。
取消注冊監聽器:
public finalvoid unregisterContentObserver(ContentObserver observer)
功能:取消對給定Uri的觀察
參數: observer ContentObserver的派生類實例。
ContentObserver——內容觀察者,目的是觀察(捕捉)特定Uri引起的數據庫的變化,繼而做一些對應的處理,它類似於數據庫技術中的觸發器(Trigger)。當ContentObserver所觀察的Uri發生變化時,便會觸發它。觸發器分為表觸發器、行觸發器。對應地ContentObserver也分為“表“ContentObserver、“行”ContentObserver,當然這是與它所監聽的Uri MIME Type有
關的。
ContentObserver類介紹:
接收回調的更改內容。
必須由被加入到一個ContentObservable對象實現。
構造方法:
| Public Constructors |
|
|
ContentObserver(Handler handler) onChange() will happen on the provider Handler. |
|
說明:全部 ContentObserver的派生類都須要調用該構造方法
參數:handler Handler對象。能夠是主線程Handler(這時候能夠更新UI 了),也能夠是不論什么Handler對象。
經常用法:
| Public Methods |
|
|
boolean |
deliverSelfNotifications() Returns true if this observer is interested in notifications for changes made through the cursor the observer is registered with. |
|
final void |
dispatchChange(boolean selfChange) |
|
void |
onChange(boolean selfChange) This method is called when a change occurs to the cursor that is being observed. |
說明:
void onChange(booleanselfChange)
功能:當觀察到的Uri發生變化時,回調該方法去處理。全部ContentObserver的派生類都須要重載該方法去處理邏輯。
參數:selfChange 回調后。其值一般為false,該參數意義不大(我也不懂。理解方法最重要)。
觀察特定Uri的過程例如以下:
1、 創建我們特定的ContentObserver派生類。必須重載父類構造方法。必須重載onChange()方法去處理回調后的功能實現
2、 利用context.getContentResolover()獲得ContentResolove對象。接着調用registerContentObserver()方法去注冊內容觀察者
如://為content://sms的數據改變注冊監聽器getContentResolver().registerContentObserver(Uri.parse
("content://sms"), true, new SmsObserver(new Handler()));
3、 因為ContentObserver的生命周期不同步於Activity和Service等。因此,在不須要時,須要手動的調用unregisterContentObserver()去取消注冊。
短信相關權限:
<!-- 發送消息--><uses-permission android:name="android.permission.SEND_SMS"/>
<!-- 閱讀消息-->
<uses-permission android:name="android.permission.READ_SMS"/>
<!-- 寫入消息-->
<uses-permission android:name="android.permission.WRITE_SMS" />
<!-- 接收消息 -->
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
相關的協議:
content://sms/sent
content://sms/draft
content://sms/outbox
content://sms/failed
content://sms/queued
數據庫中sms相關的字段及說明:
| 字段 |
說明 |
| _id |
短信序號,如100 |
| thread_id |
對話的序號,如100,與同一個手機號互發的短信。其序號是同樣的 |
| address |
發件人地址,即手機號。如+86138138000 |
| person |
發件人,假設發件人在通訊錄中則為詳細姓名。陌生人為null |
| date |
日期。long型,如1346988516。能夠對日期顯示格式進行設置 |
| protocol |
協議0SMS_RPOTO短信,1MMS_PROTO彩信 |
| read |
是否閱讀0未讀,1已讀 |
| status |
短信狀態-1接收,0complete,64pending,128failed |
| type |
短信類型1是接收到的,2是已發出 |
| body |
短信詳細內容 |
| service_center |
短信服務中心號碼編號。如+8613800755500 |
應用實例:
package com.jph.monitorsms; import java.text.SimpleDateFormat; import java.util.Date; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.widget.Toast; import android.app.Activity; import android.database.ContentObserver; import android.database.Cursor; /** * Describe:</br> * 獲取用戶正在發送的短信 * 本實例通過為content://sms的數據改變注冊監聽器來 * 獲取手機正在發送的消息。* @author JPH * Date:2014.07.20 * */ public class MonitorSms extends Activity { TextView txtView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txtView=(TextView)findViewById(R.id.txtView); //為content://sms的數據改變注冊監聽器 getContentResolver().registerContentObserver(Uri.parse ("content://sms"), true, new SmsObserver(new Handler())); } //一個繼承自ContentObserver的監聽器類 class SmsObserver extends ContentObserver{ public SmsObserver(Handler handler) { super(handler); // TODO Auto-generated constructor stub } @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub //查詢發送向箱中的短信 Cursor cursor=getContentResolver().query(Uri.parse( "content://sms/outbox"), null, null, null, null); //遍歷查詢結果獲取用戶正在發送的短信 while (cursor.moveToNext()) { StringBuffer sb=new StringBuffer(); //獲取短信的發送地址 sb.append("發送地址:"+cursor.getString(cursor.getColumnIndex("address"))); //獲取短信的標題 sb.append("\n標題:"+cursor.getString(cursor.getColumnIndex("subject"))); //獲取短信的內容 sb.append("\n內容:"+cursor.getString(cursor.getColumnIndex("body"))); //獲取短信的發送時間 Date date=new Date(cursor.getLong(cursor.getColumnIndex("date"))); //格式化以秒為單位的日期 SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 hh時mm分ss秒"); sb.append("\n時間:"+sdf.format(date)); System.out.println("查詢到的正在發送的短信:"+sb.toString()); Toast.makeText(MonitorSms.this, sb.toString(), Toast.LENGTH_LONG).show(); txtView.setText(sb.toString()); } super.onChange(selfChange); } } }


