Android - 内容提供者

1.谷歌为什么研发内容提供者

   1.activity 代表页面  2.广播接收者.外拨电话事件 方便程序员开发更多的应用程序.3.service:播放音乐 4.内容提供者:暴漏私有的数据库给其他应用使用.
   2.chmod 777 itheima.db 修改文件权限 

2.内容提供者工作原理

   
    代码实现
    1.在应用1的内部定义一个内容提供者 
     URI:统一资源标示符   也表示一个路径  这个路径可以自己定义 
     URL:统一资源定位符    www.baidu.com
     2.在内容提供者内部定义一个urimatcher  并且定义一个静态代码块添加匹配规则 
 
 
  1. //1.定义一个urimatcher(路径匹配器)
  2. private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  3. private static final int QUERYSUCESS = 1;
  4. //2.定义一个静态代码块 特点:随着类的加载而加载 只执行一次.
  5. static {
  6. /**
  7. * 3.添加路径 参数1:要和你清单文件配置参数一样 参数3 匹配码
  8. * http://www.baidu.com/tieba 通过这个路径代表访问百度贴吧
  9. * content://com.itheima/query 定义含义
  10. */
  11. sURIMatcher.addURI("com.itheima","query",QUERYSUCESS);
  12. }
    3.把增删改查方法暴漏出去 
 
 
  1. @Override
  2. public Cursor query(Uri uri, String[] projection, String selection,
  3. String[] selectionArgs, String sortOrder) {
  4. //1.匹配其他应用传递过来的uri路径
  5. int code = sURIMatcher.match(uri);
  6. if (code == QUERYSUCESS){
  7. //2.说明路径匹配成功 把query方法实现 对数据库进行查询操作--->获取sqlteDatabase实例
  8. SQLiteDatabase db = myOpenHelper.getReadableDatabase();
  9. //3.对数据库实现查询操作
  10. Cursor cursor = db.query("info", projection, selection, selectionArgs, sortOrder, null, null);
  11. //4.把cursor返回
  12. return cursor;
  13. }else{
  14. //说明路径匹配失败
  15. throw new IllegalArgumentException("哥们 路径匹配失败");
  16. // return null;
  17. }
  18. }
   4.其他应用程序提供内容解析者操作数据库
 
 
  1. public void click(View view) {
  2. //0.定义Uri
  3. Uri uri = Uri.parse("content://com.itheima/query");
  4. //1.获取内容解析者
  5. Cursor cursor = getContentResolver().query(uri, null, null, null, null);
  6. //2.把张三 李四信息查询出来
  7. if (cursor!=null){
  8. while (cursor.moveToNext()){
  9. String id = cursor.getString(0);
  10. String name = cursor.getString(1);
  11. String phone = cursor.getString(2);
  12. String money = cursor.getString(3);
  13. System.out.println("第二222个应用id:"+id+"----:"+name+"----:"+phone);
  14. }
  15. }
  16. }

  

3.短信备份:

  代码实现过程 
  1.提供内容解析者把短信数据取出来
 
 
  1. {
  2. //0.准备访问短信数据库的uri
  3. Uri uri = Uri.parse("content://sms/");
  4. //1.读取短信数据库的内容 由于短信数据库系统已经通过内容提供者暴漏出来 所以我们可以直接通过内容解析者来查询数据库
  5. Cursor cursor = getContentResolver().query(uri, new String[]{"address", "date", "body"}, null, null, null);
  6. //2.把对应的数据取出来
  7. while (cursor.moveToNext()){
  8. String address = cursor.getString(0);
  9. String date = cursor.getString(1);
  10. String body = cursor.getString(2);
  11. System.out.println("address:"+address+"---"+date+"===="+body);
  12. }
  13. }
 2.使用xml序列化把数据保存到xml文件中 
 
 
  1. public class MainActivity extends AppCompatActivity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_main);
  6. }
  7. //点击按钮备份系统短信 --->xml描述数据
  8. public void click1(View view) {
  9. try {
  10. //1.获取一个xml序列化器
  11. XmlSerializer serializer = Xml.newSerializer();
  12. //1.1 通过文件输出流指定文件生成位置
  13. File file = new File(getFilesDir().getPath(),"smsbackup.xml");
  14. FileOutputStream fos = new FileOutputStream(file);
  15. //2.告诉序列化器 生成一个xml文件
  16. serializer.setOutput(fos,"utf-8");
  17. //3.根据xml语法生成xml文件 文档声明
  18. serializer.startDocument("utf-8",true);
  19. //4.生成xml根标签
  20. serializer.startTag(null,"smss");
  21. //5.循环生成子标签 sms标签生成几个 准备访问短信数据库的uri
  22. Uri uri = Uri.parse("content://sms/");
  23. //6.读取短信数据库的内容 由于短信数据库系统已经通过内容提供者暴漏出来 所以我们可以直接通过内容解析者来查询数据库
  24. Cursor cursor = getContentResolver().query(uri, new String[]{"address", "date", "body"}, null, null, null);
  25. //7.把对应的数据取出来
  26. while (cursor.moveToNext()){
  27. String address = cursor.getString(0);
  28. String date = cursor.getString(1);
  29. String body = cursor.getString(2);
  30. //8.生成xml的sms标签
  31. serializer.startTag(null,"sms");
  32. //9.生成address标签
  33. serializer.startTag(null,"address");
  34. serializer.text(address);
  35. serializer.endTag(null,"address");
  36. //10.生成date标签
  37. serializer.startTag(null,"date");
  38. serializer.text(date);
  39. serializer.endTag(null,"date");
  40. //11.生成body标签
  41. serializer.startTag(null,"body");
  42. serializer.text(body);
  43. serializer.endTag(null,"body");
  44. serializer.endTag(null,"sms");
  45. }
  46. serializer.endTag(null,"smss");
  47. serializer.endDocument();
  48. Toast.makeText(this, "备份成功", Toast.LENGTH_SHORT).show();
  49. } catch (Exception e) {
  50. e.printStackTrace();
  51. Toast.makeText(this, "备份失败", Toast.LENGTH_SHORT).show();
  52. }
  53. }

4.生成虚拟短信
 
 
  1. //点击按钮 实现短信还原的逻辑 ---->就是xml解析 把数据解析出来--->插入到短信数据库
  2. public void click2(View view) {
  3. //0.把xml里面的数据解析出来 TODO xml解析的逻辑
  4. //1.由于系统短信数据库 系统已经通过内容提供者暴漏出来 所以我们可以直接通过内容解析者操作数据库
  5. Uri uri = Uri.parse("content://sms/"); //张三 回家 小伙伴
  6. //2.创建一个ContentValues
  7. ContentValues values = new ContentValues();
  8. values.put("address","95555"); //招商银行客服
  9. values.put("date",System.currentTimeMillis());
  10. values.put("body","您好,请的银行卡余额为-500000元");
  11. //3.把数据插入到短信数据库
  12. getContentResolver().insert(uri,values);
  13. }
  14. }

5.查询联系人

 微信 QQ  陌陌....
 联系人相关的三张表 
 1.data表  data1列 存的是联系人所有的信息(包括 电话 邮箱 姓名 地址)
 2.raw_contacts表 contact_id列 表示应用一共有几条联系人
 3.mimetype 表  id字段 用来区分联系人信息 
 查询联系人的步骤 
 [1]先查询 raw_contacts 的contact_id字段  就知道一共有几条联系人 
 [2]在查询data表  先查询data1字段和mimetype_id字段
 Invalid column mimetype_id() :报mimetype_id列无效  1:列名写错了   2.表中没有这列.
 
 
  1. public class QueryContactUtils {
  2. //查询联系人的业务方法
  3. public static List<Contact> getContact(Context context){
  4. List<Contact> lists = new ArrayList<>();
  5. //0.准备查询联系人数据库的路径
  6. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  7. Uri dataUri = Uri.parse("content://com.android.contacts/data");
  8. //1.先查询raw_contacts 的contact_id字段 由于联系人数据库系统已经通过内容提供者暴漏出来 所以我们可以直接通过内容解析者操作数据
  9. Cursor cursor = context.getContentResolver().query(uri, new String[]{"contact_id"}, null, null, null);
  10. while (cursor.moveToNext()){
  11. Contact contact = new Contact();
  12. String contact_id = cursor.getString(0);
  13. System.out.println("contact_id:"+contact_id);
  14. //1.1 把data表中所有的列都查询出来
  15. //2.根据联系人id 取查询data表 data1列和mimetype_id列
  16. Cursor dataCursor = context.getContentResolver().query(dataUri, new String[]{"data1", "mimetype"}, "raw_contact_id=?", new String[]{contact_id}, null);
  17. while (dataCursor.moveToNext()){
  18. String data1 = dataCursor.getString(0);
  19. String mimetype = dataCursor.getString(1);
  20. //3.通过字符串判断data1数据类型
  21. if ("vnd.android.cursor.item/email_v2".equals(mimetype)){
  22. System.out.println("邮箱:"+data1);
  23. contact.setEmail(data1);
  24. }else if ("vnd.android.cursor.item/phone_v2".equals(mimetype)){
  25. System.out.println("电话:"+ data1);
  26. contact.setPhone(data1);
  27. }else if ("vnd.android.cursor.item/name".equals(mimetype)){
  28. System.out.println("姓名:"+data1);
  29. contact.setName(data1);
  30. }
  31. }
  32. lists.add(contact);
  33. }
  34. return lists;
  35. }
  36. }

6.通过内容解析者向联系人数据库插入联系人

插入联系人的步骤
 [1]先往 raw_contacts   表插入数据  更新contact_id
 [2]在往data表里面插入数据 
 
 
  1. {
  2. //2.获取name phone 和 email
  3. String email = et_email.getText().toString().trim();
  4. String name = et_name.getText().toString().trim();
  5. String phone = et_phone.getText().toString().trim();
  6. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  7. Uri dataUri = Uri.parse("content://com.android.contacts/data");
  8. //2.0 插入数据之前 应该先查询一共有几条联系人 数量+1 = contact_id的值
  9. Cursor cursor = getContentResolver().query(uri, null, null, null, null);
  10. int count = cursor.getCount();//获取表中行数
  11. int contact_id = count + 1;
  12. //2.1 通过values更新contact_id字段
  13. ContentValues values = new ContentValues();
  14. values.put("contact_id",contact_id);
  15. //3.把email name phone插入到联系人数据库 由于联系人数据库系统已经通过内容提供者暴漏出来 所以我们可以直接通过内容解析者操作数据库
  16. getContentResolver().insert(uri,values);
  17. //4.先更新name的数据
  18. ContentValues nameVaues = new ContentValues();
  19. nameVaues.put("data1",name); //把name数据更新到data1列
  20. nameVaues.put("raw_contact_id",contact_id); //告诉系统新插入的name属于哪个联系人
  21. nameVaues.put("mimetype","vnd.android.cursor.item/name");
  22. //5.把name 更新到data表
  23. getContentResolver().insert(dataUri,nameVaues);
  24. //6.先更新phone的数据
  25. ContentValues phonoeVaues = new ContentValues();
  26. phonoeVaues.put("data1",phone); //把name数据更新到data1列
  27. phonoeVaues.put("raw_contact_id",contact_id); //告诉系统新插入的name属于哪个联系人
  28. phonoeVaues.put("mimetype","vnd.android.cursor.item/phone_v2");
  29. //7.phone 更新到data表
  30. getContentResolver().insert(dataUri,phonoeVaues);
  31. //8.先更新phone的数据
  32. ContentValues emailVaues = new ContentValues();
  33. emailVaues.put("data1",email); //把name数据更新到data1列
  34. emailVaues.put("raw_contact_id",contact_id); //告诉系统新插入的name属于哪个联系人
  35. emailVaues.put("mimetype","vnd.android.cursor.item/email_v2");
  36. //9.phone 更新到data表
  37. getContentResolver().insert(dataUri,emailVaues);
  38. }

7.内容观察者 

内容观察者不是四大组件. 可以用来观察数据库是否被操作了
   注册内容观察者代码如下:
 
 
  1. public class MainActivity extends AppCompatActivity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_main);
  6. Uri uri = Uri.parse("content://com.itheima/");
  7. //1.注册一个内容观察者 参数2:fase 必须是一个精确uri
  8. getContentResolver().registerContentObserver(uri,true,new MyContentObserver(new Handler()));
  9. }
  10. //定义内容观察者
  11. class MyContentObserver extends ContentObserver{
  12. public MyContentObserver(Handler handler) {
  13. super(handler);
  14. }
  15. //当我们观察的内容发生了改变就会执行这个方法
  16. @Override
  17. public void onChange(boolean selfChange) {
  18. System.out.println("哈哈 我执行了");
  19. super.onChange(selfChange);
  20. }
  21. }
  22. }

8.今天总结 
1.内容提供者工作原理 掌握 
2.内容提供者实现步骤  掌握 ☆ ☆ 
3.短信备份案例  
4.虚假短信  ☆ 
5.查询联系人  ☆ 
6.插入联系人  ☆ 
7.内容观察者 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值