Android视频学习(九):内容提供者和知识点回顾

内容提供者

  • 应用的数据库是不允许其他应用访问的
  • 内容提供者的作用就是让别的应用访问到你的私有数据
  • 自定义内容提供者,继承ContentProvider类,重写增删改查方法,在方法中写增删改查数据库的代码,举例增方法
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            db.insert("person", null, values);
            return uri;
        }
  • 在清单文件中定义内容提供者的标签,注意必须要有authorities属性,这是内容提供者的主机名,功能类似地址
        <provider android:name="com.itheima.contentprovider.PersonProvider"
            android:authorities="com.itheima.person"
            android:exported="true"
         ></provider>
  • 创建一个其他应用,访问自定义的内容提供者,实现对数据库的插入操作
        public void click(View v){
            //得到内容分解器对象
            ContentResolver cr = getContentResolver();
            ContentValues cv = new ContentValues();
            cv.put("name", "小方");
            cv.put("phone", 138856);
            cv.put("money", 3000);
            //url:内容提供者的主机名
            cr.insert(Uri.parse("content://com.itheima.person"), cv);
        }

UriMatcher

  • 用于判断一条uri跟指定的多条uri中的哪条匹配
  • 添加匹配规则
        //创建uri匹配器
    UriMatcher um = new UriMatcher(UriMatcher.NO_MATCH);
    {
        //添加匹配规则
        //arg0:主机名
        //arg1:路径
        //arg2:匹配码
        //指定多条uri
        um.addURI("com.itheima.people", "person", 1);//content://com.itheima.people/person
        um.addURI("com.itheima.people", "handsome", 2);//content://com.itheima.people/handsome
        //#号可以代表任意数字
        um.addURI("com.itheima.people", "person/#", 3);//content://com.itheima.people/person/10
    }
  • 通过Uri匹配器可以实现操作不同的表
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            if(um.match(uri) == 1){
                db.insert("person", null, values);
            }
            else if(um.match(uri) == 2){
                db.insert("company", null, values);
            }
            else{
                throw new IllegalArgumentException();
            }
            return uri;
        }
  • 如果路径中带有数字,把数字提取出来的api
        int id = (int) ContentUris.parseId(uri);

短信数据库

  • 只需要关注sms表
  • 只需要关注4个字段
    • body:短信内容
    • address:短信的发件人或收件人号码(跟你聊天那哥们的号码)
    • date:短信时间
    • type:1为收到,2为发送

读取系统短信,首先查询源码获得短信数据库内容提供者的主机名和路径,然后访问内容提供者

        ContentResolver cr = getContentResolver();
        Cursor c = cr.query(Uri.parse("content://sms"), new String[]{"body", "date", "address", "type"}, null, null, null);
        while(c.moveToNext()){
            String body = c.getString(0);
            String date = c.getString(1);
            String address = c.getString(2);
            String type = c.getString(3);
            System.out.println(body+";" + date + ";" + address + ";" + type);
        }

插入系统短信

        ContentResolver cr = getContentResolver();
        ContentValues cv = new ContentValues();
        cv.put("body", "您尾号为XXXX的招行储蓄卡收到转账1,000,000人民币");
        cv.put("address", 95555);
        cv.put("type", 1);
        cv.put("date", System.currentTimeMillis());
        cr.insert(Uri.parse("content://sms"), cv);
  • 插入查询系统短信需要注册权限

联系人数据库

  • raw_contacts表:
    • contact_id:联系人id
  • data表:联系人的具体信息,一个信息占一行
    • data1:信息的具体内容
    • raw_contact_id:联系人id,描述信息属于哪个联系人
    • mimetype_id:描述信息是属于什么类型
  • mimetypes表:通过mimetype_id到该表查看具体类型

读取联系人

  • 先查询raw_contacts表拿到联系人id
        Cursor cursor = cr.query(Uri.parse("content://com.android.contacts/raw_contacts"), new String[]{"contact_id"}, null, null, null);
  • 然后拿着联系人id去data表查询属于该联系人的信息
        Cursor c = cr.query(Uri.parse("content://com.android.contacts/data"), new String[]{"data1", "mimetype"}, "raw_contact_id = ?", new String[]{contactId}, null);
  • 得到data1字段的值,就是联系人的信息,通过mimetype判断是什么类型的信息
        while(c.moveToNext()){
            String data1 = c.getString(0);
            String mimetype = c.getString(1);
            if("vnd.android.cursor.item/email_v2".equals(mimetype)){
                contact.setEmail(data1);
            }
            else if("vnd.android.cursor.item/name".equals(mimetype)){
                contact.setName(data1);
            }
            else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
                contact.setPhone(data1);
            }
        }

插入联系人

  • 先查询raw_contacts表,确定新的联系人的id应该是多少
  • 把确定的联系人id插入raw_contacts表
        cv.put("contact_id", _id);
        cr.insert(Uri.parse("content://com.android.contacts/raw_contacts"), cv);
  • 在data表插入数据
    • 插3个字段:data1、mimetype、raw_contact_id
    cv = new ContentValues();
            cv.put("data1", "赵六");
            cv.put("mimetype", "vnd.android.cursor.item/name");
            cv.put("raw_contact_id", _id);
            cr.insert(Uri.parse("content://com.android.contacts/data"), cv);

            cv = new ContentValues();
            cv.put("data1", "1596874");
            cv.put("mimetype", "vnd.android.cursor.item/phone_v2");
            cv.put("raw_contact_id", _id);
            cr.insert(Uri.parse("content://com.android.contacts/data"), cv);

内容观察者

  • 当数据库数据改变时,内容提供者会发出通知,在内容提供者的uri上注册一个内容观察者,就可以收到数据改变的通知
        cr.registerContentObserver(Uri.parse("content://sms"), true, //如果为true,以这个uri作为开头的uri上的数据改变了,该内容观察者都会收到通知,false精确匹配
         new MyObserver(new Handler()));

        class MyObserver extends ContentObserver{

            public MyObserver(Handler handler) {
                super(handler);
                // TODO Auto-generated constructor stub
            }

            //内容观察者收到数据库发生改变的通知时,会调用此方法
            @Override
            public void onChange(boolean selfChange) {

            }

        }
  • 在内容提供者中发通知的代码
        ContentResolver cr = getContext().getContentResolver();
        //发出通知,所有注册在这个uri上的内容观察者都可以收到通知
        cr.notifyChange(uri, null);

知识点回顾

  • ADB进程
  • adb指令

    • adb install xxx.apk
    • adb uninstall 包名
    • adb devices
    • adb start-server
    • adb kill-server
    • adb shell
      • ls
      • ps
      • rm
      • cd
    • adb push 文件路径/文件名 sdcard/文件名
    • adb pull sdcard/文件名
  • Android开发环境

    • sdk
    • eclipse
    • adt:eclipse插件
  • DDMS
    • 查看Android设备
    • 控制台输出
    • 给模拟器打电话发短信
  • Android项目目录结构
    • assets:较大资源文件,没有资源id,使用io流读取
    • libs:第三方jar包
    • res:资源文件,有资源id
  • 按钮点击事件
    • 设置侦听
    • onClick属性
  • android五种常见布局
    • 线性
    • 相对
    • 表格:TableRow
    • 绝对
  • Log
    • 控制台输出分5个等级
    • Log.v
    • Log.e
  • 单元测试框架
    • AndroidTestCase
    • 指令集和类库
  • 数据存储
    • 文件读写:内部存储、外部存储路径
    • SharedPreference
      • 键值对形式保存数据
      • 保存到xml文件
    • 数据库SQLite数据库
    • ContentProvider
      • 把数据保存在别人的私有文件中
  • XML生成解析
    • XmlSerializer,序列化器
    • DOM、SAX、PULL
    • pull事件类型
      • START_DOCUMENT
      • END_DOCUMENT
      • START_TAG
      • END_TAG
      • TEXT
  • SQLite数据库
    • SQLiteOpenHelper:创建数据库
    • 构造方法的4个参数
    • SQLiteDatabase:增删改查
    • 主键:_id
  • ListView:用于显示列表
    • 条目是一个View对象,可以用布局文件填充而来
    • 设置Adapter
    • getCount:获取条目总数
    • getView:获取View对象作为条目显示
    • 条目一旦划出屏幕,就会被缓存
    • 下一次getView方法调用时,会把缓存传进去
  • 网络请求
    • URL对象封装网址
    • 打开连接对象
    • 对连接对象做设置
      • 请求方式get/post
      • 连接/读取超时
    • 发送请求,获取相应码
    • 服务器通过流把请求的数据交给客户端
  • 消息队列机制
    • 主线程创建时,就会创建MessageQueue和Looper对象
    • 程序员创建Handler对象
    • 消息队列中有消息,Looper就把消息取出,交给Handler,触发handleMessage调用
    • 发送消息:sendMessage
      • 把消息发到创建Handler的那个线程的消息队列
    • 消息携带数据
      • what
      • obj
      • setData:Bundle
  • Android四大组件
    • Activity
    • service
    • broadcastReceiver
    • contentProvider
  • Activity
    • 生命周期:
      • oncreate
      • onstart
      • onresume
      • onpause
      • onstop
      • ondestroy
      • onrestart
    • 启动方式:
      • startActivity
      • startActivityForResult
      • 回调onActivityReslut
    • 启动模式:
      • 标准
      • singleTop
      • singleTask
      • singleInstance
  • Intent
    • Activity跳转
    • Service启动
    • 广播发送
    • 显式意图:指定目标Activity/Service的字节码
    • 隐式意图:设置intent对象去匹配intent-filter
    • 可以封装数据
      • 八大基本数据类型及其数组
      • String及其数组
      • bundle
      • 实现了序列化接口的对象
        • Serializable
        • Parcelable
  • 广播接收者
    • 通过intent-filter定义接收什么广播
    • 可以设置优先级,对于有序广播有效
    • 有序广播
      • 按照优先级区分接收的先后顺序
    • 无序广播
      • 不分先后顺序
      • 不能拦截,不能修改广播内容
  • Service
    • 启动方式
      • startService
        • 服务进程
        • 服务跟Activity没有一毛钱关系
        • onCreate-onStartCommand-onDestroy
      • bindService
        • 进程优先级不变
        • 服务和Activity同生共死
          • onCreate-onBind-onUnbind-onDestroy
    • 进程优先级
      • 前台进程
      • 可见进程
      • 服务进程
      • 后台进程
      • 空进程
      • 先杀优先级低的,相同优先级,LRU算法定生死
  • AIDL
    • 把接口文件后缀名改成aidl
    • aidl中默认都是public,不需要也不允许定义访问修饰符
    • 中间人对象继承Stub
    • 把aidl赋值到启动者的应用中,包名必须一致
    • 绑定时获得中间人对象,Stub.asInterface强转
  • ContentProvider:
    • 共享私有数据
    • 提高安全性,可以定义共享规则
    • Uri匹配器
      • 匹配Uri末尾携带的内容
    • ContentObserver:接收通知,内容提供者改变数据库时会发通知
  • 播放器
    • MediaPlayer:音乐视频
    • SurfaceView:视频播放
      • surfaceHolder
      • 可见时创建,不可见时销毁
  • 摄像头

    • 启动系统自带的Activity
    • Camera:负责拍照
    • SurfaceView:显示预览界面
  • 图片处理

    • 加载图片时会解析图片的所有像素信息
    • 内存中使用ARGB保存像素信息,也就是32位色,占用4个字节
    • 压缩图片后再加载

代码下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值