zoukankan      html  css  js  c++  java
  • Android10_内容提供者_内容观察者_标题栏

    安卓四大组件Activity ,Service,BroadCastReceiver,ContentProvider(内容提供者)

    1.1内容提供者的作用:

    应用程序创建的数据库默认都是私有的,别的应用程序不可以访问里面的数据,如果有需求把自己应用程序私有的数据库暴露给别的用户增删改查,就需要使用内容提供者.

    1.2 内容提供者的代码实现

    在需要提供给它人数据的应用中

    ①创建一个项目,并且创建数据库(数据库开启帮助类)(非必要)

    ②创建一个类,继承ContentProvider内容提供者,

    内容提供者,后门程序,提供私有的数据给别的应用程序,默认都是空实现

    配置清单文件<provider name=xxx>报错:如果一个tagprovider,必须添加主机名的属性.

    Android:authorities=”一般写应用程序的包名”//内线的口令,主机名

    在想要获取数据的应用中

    ①找到后门程序,resolver = getContentResolver()//得到内容提供者的解析器

    ②定义uri,Uri uri = Uri.parse(“content://”+主机名,前面是固定写法);

    ContentValues values = new ContentValues();

    resolver.insert(uri,values);//通过内容解析者,让内容提供者添加一条数据

    额外:在继承ContentProvider内容提供者对uri进行解析

    主机名是外界都可以知道的(启动时在日志猫中可以看到ActivityThread,pub主机名)

    ①解析方式通过UriMatcher(uri匹配器)进行解析

    Static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    //采用静态代码块初始化UriMatcher,可以在一开始就判断匹配结果

    mUriMatcher.addURI(主机名,暗号名(String),匹配码(int));

    ③在增删改查的方法里,mUriMatcher.match(uri),返回一个匹配码,可以与在静态代码块中的匹配码进行判断

    throw new XXX异常(“异常信息”);

    ④其它应用程序在指定 uri的时候“content://”+主机名+/暗号(一般写数据库表名)

    1.3 内容提供者中代码的一些注意问题

    ContentProvider中想要获取上下文,直接通过getContext()即可//模拟的上下文

    ②每个方法上对应的

    删除的参数 String selection 筛选的条件String[] selectionArgs 执行的参数

    添加的参数values,增加的内容

    查询的参数 projection(查询的列),selection(where语句)selectionArgs(对应的参数)

    sortOrder以什么排序,这个方法返回一个Cursor,不要在查询操作里关闭数据库,否则会提示错误,数据被提前关闭了.

    修改的方法:values(修改的值),selection(where条件),selectionArgs(where条件对应的参数)

    1.4内容提供者的编写流程

    ①写一个类继承内容提供者,实现增删改查的方法

    ②配置清单文件ContentProvider,指定authortites主机属性

    ③在内容提供者的代码内部,声明UriMatcher匹配规则

    ④通过uriMatcher坚持uri路径是否正确

    ⑤在另一个应用程序里,通过ContentProvicer增删改查.

    1.5 学习内容提供者的目的

    实际开发中,内容提供者很少编写,因为这些数据根本不想让别人看到,而且还进行加密操作,一般只有一些大公司想要打造平台的时候,会对外暴露一部分数据库来给开发者使用.

    额外,短信,联系人应用可以通过内容提供者读取

    2.利用内容提供者对短信进行增加和删除操作

    通过数据库的操作,会在通知栏中显示

    2.1短信数据库中,sms表单,type属性,1,是自己发送给别人,2是别人发送给自己

    Address 发件人地址, data发送时间,body短信内容

    默认权限是对外私有的,但是它是com.android.provider下的程序,是有内容提供者暴露的.

    2.2 查看短信的顶层源代码,可以通过清单文件获取主机名”sms”

    查看SmsProvider的源代码可以看到具体的匹配规则,如果不加暗号,就是获取所有信息.

    额外:需要获取权限READ_SMS WRITE_SMS读写信息

    3.通知栏的提醒

    界面提醒方式:Toast,对话框,通知栏

    通知栏显示的位置是在Systemui进程中(可以看做是进程间的通讯?)

    ①获取系统服务NotificationManagger nm = getStreamService(NOTIFIACTION_SERVICE);

    nm.notify(id,notification);

    Id:通知信息的编号

    Notification:通过notification.builder获取,消息栏的类

    版本支持的获取是从api16开始的,4.0以上版本才可以使用

    ③向下兼容的写法:

    先获取NotificationManager对象

    创建Notification对象 = (图片资源,文本,时间);

    //设置通知的点击事件

    notification.setLatestEventInfo(context,contentTItle,contentText,contentIntent);

    contentTitle 大的标题

    contentText 大的文本

    contentIntent:PendingIntent:用来描述一个动作和它的意图,这个类是以个延期的意图

    实现了Parcelable接口,对象实现了Parcelable才能在进程之间传递

    contentIntent = PendingIntent.getActivity(上下文,请求码0即可,intent,flags(0即可))

    //设置通知的声音

    Notification.defaults = notification.DEFAULT_SOUND

    //设置打电话的意图

    Intent.setAction(Intent.ACTION_CALL);

    intent.setData(Uri.parse(tel://110));

    //但是没有拨打成功,需要添加权限CALL_PHONE

    //设置打开信息的意图

    Intent intent = new Intent();

    intent.setAction("android.intent.action.MAIN");

    intent.addCategory("android.intent.category.DEFAULT");

    intent.setType("vnd.android.cursor.dir/mms");

    4.联系人的内容提供者

    联系人数据库所在的位置: com.android.providers.contacts

    4.1联系人数据库的表结构:

    打开表的时候会有错误,是因为有一些视图表在外部的工具打开的时候不会刷新,不影响开发.

    用到的表有:

    raw_contact:联系人的ID

    Contact_id列保存联系人的id

    data:联系人的数据表

    Raw_contact_id 表示属于哪个联系人

    Data1具体的数据

    Mimetype_id代表数据的类型

    mimetype:联系人数据类型表,对照它可以查询联系人的数据表

    要想查询练习人的信息

    ①查询raw_contact,获取联系人的Contact_id

    ②根据contact_id查询Data,查询联系人的数据

    ③根据mimetype确定数据的类型

    5.1代码实现访问联系人数据库

    当主机名用;号分割的时候,contacts;com.androdi,contacts.用前后哪一种都可以.

    在系统源码中查找匹配规则,可以查询UriMatcher

    需要权限:READ_CONTACTS

    cursor记得关闭掉

    Mimetype_id这一列在真正查询的时候,查询的不是 data,而是view_data,所以在取数据的时候要直接在data表中查memetype,而不是mimetype_id.

    在真机上有可能查不出来,因为有的定制机把表的字段名给改了,所以要考虑到机型的适配.

    5.2 获取联系人数据的工具方法

    ①分包:domain(封装联系人数据),utilsbao(实现具体的业务逻辑)

    ②把联系人从数据库读取出来,封装到集合里即可

    5.3 删除联系人的细节问题

    删除联系人之后,再查询联系人数据库会报不合法的参数异常

    因为安卓有网络,本地保存联系人的保存方式,本地删除了,也会删除网络上的联系人列表.当本地的联系人被删掉了之后,会把联系人的ID保存为null,因为如果这时候网络不好,那么网络保存的联系人信息就没有删掉,所以谷歌就把删除的联系人ID保存为null.等有网同步联系人列表的时候,只需要把为null的信息再网络上删掉即可,而不是把所有联系人跟网络保存的联系人进行一一匹配.

    5.4 添加联系人

    ①获取输入的联系人姓名,电话,邮箱

    ②获取内容提供者相关信息uri,ContentValues,ContentResolver

    ③获取raw_contacts表中最大的id

    ④添加id为最大的id+1,最后再向data表中添加对应的数据即可,

    排序_id desc 降序排列

    必须指定的列名称有id,mimeType,data1

    行结构id   data1  mimeType

    练习人每一条属性都代表data表中的一行

    ⑤添加读写联系人的权限

    6.内容观察者(高版本的广播接收不到信息,可以通过内容观察者监听)

    ①可以看做是内容提供者的监听?

    ②在内容提供者中,通知内容观察者数据发生了变化,null就是保存下来,不为null就是创建对象立即汇报,实现方式getContext().getContentResolver().notifyChanger(uri,null)

    ③在需要获知内容观察者的代码中:

    注册内容观察者

    getContentResolver().regiterContentObserver(uri,notifyForDestor,observer);

    第二个参数:需要uri匹配的前面数据(配置清单的路径)满足为true,需要全满足(含匹配规则)false

    第三个参数 new ContentObserver(new xxx里面有一个onChange的方法(需要自己去重写)观察数据变化);

    应用场景:需要观察短信的变化,用以备份或还原

    7.练习:利用短信内容提供者,开发短信备份与还原的应用

  • 相关阅读:
    ubuntu16.04自动删除内核
    禅道服务数据的迁移
    k8s常用命令3
    使用logstash迁移es集群数据
    es集群迁移脚本
    helm常用命令1
    【操作】python2升级到python3
    【推荐】构建脚本之shell编写规范
    【推荐】linux使用zip命令
    Sublime使用大全
  • 原文地址:https://www.cnblogs.com/adventurer/p/5551515.html
Copyright © 2011-2022 走看看