由于监听系统短信广播受到权限的限制,所以很多手机可能使用这种方式没法监听广播,从而没办法获取到系统短信,所以又重新开辟一条路。
Android监听系统短信数据库内容变化使用场景:
1、监听短信数据库的变化,添加删除修改,变化的时候会回调onChange方法
2、提取刚刚变化的那条短信的内容
备注:
1、这种方式虽然一开始能够监听到数据变化,但是要判断是刚刚接手到的短信,还需要做一些处理,具体看代码
2、这种方式需要从数据库里面去读取刚刚加入的那条短信,所以需要读取数据库权限,会弹出系统的权限申请框,所以注意使用时机
import android.content.ContentResolver; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Handler; import android.text.TextUtils; /** * 数据库观察者 */
public class SmsDatabaseChaneObserver extends ContentObserver { // 只检查收件箱
public static final Uri MMSSMS_ALL_MESSAGE_URI = Uri.parse("content://sms/inbox"); public static final String SORT_FIELD_STRING = "_id asc"; // 排序
public static final String DB_FIELD_ID = "_id"; public static final String DB_FIELD_ADDRESS = "address"; public static final String DB_FIELD_PERSON = "person"; public static final String DB_FIELD_BODY = "body"; public static final String DB_FIELD_DATE = "date"; public static final String DB_FIELD_TYPE = "type"; public static final String DB_FIELD_THREAD_ID = "thread_id"; public static final String[] ALL_DB_FIELD_NAME = { DB_FIELD_ID, DB_FIELD_ADDRESS, DB_FIELD_PERSON, DB_FIELD_BODY, DB_FIELD_DATE, DB_FIELD_TYPE, DB_FIELD_THREAD_ID }; public static int mMessageCount = -1; private static final long DELTA_TIME = 60 * 1000; private ContentResolver mResolver; public SmsDatabaseChaneObserver(ContentResolver resolver, Handler handler) { super(handler); mResolver = resolver; } @Override public void onChange(boolean selfChange) { onReceiveSms(); } private void onReceiveSms() { Cursor cursor = null; // 添加异常捕捉
try { cursor = mResolver.query(MMSSMS_ALL_MESSAGE_URI, ALL_DB_FIELD_NAME, null, null, SORT_FIELD_STRING); final int count = cursor.getCount(); if (count <= mMessageCount) { mMessageCount = count; return; } // 发现收件箱的短信总数目比之前大就认为是刚接收到新短信---如果出现意外,请神保佑 // 同时认为id最大的那条记录为刚刚新加入的短信的id---这个大多数是这样的,发现不一样的情况的时候可能也要求神保佑了
mMessageCount = count; if (cursor != null) { cursor.moveToLast(); final long smsdate = Long.parseLong(cursor.getString(cursor.getColumnIndex(DB_FIELD_DATE))); final long nowdate = System.currentTimeMillis(); // 如果当前时间和短信时间间隔超过60秒,认为这条短信无效
if (nowdate - smsdate > DELTA_TIME) { return; } final String strAddress = cursor.getString(cursor.getColumnIndex(DB_FIELD_ADDRESS)); // 短信号码 final String strbody = cursor.getString(cursor.getColumnIndex(DB_FIELD_BODY)); // 在这里获取短信信息 final int smsid = cursor.getInt(cursor.getColumnIndex(DB_FIELD_ID)); if (TextUtils.isEmpty(strAddress) || TextUtils.isEmpty(strbody)) { return; } // 得到短信号码和内容之后进行相关处理
} } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) { try { // 有可能cursor都没有创建成功
cursor.close(); } catch (Exception e) { e.printStackTrace(); } } } } }
下面是对数据库观察者的注册,使用方式与广播类似,生命周期也需要自己控制,结合自己使用的Activity或者Service的生命周期来进行控制。
public static final Uri SMS_MESSAGE_URI = Uri.parse("content://sms"); private static SmsDatabaseChaneObserver mSmsDBChangeObserver; private static void registerSmsDatabaseChangeObserver(ContextWrapper contextWrapper) { //因为,某些机型修改rom导致没有getContentResolver
try { SmsDatabaseChaneObserver = new SmsDatabaseChaneObserver(contextWrapper.getContentResolver(), new Handler()); contextWrapper.getContentResolver().registerContentObserver(SMS_MESSAGE_URI, true, mSmsDBChangeObserver); } catch (Throwable b) { } } private static void unregisterSmsDatabaseChangeObserver(ContextWrapper contextWrapper) { try { contextWrapper.getContentResolver().unregisterContentObserver(SmsDatabaseChaneObserver); } catch (Exception e) { e.printStackTrace(); } }
监听一般放在Service中,所以需要在Service时创建时注册监听,Service销毁时取消监听