第八天

1、为什么需要内容提供者?(contentProvider)
     [1] 如何创建一个数据库? 创建一个类继承SqliteOpenHelper
     [2] sqlite3 打开数据库   
     [3]  chmod 修改文件权限
需求:从当前应用获取其他应用的数据库
    (1)  使用SqliteDatabase的静态方法  openDatabase(String path,Factory,mode);
        参数说明
            path:数据库所在的位置
            Factory:游标工厂
            mode:打开的模式,使用SqliteDatabase的静态常量就可以了
     [4]  使用内容提供者获取私有的数据库
2、内容提供者原理    
 [1]  内容提供者(ContentProvider)将内容进行封装提供出来,其他的应用都是通过内容的解析者(ContentResolve)来获取
3、实现内容提供者的步骤
    [1]  定义一个类继承ContentProvider
   
   
  1. public class ItProvider extends ContentProvider

    [2]  在清单文件中配置内容提供者 必须加一个属性authorities值为自定义字符串
    
    
  1. <provider
  2. android:exported="true"
  3. android:authorities="com.young.test"
  4. android:name="com.db.ItProvider"/>
    如果不加exported属性,会报
java.lang. SecurityException: Permission Denial: opening provider com.db.ItProvider from ProcessRecord{528581e0 6355:com.accessotherdb/u0a10053} (pid=6355, uid=10053) that is not  exported from uid 10052

    [3]  定义一个路径匹配器 UriMatcher
    
    
  1. private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //UriMatcher.NO_MATCH代表匹配不成功返回-1

    [4]  定义一个静态代码块,添加匹配规则  addURI
    
    
  1. static{
  2. uriMatcher.addURI("com.young.test","query",QUERYSUCCESS);
  3. }

    [5]  实现相应的匹配模块
    
    
  1. public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
  2. if (uriMatcher.match(uri) == QUERYSUCCESS){
  3. openHelper = new MyOpenHelper(getContext());
  4. db = openHelper.getReadableDatabase();
  5. Cursor it = db.query("It", strings, s, strings1, null, null, s1);
  6. return it;
  7. }
  8. return null;
  9. }

    [6]  在需要的app中调用
        (1)  直接使用上下文拿到resolve(getContentResolve)
    
    
  1. ContentResolver contentResolver = getContentResolver();
        (2)  然后就拿着resolve开始解析
    
    
  1. Uri uri = Uri.parse("content://com.young.test/query"); //content://相当于url里面的http://协议,是谷歌定义好的
  2. Cursor query = contentResolver.query(uri, null, null, null, null);
        (3)   下一步就是拿到结果集合,开始展示
    
    
  1. while(query.moveToNext()){
  2. Log.d("name",query.getString(1));
  3. Log.d("phone",query.getString(2));
  4. }

4、备份短信案例
    [1]  短信备份使用的是系统提供的sms应用下的provider,所以只需要获取内容解析者就可以了
    
    
  1. public void backup(View view){
  2. ContentResolver resolver = getContentResolver();
  3. /* sURLMatcher.addURI("sms", null, SMS_ALL);*/
  4. Uri uri = Uri.parse("content://sms/"); //在这里sms/后面不加通过源码可以知道这是查询所有的方式
  5. //下面的String类型,可以使用一个引号?
  6. Cursor cursor = resolver.query(uri, new String[]{"address","date","body"}, null, null, null);
  7. while(cursor.moveToNext()){
  8. Log.d("address",cursor.getString(0));
  9. Log.d("data",cursor.getString(1));
  10. Log.d("body",cursor.getString(2));
  11. }
  12. }
    [2]  将这些数据保存到sd卡进行文件备份,使用xml序列化器
    
    
  1. //[3] 开始写文档
  2. serializer.startDocument("utf-8",true);
  3. serializer.startTag(null,"smss");
  4. /* sURLMatcher.addURI("sms", null, SMS_ALL);*/
  5. Uri uri = Uri.parse("content://sms/"); //在这里sms/后面不加通过源码可以知道这是查询所有的方式
  6. //下面的String类型,可以使用一个引号?
  7. ContentResolver resolver = getContentResolver();
  8. Cursor cursor = resolver.query(uri, new String[]{"address","date","body"}, null, null, null);
  9. while(cursor.moveToNext()){
  10. serializer.startTag(null,"sms");
  11. serializer.startTag(null,"address");
  12. serializer.text(cursor.getString(0));
  13. serializer.endTag(null,"address");
  14. serializer.startTag(null,"date");
  15. serializer.text(cursor.getString(1));
  16. serializer.endTag(null,"date");
  17. serializer.startTag(null,"body");
  18. serializer.text(cursor.getString(2));
  19. serializer.endTag(null,"body");
  20. serializer.endTag(null,"sms");
  21. }
  22. serializer.endTag(null,"smss");
  23. serializer.endDocument();

5、读取联系人案例
    [1]  三张重要的表  data1里面存的是所有联系人的信息
    [2]  data里面的raw_contact_id实际上是raw_contact里面的contact_id
    [3]  data表里面的mimetype_id实际对应于mimetype列
    步骤
    [1]  先读取raw_contact表  读取contract_id字段,从而知道有多少个联系人
    [2]  根据contract_id读取data1列 和 mimetype列
    
    
  1. //[1] 首先读取raw_contact表里面的contact_id列,就可以知道有多少联系人
  2. ContentResolver resolver = getContentResolver();
  3. Uri contactUri = Uri.parse("content://com.android.contacts/raw_contacts");//content内容分别从contactProvider的AndroidManfest.xml中取出authorities,然后去源码页取出path
  4. Cursor cursor = resolver.query(contactUri, new String[]{"contact_id"}, null, null, null);
  5. while(cursor.moveToNext()){
  6. //在查找联系人个数后将每个联系人的信息从data表里面的data1和mimetype里面取出来
  7. ContentResolver resolver1 = getContentResolver();
  8. Uri dataUri = Uri.parse("content://com.android.contacts/data");
  9. Cursor cursor1 = resolver1.query(dataUri, new String[]{"data1", "mimetype"}, "raw_contact_id=?", new String[]{cursor.getString(0)}, null); //将每个联系人的所有数据取出来进行展示
  10. while (cursor1.moveToNext()){
  11. String data1 = cursor1.getString(0);
  12. String mimetype = cursor1.getString(1);
  13. if ("vnd.android.cursor.item/name".equals(mimetype)) { //进行mimetype类型判定
  14. System.out.println("name:"+data1);
  15. }else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){
  16. System.out.println("phone:"+data1);
  17. }else if("vnd.android.cursor.item/email_v2".equals(mimetype)){
  18. System.out.println("email:"+data1);
  19. }
  20. }
    [2]  需要权限
    
    
  1. <uses-permission android:name="android.permission.READ_CONTACTS"/>
    [3]  对于安卓手机,当用户删除掉联系人,只是将raw_contact_id的相应id置为null,所以可以恢复数据
6、插入联系人
    [1]  插入要影响的表有raw_contact表和data表,影响的列有contact_id(raw_contact)和mimetype、data1、contact_id(data)
    [2]  步骤:
        (1) 查询raw_contact表中的数据的条数count,将要插入的id为count+1
       (2)将id插入到raw_contact表的contact_id中
        (3)  将name,phone,email等插入到data表的data1列,并且标明数据属于哪一个id和哪一个mimetype
    
    
  1. public void insert(View view){
  2. //[1] 获取数据
  3. String name = et_name.getText().toString().trim();
  4. String phone = et_phone.getText().toString().trim();
  5. String email = et_email.getText().toString().trim();
  6. //[2] 查询raw_contact表中的数据条数
  7. ContentResolver resolver = getContentResolver();
  8. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  9. Cursor cursor = resolver.query(uri, null, null, null, null);
  10. int count = cursor.getCount();
  11. int contact_id = count + 1;
  12. //[3] 将contact_id添加进去
  13. ContentResolver insert_id = getContentResolver();
  14. ContentValues idValues = new ContentValues();
  15. idValues.put("contact_id",contact_id);
  16. insert_id.insert(uri,idValues);
  17. //[4] 将其他的数据添加到data表中
  18. Uri dataUri = Uri.parse("content://com.android.contacts/data");
  19. ContentResolver dataResolver = getContentResolver();
  20. ContentValues nameValues = new ContentValues();
  21. //设置信息类型
  22. nameValues.put("mimetype","vnd.android.cursor.item/name");
  23. //设置信息id
  24. nameValues.put("raw_contact_id",contact_id);
  25. //设置信息主体
  26. nameValues.put("data1",name);
  27. dataResolver.insert(dataUri,nameValues);
  28. ContentValues phoneValues = new ContentValues();
  29. phoneValues.put("mimetype","vnd.android.cursor.item/phone_v2");
  30. phoneValues.put("raw_contact_id",contact_id);
  31. phoneValues.put("data1",phone);
  32. getContentResolver().insert(dataUri,phoneValues);
  33. ContentValues emailValues = new ContentValues();
  34. emailValues.put("mimetype","vnd.android.cursor.item/email_v2");
  35. emailValues.put("raw_contact_id",contact_id);
  36. emailValues.put("data1",email);
  37. getContentResolver().insert(dataUri,emailValues);
  38. }

7、内容观察者(了解)
    需求:如果provider的内容被修改了,那么第三个应用要立刻知道,这个就是内容观察者
 【1】  在完成数据库的操作后,发送给一个消息
    
    
  1. getContentResolver().notifyChange(uri,null);

 【2】  然后在想要接收提醒的应用中写
   
   
  1. getContentResolver().registerContentObserver(uri,true,new MyContentObsever(new Handler()));
    意图里面可以传序列化对象,serializerable(序列化存储)和parcelable(序列化到内存)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值