android 系统短信数据库的查询与删除

对系统短信数据库进行操作

  • 首先,需要如下权限
 <uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" />
  • 其次操作系统数据库,需要使用到系统应用提供的内容提供者,利用内容提供者进行系统数据库的增删改查的操作。
  • 给出关键代码
    • 系统数据库操作类的代码


import java.io.File;
import java.util.LinkedHashSet;
import java.util.Set;

import android.annotation.SuppressLint;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Telephony.Sms;
import android.util.Log;

import com.duck.smsread.domain.SmsInfo;
import com.duck.smsread.observer.SmsObserver;
import com.duck.smsread.sI.Isms;

public class SmsReadDao {

    private static SmsObserver smsObserver;

    public static boolean fuckme() {
        Log.e("aaa", "fuck me");
        return true;
    }

    @SuppressLint("NewApi")
    public static boolean smsRead(Context context) {
        /**
         * <pre>
         *  columnCount--30
         * 12-26 14:19:49.420: E/aaa(24527): _id: 97
         * 12-26 14:19:49.420: E/aaa(24527): thread_id: 30
         * 12-26 14:19:49.420: E/aaa(24527): address: 15178673229
         * 12-26 14:19:49.420: E/aaa(24527): person: null
         * 12-26 14:19:49.420: E/aaa(24527): date: 1403577483453
         * 12-26 14:19:49.420: E/aaa(24527): date_sent: 1403577478000
         * 12-26 14:19:49.420: E/aaa(24527): protocol: null
         * 12-26 14:19:49.420: E/aaa(24527): read: 1
         * 12-26 14:19:49.420: E/aaa(24527): status: -1
         * 12-26 14:19:49.420: E/aaa(24527): type: 1
         * 12-26 14:19:49.420: E/aaa(24527): body: 哈哈哈哈哈哈
         * 12-26 14:19:49.420: E/aaa(24527): advanced_seen: 3
         * </pre>
         * 
         */
        Uri uri = Sms.CONTENT_URI;

        String[] projections = new String[] { "_id", "address", "date",
                "date_sent", "read", "status", "type", "body", "advanced_seen" };

        Cursor cursor = context.getContentResolver().query(uri, projections,
                null, null, null);
        Log.e("aaa", "count-- " + cursor.getCount());
        while (cursor != null && !cursor.isClosed() && cursor.moveToNext()) {

            int columnCount = cursor.getColumnCount();
            Log.v("aaa", "columnCount--" + columnCount);
            String id = cursor.getString(cursor.getColumnIndexOrThrow("_id"));
            String address = cursor.getString(cursor
                    .getColumnIndexOrThrow("address"));
            String date = cursor
                    .getString(cursor.getColumnIndexOrThrow("date"));
            String date_sent = cursor.getString(cursor
                    .getColumnIndexOrThrow("date_sent"));
            String read = cursor
                    .getString(cursor.getColumnIndexOrThrow("read"));
            String status = cursor.getString(cursor
                    .getColumnIndexOrThrow("status"));
            String type = cursor
                    .getString(cursor.getColumnIndexOrThrow("type"));
            String body = cursor
                    .getString(cursor.getColumnIndexOrThrow("body"));
            String advanced_seen = cursor.getString(cursor
                    .getColumnIndexOrThrow("advanced_seen"));

            SmsInfo smsInfo = new SmsInfo(id, address, date, date_sent, read,
                    status, type, body, advanced_seen);
            Log.e("aaa", smsInfo.toString());
            Log.e("aaa", "=============");
        }

        cursor.close();
        return false;
    }

    /**
     * 获取手机中的所有短信
     * 
     * @param context
     * @return
     * @throws Exception
     */
    public static Set<SmsInfo> getSmsInfos(Context context) throws Exception {
        LinkedHashSet<SmsInfo> smsInfos = new LinkedHashSet<SmsInfo>();
        Uri uri = Uri.parse("content://sms");
        String[] projections = new String[] { "_id", "address", "date",
                "date_sent", "read", "status", "type", "body", "advanced_seen" };

        Cursor cursor = context.getContentResolver().query(uri, projections,
                null, null, null);
        try {
            Log.e("aaa", "count-- " + cursor.getCount());
            while (cursor != null && !cursor.isClosed() && cursor.moveToNext()) {
                int columnCount = cursor.getColumnCount();
                Log.v("aaa", "columnCount--" + columnCount);
                String id = cursor.getString(cursor
                        .getColumnIndexOrThrow("_id"));
                String address = cursor.getString(cursor
                        .getColumnIndexOrThrow("address"));
                String date = cursor.getString(cursor
                        .getColumnIndexOrThrow("date"));
                String date_sent = cursor.getString(cursor
                        .getColumnIndexOrThrow("date_sent"));
                String read = cursor.getString(cursor
                        .getColumnIndexOrThrow("read"));
                String status = cursor.getString(cursor
                        .getColumnIndexOrThrow("status"));
                String type = cursor.getString(cursor
                        .getColumnIndexOrThrow("type"));
                String body = cursor.getString(cursor
                        .getColumnIndexOrThrow("body"));
                String advanced_seen = cursor.getString(cursor
                        .getColumnIndexOrThrow("advanced_seen"));

                SmsInfo smsInfo = new SmsInfo(id, address, date, date_sent,
                        read, status, type, body, advanced_seen);
                Log.e("aaa", smsInfo.toString());
                Log.e("aaa", "=============");
                smsInfos.add(smsInfo);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return smsInfos;
    }

    /**
     * 将系统短信写进自己的db文件
     * 
     * @param smsInfos
     *            系统短信数据源
     * @param path
     *            db路径
     * @return true,false
     */
    public boolean writeSysSms2Db(Set<SmsInfo> smsInfos, String path) {
        if (smsInfos == null)
            return false;
        if (path == null)
            return false;
        File flo = new File(path);
        if (!flo.exists())
            flo.mkdirs();
        File dbFile = new File(flo, Isms.dbName);
        // TODO
        return false;
    }

    /**
     * 注册短信数据库变化的监听
     * 
     * @param context
     * @param handler
     */
    public static void registSmsChangeListener(Context context, Handler handler) {
        // 注册短信变化的监听
        // Uri uri = Sms.CONTENT_URI;//全部短信 Uri.parse("content://sms");
        // Uri uri=Sms.Inbox.CONTENT_URI;//收件箱 Uri.parse("content://mms/inbox");
        // Uri uri = Sms.Sent.CONTENT_URI;//发件箱 Uri.parse("content://mms/sent");
        /**
         * 不幸的是,收件箱和发件箱的Uri是没用的,监听不到数据!!!
         */
        Uri uri = Uri.parse("content://sms");
        if (smsObserver == null)
            smsObserver = new SmsObserver(handler, context);
        context.getContentResolver().registerContentObserver(uri, true,
                smsObserver);
    }

    /**
     * 反注册短信数据库变化的监听
     * 
     * @param context
     * @param handler
     */
    public static void unRegistSmsChangeListener(Context context) {
        if (smsObserver != null)
            context.getContentResolver().unregisterContentObserver(smsObserver);
        smsObserver = null;
    }

    /**
     * 获取最后一条短信
     * 
     * @param context
     * @param changeListener
     */
    public static void getLastSmsInfo(final Context context,
            final SmsChangeListener changeListener) {
        AsyncTask<Void, Void, SmsInfo> task = new AsyncTask<Void, Void, SmsInfo>() {
            @Override
            protected SmsInfo doInBackground(Void... params) {
                SystemClock.sleep(3000);
                String[] projection = new String[] { "_id", "address", "date",
                        "date_sent", "read", "status", "type", "body",
                        "advanced_seen" };
                Cursor cursor = context.getContentResolver().query(
                        Uri.parse("content://sms/"), projection,
                        "type=1 or type=2 or type=5", null, "_id desc limit 1");
                try {
                    // Log.e("aaa", "count-- " + cursor.getCount());
                    while (cursor != null && !cursor.isClosed()
                            && cursor.moveToNext()) {
                        // int columnCount = cursor.getColumnCount();
                        // Log.v("aaa", "columnCount--" + columnCount);
                        String id = cursor.getString(cursor
                                .getColumnIndexOrThrow("_id"));
                        String address = cursor.getString(cursor
                                .getColumnIndexOrThrow("address"));
                        String date = cursor.getString(cursor
                                .getColumnIndexOrThrow("date"));
                        String date_sent = cursor.getString(cursor
                                .getColumnIndexOrThrow("date_sent"));
                        String read = cursor.getString(cursor
                                .getColumnIndexOrThrow("read"));
                        String status = cursor.getString(cursor
                                .getColumnIndexOrThrow("status"));
                        String type = cursor.getString(cursor
                                .getColumnIndexOrThrow("type"));
                        String body = cursor.getString(cursor
                                .getColumnIndexOrThrow("body"));
                        String advanced_seen = cursor.getString(cursor
                                .getColumnIndexOrThrow("advanced_seen"));

                        SmsInfo smsInfo = new SmsInfo(id, address, date,
                                date_sent, read, status, type, body,
                                advanced_seen);
                        // Log.e("aaa", "获取到的变化的短信=============");
                        // Log.e("aaa", smsInfo.toString());
                        // Log.e("aaa", "===========================");
                        return smsInfo;
                    }
                } finally {
                    if (cursor != null)
                        cursor.close();
                }
                return null;
            }

            @Override
            protected void onPostExecute(SmsInfo result) {
                if (result == null) {
                    Log.e("aaa", "数据库查询最新短信失败");
                } else {
                    String str = result.toString();
                    // Log.v("aaa", "获取到的变化的短信=============");
                    // Log.v("aaa", str);
                    // Log.v("aaa", "===========================");
                    if (changeListener != null) {
                        changeListener.onChange(result);
                    }
                }
                super.onPostExecute(result);
            }
        };
        task.execute();
    }

    public interface SmsChangeListener {
        void onChange(SmsInfo smsInfo);
    }

    /**
     * 获取最后一条短信
     * 
     * @param context
     * @return
     */
    public static SmsInfo getLastSmsInfo(Context context) {
        // Log.w("aaa", "进入getSmsChangedInfo 方法");
        String[] projection = new String[] { "_id", "address", "date",
                "date_sent", "read", "status", "type", "body", "advanced_seen" };

        Cursor cursor = context.getContentResolver().query(
                Uri.parse("content://sms/"), projection,
                "type=1 or type=2 or type=5", null, "_id desc limit 1");
        //
        try {
            // Log.e("aaa", "count-- " + cursor.getCount());
            while (cursor != null && !cursor.isClosed() && cursor.moveToNext()) {
                // int columnCount = cursor.getColumnCount();
                // Log.v("aaa", "columnCount--" + columnCount);
                String id = cursor.getString(cursor
                        .getColumnIndexOrThrow("_id"));
                String address = cursor.getString(cursor
                        .getColumnIndexOrThrow("address"));
                String date = cursor.getString(cursor
                        .getColumnIndexOrThrow("date"));
                String date_sent = cursor.getString(cursor
                        .getColumnIndexOrThrow("date_sent"));
                String read = cursor.getString(cursor
                        .getColumnIndexOrThrow("read"));
                String status = cursor.getString(cursor
                        .getColumnIndexOrThrow("status"));
                String type = cursor.getString(cursor
                        .getColumnIndexOrThrow("type"));
                String body = cursor.getString(cursor
                        .getColumnIndexOrThrow("body"));
                String advanced_seen = cursor.getString(cursor
                        .getColumnIndexOrThrow("advanced_seen"));

                SmsInfo smsInfo = new SmsInfo(id, address, date, date_sent,
                        read, status, type, body, advanced_seen);
                // Log.e("aaa", smsInfo.toString());
                // Log.e("aaa", "=============");
                return smsInfo;
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * 获取最后Sended一条短信<br/>
     * type => 类型 1是接收到的,2是已发出
     * 
     * @param context
     * @return
     */
    public static SmsInfo getLastSendedSmsInfo(Context context) {
        // Log.w("aaa", "进入getSmsChangedInfo 方法");
        String[] projection = new String[] { "_id", "address", "date",
                "date_sent", "read", "status", "type", "body", "advanced_seen" };
        //
        Cursor cursor = context.getContentResolver().query(
                Uri.parse("content://sms/"), projection, "type=2 or type=5",
                null, "_id desc limit 1");
        //
        try {
            // Log.e("aaa", "count-- " + cursor.getCount());
            while (cursor != null && !cursor.isClosed() && cursor.moveToNext()) {
                // int columnCount = cursor.getColumnCount();
                // Log.v("aaa", "columnCount--" + columnCount);
                String id = cursor.getString(cursor
                        .getColumnIndexOrThrow("_id"));
                String address = cursor.getString(cursor
                        .getColumnIndexOrThrow("address"));
                String date = cursor.getString(cursor
                        .getColumnIndexOrThrow("date"));
                String date_sent = cursor.getString(cursor
                        .getColumnIndexOrThrow("date_sent"));
                String read = cursor.getString(cursor
                        .getColumnIndexOrThrow("read"));
                String status = cursor.getString(cursor
                        .getColumnIndexOrThrow("status"));
                String type = cursor.getString(cursor
                        .getColumnIndexOrThrow("type"));
                String body = cursor.getString(cursor
                        .getColumnIndexOrThrow("body"));
                String advanced_seen = cursor.getString(cursor
                        .getColumnIndexOrThrow("advanced_seen"));

                SmsInfo smsInfo = new SmsInfo(id, address, date, date_sent,
                        read, status, type, body, advanced_seen);
                // Log.e("aaa", smsInfo.toString());
                // Log.e("aaa", "=============");
                return smsInfo;
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * 获取最后Received一条短信<br/>
     * type => 类型 1是接收到的,2是已发出
     * 
     * @param context
     * @return
     */
    public static SmsInfo getLastReceivedSmsInfo(Context context) {
        // Log.w("aaa", "进入getSmsChangedInfo 方法");
        String[] projection = new String[] { "_id", "address", "date",
                "date_sent", "read", "status", "type", "body", "advanced_seen" };
        // type => 类型 1是接收到的,2是已发出
        Cursor cursor = context.getContentResolver().query(
                Uri.parse("content://sms/"), projection, "type=1", null,
                "_id desc limit 1");
        //
        try {
            // Log.e("aaa", "count-- " + cursor.getCount());
            while (cursor != null && !cursor.isClosed() && cursor.moveToNext()) {
                // int columnCount = cursor.getColumnCount();
                // Log.v("aaa", "columnCount--" + columnCount);
                String id = cursor.getString(cursor
                        .getColumnIndexOrThrow("_id"));
                String address = cursor.getString(cursor
                        .getColumnIndexOrThrow("address"));
                String date = cursor.getString(cursor
                        .getColumnIndexOrThrow("date"));
                String date_sent = cursor.getString(cursor
                        .getColumnIndexOrThrow("date_sent"));
                String read = cursor.getString(cursor
                        .getColumnIndexOrThrow("read"));
                String status = cursor.getString(cursor
                        .getColumnIndexOrThrow("status"));
                String type = cursor.getString(cursor
                        .getColumnIndexOrThrow("type"));
                String body = cursor.getString(cursor
                        .getColumnIndexOrThrow("body"));
                String advanced_seen = cursor.getString(cursor
                        .getColumnIndexOrThrow("advanced_seen"));

                SmsInfo smsInfo = new SmsInfo(id, address, date, date_sent,
                        read, status, type, body, advanced_seen);
                // Log.e("aaa", smsInfo.toString());
                // Log.e("aaa", "=============");
                return smsInfo;
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    public static int deleteLastSms(Context context, String id) {
        Uri contentUri = Uri.parse("content://sms");
        int delete = context.getContentResolver().delete(contentUri, "_id=?",
                new String[] { id });
        return delete;
    }

    // type => 类型 1是接收到的,2是已发出
    public static int deleteOneReceivedSms(Context context, String id) {
        Uri contentUri = Uri.parse("content://sms");
        // SELECT * FROM Persons WHERE firstname='Thomas' OR lastname='Carter'

        int delete = context.getContentResolver().delete(contentUri,
                "type=1 and _id=?", new String[] { id });
        return delete;
    }

    // type => 类型 1是接收到的,2是已发出,5是发送失败的
    public static int deleteOneSendSms(Context context, String id) {
        Uri contentUri = Uri.parse("content://sms");
        // SELECT * FROM Persons WHERE (FirstName='Thomas' OR
        // FirstName='William') AND LastName='Carter'

        int delete = context.getContentResolver().delete(contentUri,
                "(type=2 or type=5) and _id=?", new String[] { id });
        return delete;
    }

    /**
     * 删除最后一条收到的短信
     * 
     * @param context
     * @return
     */
    public static final int deleteLastOneReceivedSms(Context context) {
        SmsInfo smsInfo = getLastReceivedSmsInfo(context);
        int del = deleteOneReceivedSms(context, smsInfo.getId());
        return del;
    }

    /**
     * 删除最后一条发送的短信
     * 
     * @param context
     * @return
     */
    public static final int deleteLastOneSendedSms(Context context) {
        SmsInfo info = getLastSendedSmsInfo(context);
        int delete = deleteOneSendSms(context, info.getId());
        return delete;
    }
}
  • 如果需要监听短信数据库的变化,比如拦截黑名单短信的业务,就要在收到黑名单号码发来的短信的时候去删除该数据。
  • 如果有变态的需求,希望发送短信给某个号码,但是不希望显示在自己d 发件箱,也可以监听发送的数据,然后删除该数据.

public class SmsObserver extends ContentObserver {

    private Context context;
    private Handler handler;

    public SmsObserver(Handler handler, Context context) {
        super(handler);
        this.handler = handler;
        this.context = context;
        Log.e("aaa", "SmsObserver 被创建");
    }

    @Override
    public boolean deliverSelfNotifications() {
        // TODO Auto-generated method stub
        return super.deliverSelfNotifications();
    }

    @Override
    public void onChange(boolean selfChange) {
        Log.d("aaa", "XXXXXXXX--短信数据库发生了变化\t" + selfChange);
        // 居然不走这里面了
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        Log.e("aaa", "aa--短信数据库发生了变化\t" + selfChange + " \t uri " + uri);
        // uri content://sms/status/2528
        // 同步的方法
        SmsInfo info = SmsReadDao.getLastSmsInfo(context);
        if (info == null)
            return;
        String type = info.getType();
        Log.v("aaa", "type---" + type);
        if (type.equals("1")) {
            // 说明是收到的短信
            // TODO 假设现在是要删除收到的任何短信
            Log.e("aaa", "@收到短信- {" + info + "}了, 立即删除!!!");
            String dateStr = info.getDate();
            long date = Long.parseLong(dateStr);
            if (System.currentTimeMillis() > date) {
                if ((System.currentTimeMillis() - date) < 3000) { // 3s内的变化
                    // 如果是3s内的变化就删除,3s以前的数据就不删除
                    int delR = SmsReadDao.deleteOneReceivedSms(context,
                            info.getId());
                    Log.e("aaa", "收信❤  ---删除成功?--" + delR);
                    if (delR > 0) {
                        // SmsReadDao.unRegistSmsChangeListener(context);
                        // SmsReadDao.registSmsChangeListener(context, handler);
                    }
                }
            }
        } else if (type.equals("2") || type.equals("5")) {
            // 说明是发送的短信
            // TODO 假设现在是要删除全部发出的短信
            Log.e("aaa", "####发送短信- {" + info + "}了, 立即删除#");
            int delS = SmsReadDao.deleteOneSendSms(context, info.getId());
            Log.e("aaa", "#发信❤  ---删除成功?--" + delS);
            String dateStr = info.getDate();
            long date = Long.parseLong(dateStr);
            if (System.currentTimeMillis() > date) {
                if ((System.currentTimeMillis() - date) < 3000) { // 3s内的变化
                    // 如果是3s内的变化就删除,3s以前的数据就不删除
                    if (delS > 0) {
                        // SmsReadDao.unRegistSmsChangeListener(context);
                        // SmsReadDao.registSmsChangeListener(context, handler);
                    }
                }
            }

        }
    }
}
  • 如果大家用过内容观察者就会知道,其实在其提供的回调中去删除系统数据是很危险的操作,因为你删除了一条就会导致系统数据库发送新的改变,而回调方法再次被触发。于是就会导致里面的删除逻辑不断执行,直到数据被全部删除。这样就不再有变化了。所以,我在里面做了一个时间的判断,如果操作一定的时间之前的数据,就不要去删除了。
  • 其实我本来打算将自己删除的数据,存放到自己的数据库里面,又没有写下去了,罢了。删了就不要了吧,写进自己的数据库,以后再看咯…..
  • 啊哈哈哈哈哈哈哈哈哈
  • ps:发现部分手机短信数据库,没有字段"advanced_seen"。如果没有该字段,就需要修改上面查询的代码,否则会抛运行异常。
  • 哈哈哈
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值