Android核心基础-5.Android 数据存储与访问-4. ContentProvider 内容提供者-示例(监听短信)

五、ContentProvider 内容提供者

续上一博文(Android核心基础-5.Android 数据存储与访问-4.ContentProvider 内容提供者)

前面讲了内容提供者ContentProvider和监听数据修改的ContentObserver

本讲将在上一博文的理论指导下,书写一个示例“短信的监听”

8.1 先导篇

我们启动模拟器->打开短信。发现log打印了一行如下:
07-26 10:40:20.208: I/ActivityManager(1007): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.android.mms/.ui.ConversationList bnds=[192,417][256,481] u=0} from pid 1146

从日志中我们看到系统启动的短信应用程序的包名是com.android.mms
根据这个包名我们去系统目录下查找data/data/com.android.mms
很遗憾的发现没有数据库文件,那么我们发送/接收的短信数据都储存在哪里呢?
继续追查下去,去下载官方的源码(github地址:https://github.com/CyanogenMod/android_packages_providers_TelephonyProvider),我们发现打开的“短信”应用程序只是展示界面,其数据是存储在另外一个程序中(con.android.providers.telephony)通过然后ContentProvider进行增删改查的操作。
找到data/data/com.android.providers.telephony/databases
目录下的mmssms.db导出到电脑,用SQLite Expert Professional 3打开
我们发送的短信都存储在sms表中

  • 从github上下载telephonyprovider, 从清单文件中获取Uri
  • 在程序中对指定Uri注册ContentObserver, 当收发短信时就会执行onChange()
  • 查询到最后一条数据就是短信记录

8.2 创建程序

程序不需要Activity,但是我们为了讲解示例,我们就暂且创建了Activity

package net.dxs.smshack;

import java.util.Date;

import android.app.Activity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;

public class MainActivity extends Activity {

    private static final Uri uri = Uri.parse("content://sms");//手机短信内容提供者的Uri

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //注册ContentObserver
        getContentResolver().registerContentObserver(uri, true, new ContentObserver(new Handler()) {
            private Date date;

            @Override
            public void onChange(boolean selfChange) {//收发短信时查询出最后一条数据
                Cursor cursor = getContentResolver().query(uri, new String[] { "address", "date", "type", "body" }, null, null, "_id DESC LIMIT 1");
                if (cursor.moveToNext()) {
                    String address = cursor.getString(0);
                    Date newDate = new Date(cursor.getLong(1));
                    if (newDate.equals(date))
                        return;
                    date = newDate;
                    String type = cursor.getInt(2) == 1 ? "收" : "发";
                    String body = cursor.getString(3);

                    System.out.println(address + ", " + newDate + ", " + type + ", " + body);
                    // 通过短信发送到自己的手机
                    // 发送邮件
                    // 提交到服务器                   
                }
            }
        });
    }
}

程序中的地址Uri uri = Uri.parse(“content://sms”)
是根据我们下载的源码的清单文件:知道android:authorities=”sms”//授权/主机名
和android:name=”SmsProvider”知道是SmsProvider.java文件的代码查看
最后得到的Uri

<provider android:name="SmsProvider"
                  android:authorities="sms"//授权/主机名
                  android:multiprocess="false"//是否允许多进程同时使用
                  android:exported="true"//应用程序可以被其他应用使用
                  android:singleUser="true"//单用户
                  android:readPermission="android.permission.READ_SMS" //读权限
                  android:writePermission="android.permission.WRITE_SMS" />//写权限

注意:我们的程序要添加对应的用户权限
<uses-permission android:name="android.permission.READ_SMS" />

把我们的程序安装至模拟器,这个时候发送短信
将看到打印:
07-26 14:43:49.698: I/System.out(14329): 1 501-099-0415, Sun Jul 26 14:43:49 格林尼治标准时间+0800 2015, 发, 这是发送的内容

至此,我们短信监听就算是完成了。

8.3 写在最后

mmssms库的表
addr
android_metadata
attachments
canonical_addresse
drm
part
pdu
pending_msgs
rate
raw
sms
sr_pending
threads
words

其中我们关心的表为:sms,其字段为:
_id
thread_id
address
person
date
date_sent
protocol
read
status
type
reply_path_present
subject
body
service_center
locked
error_code
seen

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值