当前位置:   article > 正文

Android的内容观察者、通知、内容提供者_安卓开发内容提供者 查询网络接口数据 返回给观察者

安卓开发内容提供者 查询网络接口数据 返回给观察者
一、内容提供者的作用
1. 应用成需创建的数据库文件,默认都是私有的,其他应用程序不具备读写权限
2. 如果真的想把自己的数据库数据暴露给其他程序访问,那么就应该通过内容提供者来暴露。
3. 与aidl有点类似,但不太一样,aidl是提供内存中的数据给其他应用访问,内容提供者是提供磁盘中的数据给其他应用访问。

二、使用内容提供者的步骤
1. 自定义一个类,继承ContentProvider
public class Backdoor extends ContentProvider {}
2. 注册,要添加主机名
  1. <!-- authorities 它就相当于是一个口令,外部应用如果想操作这个内容提供者,
  2. 为他干活,必须要与内容提供者的口令一致才可以。 -->
  3. <provider android:name="com.itheima.db.Backdoor"
  4. android:authorities="com.itheima.db.BANK"></provider>
3. 定义一个Uri匹配器
  1. /**
  2. * 由于应用程序一安装,就会把程序中的内容提供者口令发布出来,为了提高数据的安全性, 所以必须对来访的uri(口令),做一些匹配规则过滤一下。
  3. */
  4. // 定义一个uri的匹配器,指定里面如果传递过来的uri,一旦没有匹配,将返回的int值 -1
  5. static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
4. 预设一些匹配规则
  1. static {
  2. // 一开始就给这个匹配器预设一些匹配规则,如果传递过来的uri
  3. // 匹配了authority 和 path ,那么将返回后面的匹配码
  4. //数据库里面有可能有多张表,为了规范匹配规则,path一般都写表名,根据表的名字来判定
  5. //当前访问的是哪个表的数据 ,如果有多张表,并且还想把这些所有表都暴露出来,那么这个匹配规则
  6. //就应该写多条语句了。并且注意返回的code不能一样。
  7. matcher.addURI("com.itheima.db.BANK", "account", 200);
  8. // matcher.addURI("com.itheima.db.BANK", "stu", 201);
  9. }
5. 编写CRUD方法
  1. @Override
  2. public int delete(Uri uri, String selection, String[] selectionArgs) {
  3. // 使用uri匹配去去过滤传递过来的uri口令,如果匹配成功,将返回200,否则将返回 -1
  4. int code = matcher.match(uri);
  5. if (code == 200) {
  6. System.out.println("delete---");
  7. Db db = new Db(getContext());
  8. SQLiteDatabase data = db.getWritableDatabase();
  9. data.delete("account", selection, selectionArgs);
  10. } else {
  11. throw new IllegalArgumentException("口令错误,滚犊子~~");
  12. }
  13. return 0;
  14. }
6. 在其他应用操作内容提供者
  1. public void insert(View v) {
  2. // 其他应用通过内容提供者 content provider 暴露数据
  3. // 本应用想操作内容提供者---内容解析者
  4. // 1.通过上下文得到内容解析者
  5. ContentResolver resolver = getContentResolver();
  6. // 2. 要访问内容提供者,必须要指定口令
  7. // 由于内容提供者省级了口令,既有主机名也有path路径,所以这里为了能够匹配成功
  8. // 必须加上主机名还有path路径名
  9. Uri uri = Uri.parse("content://com.itheima.db.BANK/account");
  10. //定义要插入的数据
  11. ContentValues values = new ContentValues();
  12. values.put("name", "zhangsan");
  13. values.put("money", 5000);
  14. // 3.调用内容提供者中的添加方法
  15. resolver.insert(uri, values);
  16. }

三、学习内容提供者的目的
1. 一般在开发当中都不会把自己的数据暴露出来,也就是编写自定义的内容提供者的几率非常之小。
2. 去访问系统应用暴露出来的数据,如:备份来联系人和备份短信

四、添加和删除短信
* 添加短信
  1. //添加短信
  2. public void insert(View v) {
  3. ContentResolver resolver = getContentResolver();
  4. //定义口令,这个口令,通过查看上层应用中的provider中的TelephonyProvider 这个应用中清单文件和源代码
  5. Uri uri = Uri.parse("content://sms");
  6. ContentValues values = new ContentValues();
  7. values.put("address", "110");
  8. values.put("date", System.currentTimeMillis());
  9. values.put("type", 1);
  10. values.put("body", "您好,尊敬的覃先生:恭喜您荣获好市民奖,希望您在以后的生活中,勇于和敢于扶老奶奶过马路。");
  11. //操作短信的添加方法
  12. resolver.insert(uri, values);
  13. }
* 删除短信
  1. //删除短信
  2. public void delete(View v) {
  3. ContentResolver resolver = getContentResolver();
  4. //定义口令,这个口令,通过查看上层应用中的provider中的TelephonyProvider 这个应用中
  5. //清单文件和源代码
  6. Uri uri = Uri.parse("content://sms");
  7. resolver.delete(uri, "address=?", new String[]{"110"});
  8. Toast.makeText(this, "删除短息成功", 0).show();
  9. }
五、界面提醒
1. Toast
2. Dialog-对话框
3. notification -- 通知

> 通知是运行在另外一个进程中 , systemui
  1. //发送通知
  2. public void send(View v){
  3. /*
  4. * 高版本
  5. * //1.得到通知管理者
  6. NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  7. //2.定义一个notification的构建器,通过这个构建器去定义通知的一些属性
  8. Notification noti = new Notification.Builder(this)
  9. .setContentTitle("这是标题")
  10. .setContentText("这是文本内容")
  11. .setSmallIcon(R.drawable.ic_launcher)
  12. .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher))
  13. .build();
  14. //2.发送一个通知 , 指定通知的id,还有通知的对象
  15. manager.notify(1, noti);
  16. *
  17. *
  18. */
  19. //低版本
  20. NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
  21. Notification notification = new Notification(
  22. R.drawable.ic_launcher, //小图标
  23. "您有一条新的未读消息", // 在状态栏上翻动显示的文本
  24. System.currentTimeMillis()); //短信发送的时间
  25. Intent intent = new Intent();
  26. intent.setAction(Intent.ACTION_CALL);
  27. intent.setData(Uri.parse("tel://10086"));
  28. //指定点击通知之后,跳转一个界面
  29. PendingIntent pIntent = PendingIntent.getActivity(
  30. this,
  31. 1, //请求码
  32. intent, //跳转的意图
  33. 0);//可选的标记
  34. //设置拖动通知下来之后,展示的内容以及点击之后跳转到的界面
  35. notification.setLatestEventInfo(
  36. this,
  37. "这是标题",
  38. "这是文本",
  39. pIntent);
  40. manager.notify(2, notification);
  41. }

六、联系人的内容提供者
6.1 查询联系人
> 1. 查询raw_contacts表,得到contact_id
> 2. 根据contact_id,去查询 data1, mimetype类型

6.2 删除联系人
> 删除联系人后,发现并不是真的从数据库中把这条记录给移除,而是把contact_id置为null而已,
Android之所以这么做,是为了日后联网同步所考虑的。

6.3 添加联系人
> 先查询raw_contacts表,获取到当前的最新_id
  1. //添加一条联系人记录
  2. ContentResolver resolver = getContentResolver();
  3. //2定义查询raw_contact表的uri
  4. Uri contactUri = Uri.parse("content://com.android.contacts/raw_contacts");
  5. //查询data表的uri
  6. Uri dataUri = Uri.parse("content://com.android.contacts/data");****
  7. //由于不知道当前的contact_id已经走到了多少,所以不能盲目直接编写,应该去查询
  8. //该表中的_id列,然后倒序排列,取第一条就可以了。
  9. Cursor cursor = resolver.query(contactUri, new String[]{"_id"}, null, null, "_id desc");
  10. cursor.moveToFirst();
  11. int id = cursor.getInt(0)+1; //在原来的id基础上+1 ,形成了现在新添加的id
  12. > 在它基础上+1 ,得到现在要往数据库添加的新raw_contact_id
  13. ContentValues values = new ContentValues();
  14. values.put("contact_id", id);
  15. resolver.insert(contactUri, values);
  16. > 最后往data表里面添加 姓名、电话、邮箱...
  17. //往data表里面添加数据
  18. //添加姓名
  19. ContentValues nameVal = new ContentValues();
  20. nameVal.put("data1", et_name.getText().toString()); //添加姓名
  21. nameVal.put("raw_contact_id", id); //添加这个数据属于谁的uri
  22. nameVal.put("mimetype", "vnd.android.cursor.item/name"); //指定添加的数据属于什么类型
  23. resolver.insert(dataUri, nameVal);//插入记录
七、内容观察者
> 内容观察者实际上就是当数据的数据发生了改变之后,发布出来一个通知,如果有哪一个内容观察者
> 在观察这个uri对应的路径,那么就会收到这个通知
* 发布通知
  1. // 对外发布一个通知,告诉其他人,这个uri对应的数据已经发生了改变。如果第二个参数不是null,
  2. //那么在此指定的这个内容观察者将会收到这个通知,如果是null,代表的是不会直接报告给某一个内容观察者,
  3. //仅仅是发出来一个通知,如果有关心这个通知,那么久能知道事件的发生
  4. getContext().getContentResolver().notifyChange(uri, null);
注意:发布通知这个事件不一定在内容观察者里面执行,也可以在数据库操作完成之后执行。
* 注册一个内容观察者
  1. Uri uri = Uri.parse("content://com.itheima.db.BANK/account");
  2. //注册一个内容观察者,让他观察指定的uri, 如果这个uri的数据发生了改变,那么将会得到通知
  3. getContentResolver().registerContentObserver(
  4. uri, //观察指定的uri
  5. true, // 如果是true, 代表只要前面的uri能够匹配成功,那么就会收到通知,如果是false代表的时候
  6. //要所有的路径都完全匹配
  7. new ContentObserver(new Handler()) {
  8. //一旦这个uri对应的数据发生了改变,那么这个方法将会被调用.
  9. @Override
  10. public void onChange(boolean selfChange) {
  11. System.out.println("来人啊,银行行长又来偷钱了。。。");
  12. }
  13. });
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号