抓根宝

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

安卓四大组件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.练习:利用短信内容提供者,开发短信备份与还原的应用

 

posted on 2016-06-01 23:33  抓根宝  阅读(995)  评论(0编辑  收藏  举报