美文网首页
ContentProvider

ContentProvider

作者: 学不好语文的LJ码农 | 来源:发表于2016-12-10 13:57 被阅读31次

    以下内容整理自互联网,仅用于个人学习


    1. ContentProvider介绍

    ContentProvider(内容提供者)是Android的四大组件之一,管理android以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他程序调用。

    2. URI

    URI(统一资源标识符)代表要操作的数据,可以用来标识每个ContentProvider,这样你就可以通过指定的URI找到想要的ContentProvider,从中获取或修改数据。

    Android中URI的格式:
    content://com.example.app.provider/table/1

    • content://: schema,已经由Android所规定为:content://
    • com.example.app.provider:权限(Authority),是URI的授权部分,是唯一标识符,用来定位ContentProvider。
    • table:指向一个对象集合,一般用表的名字,如果没有指定后面“1”部分,则返回全部记录。
    • 1:指向特定的记录。

    通配符:

    *:匹配的任意长度的任何有效字符的字符串。
    #:匹配的任意长度的数字字符的字符串。

    content://com.example.app.provider/* 匹配provider的任何内容uri
    content://com.example.app.provider/table1/# 匹配table3的所有行

    MIME

    MIME是指定某个扩展名的文件用一种应用程序来打开,就像你用浏览器查看PDF格式的文件,浏览器会选择合适的应用来打开一样。Android中的工作方式跟HTTP类似,ContentProvider会根据URI来返回MIME类型,ContentProvider会返回一个包含两部分的字符串。

    • text/html
    • text/css
    • text/xml
    • application/pdf

    一个内容URI所对应的MIME字符串主要由三个部分组成,Android对这三个部分做了格式规范:

    1. 必须以vnd开头
    1. 如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则接android.cursor.item/
    2. 最后接上vnd.<authority>.<path>

    每个内容类型的Android MIME类型有两种形式:多条记录(集合)和单条记录。

    //集合记录 
    vnd.android.cursor.dir/自定义 
     
    //单条记录  
    vnd.android.cursor.item/自定义
    

    vnd表示这些类型和子类型具有非标准的、供应商特定的形式。Android中类型已经固定好了,不能更改,只能区别是集合还是单条具体记录,子类型可以按照格式自己填写。

    Android系统提供了两个用于操作Uri的工具类:ContentUris和UriMatcher。

    ContentUris

    ContetnUris包含一个便利的函数withAppendedId()来向URI追加一个id。

    Uri uri = Uri.parse("content://cn.scu.myprovider/user") 
    Uri resultUri = ContentUris.withAppendedId(uri, 7);  
    //生成后的Uri为:content://cn.scu.myprovider/user/7
    

    同时提供parseId(uri)方法用于从URI中获取ID

    Uri uri = Uri.parse("content://cn.scu.myprovider/user/7") 
    long personid = ContentUris.parseId(uri); 
    //获取的结果为:7
    

    UriMatcher

    UriMatcher本质上是一个文本过滤器,用在contentProvider中帮助我们过滤,分辨出查询者想要查询哪个数据表。

    使用UriMatcher主要步骤:

    1. 初始化
    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 
    //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
    
    1. 注册Uri
    //USER 和 USER_ID是两个int型数据 
    matcher.addURI("cn.scu.myprovider", "user", USER); 
    matcher.addURI("cn.scu.myprovider", "user/#",USER_ID); 
    //如果match()方法匹配content://cn.scu.myprovider/user路径,返回匹配码为USER
    
    1. 匹配已经注册的Uri
    /*  
     * 如果操作集合,则必须以vnd.android.cursor.dir开头  
     * 如果操作非集合,则必须以vnd.android.cursor.item开头  
     * */   
    @Override   
    public String getType(Uri uri) {   
    Uri uri = Uri.parse("content://" + "cn.scu.myprovider" + "/user");   
        switch(matcher.match(uri)){   
        case USER:   
            return "vnd.android.cursor.dir/user";   
        case USER_ID:   
            return "vnd.android.cursor.item/user";   
        }   
    }
    

    3. ContentProvider的主要方法

    //ContentProvider创建后或打开系统后其它应用第一次访问该ContentProvider时调用。 
    public boolean onCreate() 
     
    //外部应用向ContentProvider中添加数据。 
    public Uri insert(Uri uri, ContentValues values) 
       
    //外部应用从ContentProvider删除数据。 
    public int delete(Uri uri, String selection, String[] selectionArgs) 
     
    //外部应用更新ContentProvider中的数据。 
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs): 
     
    //供外部应用从ContentProvider中获取数据。 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,  
                        String sortOrder)  
       
    //该方法用于返回当前Url所代表数据的MIME类型。 
    public String getType(Uri uri)
    

    4. ContentResolver

    ContentResolver通过URI来查询ContentProvider中提供的数据。除了URI以 外,还必须知道需要获取的数据段的名称,以及此数据段的数据类型。如果你需要获取一个特定的记录,你就必须知道当前记录的ID。

    //添加 
    public Uri insert(Uri uri, ContentValues values)  
    //删除 
    public int delete(Uri uri, String selection, String[] selectionArgs)  
    //更新 
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)  
    //获取 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
    

    示例代码

    ContentResolver resolver =  getContentResolver(); 
    Uri uri = Uri.parse("content://cn.scu.myprovider/user"); 
     
    //添加一条记录 
    ContentValues values = new ContentValues(); 
    values.put("name", "fanrunqi"); 
    values.put("age", 24); 
    resolver.insert(uri, values);   
     
    //获取user表中所有记录 
    Cursor cursor = resolver.query(uri, null, null, null, "userid desc"); 
    while(cursor.moveToNext()){ 
       //操作 
    } 
     
    //把id为1的记录的name字段值更改新为finch 
    ContentValues updateValues = new ContentValues(); 
    updateValues.put("name", "finch"); 
    Uri updateIdUri = ContentUris.withAppendedId(uri, 1); 
    resolver.update(updateIdUri, updateValues, null, null); 
     
    //删除id为2的记录 
    Uri deleteIdUri = ContentUris.withAppendedId(uri, 2); 
    resolver.delete(deleteIdUri, null, null);
    

    5. ContentObserver

    ContentObserver(内容观察者),目的是观察特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。

    下面给出一个监听短信的例子

    public class MainActivity extends Activity { 
     
        @Override 
        protected void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.activity_main); 
     
    //注册观察者Observser     
    this.getContentResolver().registerContentObserver(Uri.parse("content://sms"),true,new SMSObserver(new Handler())); 
     
        } 
     
        private final class SMSObserver extends ContentObserver { 
     
            public SMSObserver(Handler handler) { 
                super(handler); 
     
            } 
     
     
            @Override 
            public void onChange(boolean selfChange) { 
     
     Cursor cursor = MainActivity.this.getContentResolver().query( 
    Uri.parse("content://sms/inbox"), null, null, null, null); 
     
                while (cursor.moveToNext()) { 
                    StringBuilder sb = new StringBuilder(); 
     
                    sb.append("address=").append( 
                            cursor.getString(cursor.getColumnIndex("address"))); 
     
                    sb.append(";subject=").append( 
                            cursor.getString(cursor.getColumnIndex("subject"))); 
     
                    sb.append(";body=").append( 
                            cursor.getString(cursor.getColumnIndex("body"))); 
     
                    sb.append(";time=").append( 
                            cursor.getLong(cursor.getColumnIndex("date"))); 
     
                    System.out.println("--------has Receivered SMS::" + sb.toString()); 
      
                } 
            }  
        } 
    }
    

    同时可以在ContentProvider发生数据变化时调用 getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者。

    public class UserContentProvider extends ContentProvider { 
       public Uri insert(Uri uri, ContentValues values) { 
          db.insert("user", "userid", values); 
          getContext().getContentResolver().notifyChange(uri, null); 
       } 
    }
    

    相关文章

      网友评论

          本文标题:ContentProvider

          本文链接:https://www.haomeiwen.com/subject/cznymttx.html