Android?ContentObserver?監(jiān)聽短信思路詳解
概述
內(nèi)容觀察器ContentObserver給目標內(nèi)容注冊一個觀察器,目標內(nèi)容的數(shù)據(jù)一旦發(fā)生變化,觀察器規(guī)定好的動作馬上觸發(fā),從而執(zhí)行開發(fā)者預(yù)先定義的代碼。
思路
注冊一個監(jiān)聽
getContentResolver().registerContentObserver(uri, true, mObserver);
繼承 ContentObserver 實現(xiàn)一個用于回調(diào)的監(jiān)聽類
private static class SmsGetObserver extends ContentObserver { private final Context mContext; public SmsGetObserver(Context context) { super(new Handler(Looper.getMainLooper())); this.mContext = context; } @SuppressLint("Range") @Override public void onChange(boolean selfChange, @Nullable Uri uri) { super.onChange(selfChange, uri); // onChange會多次調(diào)用,收到一條短信會調(diào)用兩次onChange // mUri===content://sms/raw/20 // mUri===content://sms/inbox/20 // 安卓7.0以上系統(tǒng),點擊標記為已讀,也會調(diào)用一次 // mUri===content://sms // 收到一條短信都是uri后面都會有確定的一個數(shù)字,對應(yīng)數(shù)據(jù)庫的_id,比如上面的20 Log.d("aabb",uri.toString()); if (uri == null) { return; } if (uri.toString().contains("content://sms/raw") || uri.toString().equals("content://sms")) { return; } // 通過內(nèi)容解析器獲取符合條件的結(jié)果游標集 Cursor cursor = mContext.getContentResolver().query(uri, new String[]{"address", "body", "date"}, null, null, "date Desc"); if (cursor.moveToNext()) { // 短信的發(fā)送號碼 String sender = cursor.getString(cursor.getColumnIndex("address")); // 短信內(nèi)容 String content = cursor.getString(cursor.getColumnIndex("body")); Log.d("AAAA", String.format("sender:%s,content:%s", sender, content)); } cursor.close(); } }
短信相關(guān)權(quán)限
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
完整代碼
package com.example.cpclient; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.Log; public class MonitorSmsActivity extends AppCompatActivity { private SmsGetObserver mObserver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_monitor_sms); // 給指定Uri注冊內(nèi)容觀察器,一旦發(fā)生數(shù)據(jù)變化,就觸發(fā)觀察器的onChange方法 Uri uri = Uri.parse("content://sms"); // notifyForDescendents: // false :表示精確匹配,即只匹配該Uri,true :表示可以同時匹配其派生的Uri // 假設(shè)UriMatcher 里注冊的Uri共有以下類型: // 1.content://AUTHORITIES/[table] // 2.content://AUTHORITIES/[table]/# // 3.content://AUTHORITIES/[table]/[subtable] // 假設(shè)我們當前需要觀察的Uri為content://AUTHORITIES/student: // 如果發(fā)生數(shù)據(jù)變化的 Uri 為 3。 // 當notifyForDescendents為false,那么該ContentObserver會監(jiān)聽不到,但是當notifyForDescendents 為ture,能捕捉該Uri的數(shù)據(jù)庫變化。 mObserver = new SmsGetObserver(this); getContentResolver().registerContentObserver(uri, true, mObserver); } @Override protected void onDestroy() { super.onDestroy(); getContentResolver().unregisterContentObserver(mObserver); } private static class SmsGetObserver extends ContentObserver { private final Context mContext; public SmsGetObserver(Context context) { super(new Handler(Looper.getMainLooper())); this.mContext = context; } @SuppressLint("Range") @Override public void onChange(boolean selfChange, @Nullable Uri uri) { super.onChange(selfChange, uri); // onChange會多次調(diào)用,收到一條短信會調(diào)用兩次onChange // mUri===content://sms/raw/20 // mUri===content://sms/inbox/20 // 安卓7.0以上系統(tǒng),點擊標記為已讀,也會調(diào)用一次 // mUri===content://sms // 收到一條短信都是uri后面都會有確定的一個數(shù)字,對應(yīng)數(shù)據(jù)庫的_id,比如上面的20 Log.d("aabb",uri.toString()); if (uri == null) { return; } if (uri.toString().contains("content://sms/raw") || uri.toString().equals("content://sms")) { return; } // 通過內(nèi)容解析器獲取符合條件的結(jié)果游標集 Cursor cursor = mContext.getContentResolver().query(uri, new String[]{"address", "body", "date"}, null, null, "date Desc"); if (cursor.moveToNext()) { // 短信的發(fā)送號碼 String sender = cursor.getString(cursor.getColumnIndex("address")); // 短信內(nèi)容 String content = cursor.getString(cursor.getColumnIndex("body")); Log.d("AAAA", String.format("sender:%s,content:%s", sender, content)); } cursor.close(); } } }
拓展
當在你的provider中,別人insert了一條數(shù)據(jù),你要告知他是否成功了
使用 notifyChange進行通知回調(diào)
getContext().getContentResolver().notifyChange()
案例
@Override public Uri insert(Uri uri, ContentValues values) { if (URI_MATCHER.match(uri) == USERS) { SQLiteDatabase db = dbHelper.getWritableDatabase(); long rowId = db.insert(UserDBHelper.TABLE_NAME, null, values); if (rowId > 0) { // 如果添加成功,就利用新記錄的行號生成新的地址 Uri newUri = ContentUris.withAppendedId(UserInfoContent.CONTENT_URI, rowId); // 通知監(jiān)聽器,數(shù)據(jù)已經(jīng)改變 getContext().getContentResolver().notifyChange(newUri, null); } } return uri; }
到此這篇關(guān)于Android ContentObserver 監(jiān)聽短信的文章就介紹到這了,更多相關(guān)Android ContentObserver 監(jiān)聽短信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
android Tween Animation屬性設(shè)置方法實例
在Android開發(fā)中,Animation是用來給控件制作效果的,本文介紹二種實現(xiàn)方法2013-11-11Android開發(fā)InputManagerService創(chuàng)建與啟動流程
這篇文章主要為大家介紹了Android開發(fā)InputManagerService創(chuàng)建與啟動流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11Android使用android-wheel實現(xiàn)省市縣三級聯(lián)動
這篇文章主要為大家詳細介紹了Android使用android-wheel實現(xiàn)省市縣三級聯(lián)動,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-08-08android圖像繪制(六)獲取本地圖片或拍照圖片等圖片資源
從SD卡中獲取圖片資源,或者拍一張新的圖片,然后再進行處理(直接處理返回圖片/獲得圖片的地址再處理)接下來為您詳細介紹,感興趣的朋友可以了解下2013-01-01Android使用友盟集成QQ、微信、微博等第三方分享與登錄方法詳解
之前的項目第三方分享和登錄一直都使用ShareSDK實現(xiàn)的。為了統(tǒng)一使用友盟的全家桶,所以三方分享和登錄也就選擇了友盟,這里為大家整理出詳細方法2018-03-03Android Studio實現(xiàn)簡單計算器APP
這篇文章主要為大家詳細介紹了Android Studio實現(xiàn)簡單計算器APP,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-03-03Android基于service實現(xiàn)音樂的后臺播放功能示例
這篇文章主要介紹了Android基于service實現(xiàn)音樂的后臺播放功能,結(jié)合實例形式分析了Android基于Service組件實現(xiàn)多媒體音頻播放功能的步驟與相關(guān)操作技巧,需要的朋友可以參考下2016-10-10Android?中TextureView和SurfaceView的屬性方法及示例說明
這篇文章主要介紹了Android?中TextureView和SurfaceView的屬性方法及示例說明,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-06-06