您的位置:首页 > 编程语言 > PHP开发

ContentProvider(内容提供者)以及自定义ContentProvider

2016-09-07 15:41 363 查看

ContentProvider(内容提供者)

    1. ContentProvider的作用:  实现程序的数据的共享(因为Android中的程序的数据一般都是私有的 [如数据库], 如果有一个应用程序所管理的数据具有共性, 就可以通过ContentProvoider把这些共性的数据共享,让别的应用程序可以访问)
                                                在provider中没有数据,他只是扮演中间的共享层,数据还是存储在数据库中.
                                                在Android系统中已经存在一些通过ContentProvider共享的数据(联系人,短信记录, 通话记录)
    2.如何访问已经被共享的数据库:   通过ContentResolver实现访问
 [访问数据的程序端可称为访问端或者客户端]

    3.如何指定ContentResolver访问哪一个ContentProvider共享的数据:
 Content  Uri

以上三者的关系:  ContentProvider  用于共享一个数据(数据库),
 ContentResolver用于查询ContentProvider 所共享的数据库
                            Uri是ContentResolver和ContentProvider之间的连接桥梁(通过Uri指定ContentResolver访问的是哪一个ContentProvider)

通过ContentResolver实现查询已经存在的被ContentProvider共享数据库:
           查询系统通话记录:
                存放通话记录的数据库的存储位置: data/data/com.android.providers.contacts/databases/contact2.db
                数据库中的calls表存放的通话记录
                calls表中  number列: 存放电话号码
                                duration列:
 存放通话时长(秒)
                                date列:通话日期(年,月,日)
                                type列: 存放通话的类型
 1.来电    2.去电    3.未接
               
  添加查询的权限:  android.permission.READ_CONTACTS

        //获取数据访问端
        resolver= getContentResolver();
        //通过访问端的查询方法, 去查询ContentProvider所共享的通话记录数据库
        //参数一:指定访问的是哪张表   参数二:指定该表中的那些列  
  参数三参数四:where子句     参数五:查询到的结果的排序(asc 升序   desc  降序)
        resolver.query(CallLog.Calls.CONTENT_URI,
new String[]{"number",  "date",  "duration",  "type"},null,null,null);

查询短信记录:
    存放短信记录的数据库的位置:  data/data/com.android.providers.telephony/databases/mmssms.db
    该数据库中的sms表存放的是短信记录
    sms表的表结构: address列:存放电话号码
                               date列:存放短信记录产生的日期
                               type列:存放短信的类型
    数字1表示->收件  数字2表示->发件     数字3表示->草稿
                               body列: 存放的是短信的内容
    访问短信记录的Uri:  content://sms     访问所有短信记录的Uri
 
                                       content://sms/inbox
 访问收件箱的短信记录Uri
                                       content://sms/sent
  访问收件箱短信记录的Uri
                                       content://sms/draft
  访问草稿箱的短信记录的Uri
   
查询短信记录需要添加权限: android.permission.READ_SMS
          写的权限:  write
    查询联系人的相关信息
        存放联系人的信息的数据库的位置:data/data/com.android.providers.contacts/datab
ases/contacts2.db
        在contacts2.db数据库中有三张表示用来存放联系人的信息,分别为:
        1.  contacts表  (用ContactsContract.RawContact类表示该表)
                该表存放的是联系人的大体信息.可以理解为raw_contacts的副本
       
1106c
2.  data表(用ContactsContract.RawContact类表示该表)
                该表存放联系人的字段(电话号码, 邮箱, 姓名)信息.该表的表结构:
                    mimetype_id列:当前行的大的数据类型(1.
邮箱   5. 电话号码   6.姓名)
                    raw_contact_id列:   存放联系人的id
                    data1列:一个字段信息(电话号码,  邮箱,
 姓名)
                    data2列:data1列的备注   data1列存的是电话号码或者邮箱,则data2列是表类型的值(1.表示家庭
  ,  2.表示工作)  data1列如果是姓名则data2列存放的是姓
                    date3列:如果data1列存放的是电话或者邮箱则data3列没有数据,如果data1列存的是姓名,data3存的是名

        3.  raw_contacts (用ContactsContract.RawContact类表示该表)
                该表存放联系人的核心信息.该表中有联系人的ID编号(contact_id列),联系人的姓名(display_name列)
                通过系统API方法实现对联系人数据的CRUE操作:
                        ContactsContract类->定义联系人相关的内容(如,
表示存放联系人表的类,  存放联系人的表的Uri , 数据类型)

        //借助数据访问端执行查询全部短信
        //按日期的升序
        resolver.query(Uri.parse(SmsUri.allSms),new
String []{"address", "date", "type", "body"},null, null, "date

        //遍历查询到的cursor将日期和类型值进行转换
        private void  curso2List(Cursor cursor,
List<HashMap<String, String>> dataList){
            while(cursor.moveToNext()){
                //获取查询到的结果集中的电话号码
                String address=cursor.getString(cursor.getColumnlndex("address"));
                //将字符型的数据转换为整型数据(在转日期型格式时)
                  String dateStr=  dateFormat.format(new
Date(Long.parseLong(date)));
    }
}
getLastPathSegment();//获取uri中最后一个值

自定义ContentProvider

        在Android系统中会提供一个ContentProvider类, 该类的作用把一个数据库文件共享出去,别的应用程序就可以通过数据访问端(ContentResolver)访问该ContentProvider共享的数据库.
        
        该类是一个抽象类,该抽象类中会有一系列的相关方法, 通过这些抽象方法可以把数据库的增,删,改,查的操作暴露出去
         如果说自己的应用程序需要把自己的数据库暴露出去,就可以在自己的程序中定义ContentProvider的子类,实现该抽象父类的相应方法:
        1.  insert()           对被 暴露的数据库实现插入的操作
        2.  delete();            对被暴露的数据库实现删除操作
        3.  update();            对被暴露的数据库实现更新操作
        4.  query();                对被暴露的数据库实现查询的操作
        5.  oncreate();               表示ContentProvider(内容提供者)对象被创建[可以在该方法调用的时候执行初始化的工作-->创建数据库]该方法只会在第一次安装该应用程序的时候调用,以后无论打开多少次均不会在调用
        6.  getType()                    获取一个Uri所表示的数据的类型[数据是一条还是多条]
            以上6个方法中的前5个是由系统调用,最后一个方法是由自己调用.
            被系统自动调用的5个方法的调用时机:  对于insert()   delete()   update()   query()的调用时机-->调用数据访问端(ContentResolver对应的增,
删  改, 查方法的时候        
                                                                              对于onCreate()的调用时机->当应用程序被安装在手机上

Content  Uri的格式:  1. 协议头   Content://
                                  2. 授权(authorities)
      一个字符串. 可以理解成数据库的访问密码
                                  3. 数据路径
                  被访问的表的表名
                                    完整格式:
   content://authorities/数据的路径(TABLE_NAME)

ContentProvider 的代码实现:
创建数据库首先要创建一个子类去继承  SQLiteOpenHelper
    创建数据库  db.execSQL("create table student_info(_id
 integer  primary key  autoincrement, name  text,  score integer));

再创建一个子类继承ContentProvider父类,实现父类的抽象方法  是为了把创建的数据库暴露出去 
1. 而且需要注册ContentProvider  :< provider  android:name="
包名加类名">
2. 在配置文件中进行注册
    [在<application>标签和<activity>标签平级的位置添加<provider>标签]
    [在<provider>标签中通过android:name属性指定ContentProveier,通过android:authorites属性为注册的ContentProvider配置授权码
 通过android:exported属性指定ContentProvider对外暴露]

      String dataPath=  uri.getLastPathSegment();//获取数据访问端传入的数据的存储路径

UriMatcher类
        该类的作用:用来匹配Uri.
                            匹配的时候  # 作为数字的通配符
      *作为文本的通配符   [文本包含数字]
        该类的使用方法: 创建该类的对象,往这个类中添加用于匹配的Uri[调用addUri方法实现].这些用于匹配的Uri会按照的顺序以树的结构进行存储,当传入的某一个Uri和UriMatcher类中添加的Uri匹配成功则匹配结束.当匹配成功会返回一个整数用于表示被匹配的Uri的类型

使用方法:
            //添加静态代码块
    static{
            //创建UriMatcher对象,该对象用来存放用于匹配的Uri
            //构造方法的参数是根节点匹配成功的返回值,因为根节点没有存放Uri,
所以根节点是不会参与匹配的
        UriMatcher matcher =new  UriMatcher(UriMatcher.NO_MATCH);
            //参数一:ContentProvider 的授权码    参数二:数据的路径(具体到某一行)
    参数三:匹配成功后的返回值(可以用来作为该种类型Uri的类型值)
        matcher.addURI(authority,"student_info/#",1);//通配后面是数字的所有的Uri
        matcher.addURI(authority,"student_info/*",2);//通配所有的后面是文字的Uri
        [b]matcher.addURI(authority,"student_info",3);//只能匹配不带后缀的Uri[/b]
    }
    
    //数据库的查询方法的参数:
    //参数一:  操作的表名
    //参数二:想要的列的列表
    //参数三: where子句
    //参数四: where子句中占位符的值
    //参数五:    SQL 语句中的group by子句[根据某一列对查询的结果进行分组]
    //参数六:  SQL语句中的having子句[对分组的结果进行条件过滤]
    //参数七:  SQL 语句中的order by 子句[对查询的结果按照某一列进行升序或者降序排列]
    db.query("studnet_info",projection,selection,

SUM(score):对score求和
group by 列名: 根据指定的列队结果进行分组
分组求和的SQL语句: select 列名1, 列名2, ....SU(M被求和的列名)
 from 表名  group by  按什么分组的列名;
对分组求和的结果进行过滤:  select  列名1, 列名2,.....SUM(被求和的列名5),....
from 表名  group by 列名having  SUM(被求和的列名5);

{Uri
baseUri = Uri.parse(content_uri);
 
 Uri updateUri = Uri.withAppendedPath(baseUri, updateName);//意识是吧updateName填在baseUri后面}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: