美文网首页
android contentProvider

android contentProvider

作者: MrMagicWang | 来源:发表于2016-08-22 22:52 被阅读105次

    除了共享内存(SDCard)的数据外,其他包括SQLite、SharedPreferences都是仅限于被当前所创建的应用访问,而无法使它们的数据在应用程序之间交换数据,所以Android提供了ContentProvider,ContentProvider具有以下特点:

    • 应用程序间共享数据的一种方式
    • 为存储和获取数据提供统一接口
    • android为一些常见的数据提供了ContentProvider:
      • Browser:存储如浏览器的信息。
      • CallLog:存储通话记录等信息。
      • Contacts:存储联系人等信息。
      • MediaStore:存储媒体文件的信息。
      • Settings:存储设备的设置和首选项信息。
    ContentProvider可以理解为一个Android应用对外开放的接口, 只要是符合它所定义的Uri格式的请求,均可以正常访问执行操作。
    访问ContentProvider

    ContentProvider 实例通过处理来自其他应用的请求来管理对结构化数据集的访问。所有形式的访问最终都会调用 ContentResolver,后者接着调用ContentProvider的具体方法来获取访问权限

    一般使用Context.getContentResolver()方法获取ContentResolver对象。

    ContentResolver 可提供insert、query、update、delete等方法.

    例如,要从用户字典提供程序中获取字词及其区域设置的列表,则需调用 ContentResolver.query()。

    // Queries the user dictionary and returns results
    mCursor = getContentResolver().query(
        UserDictionary.Words.CONTENT_URI,   
        mProjection,                        
        mSelectionClause                  
        mSelectionArgs,                     
        mSortOrder);                        
    
    query() 参数 SELECT 关键字/参数 备注
    Uri FROM table_name Uri 映射至名为 table_name 的提供程序中的表。
    projection col,col,col,... projection 是应该为检索到的每个行包含的列的数组。
    selection WHERE col = value selection 会指定选择行的条件。
    selectionArgs (没有完全等效项。选择参数会替换选择子句中 ? 的占位符。)
    sortOrder ORDER BY col,col,... sortOrder 指定行在返回的 Cursor 中的显示顺序。
    内容 URI

    在Android中,Uri是一种比较常见的资源访问方式。每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。

    <srandard_prefix>://<authority>/<data_path>/<id>

    • <srandard_prefix>:
      ContentProvider的标准前缀始终是content://
    • <authority>:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。一般为该ContentProvider的包.类的名称
    • <data_path>:请求的数据类型, 如数据库的表。
    • <id>:指定请求的特定数据。如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部
    content://user_dictionary/words
    content://com.example.app.provider/table3/1
    //对应由 表table3中1标识的行的内容 URI。
    content://com.example.app.provider/table3/1/name
    //对应由 表table3中1标识的行的name字段内容 URI。
    
    UriMatcher

    UriMatcher会将内容 URI“模式”映射到整型值。 可以在一个 switch 语句中使用这些整型值,为匹配特定模式的一个或多个内容 URI 执行相应操作。

    内容 URI 模式使用通配符匹配内容 URI:

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

    假设一个具有权限 com.example.app.provider的提供程序能识别以下指向表的内容 URI:

    content://com.example.app.provider/table1:一个名为 table1 的表
    content://com.example.app.provider/table2/dataset1:一个名为 dataset1 的表
    content://com.example.app.provider/table2/dataset2:一个名为 dataset2 的表
    content://com.example.app.provider/table3:一个名为 table3 的表
    

    可以使用以下内容 URI 模式:

    content://com.example.app.provider/*
    //匹配提供程序中的任何内容 URI。
    content://com.example.app.provider/table2/*:
    //匹配表 dataset1 和表 dataset2 的内容 URI,但不匹配 table1 或 table3 的内容 URI。
    content://com.example.app.provider/table3/#
    //匹配 table3 中单个行的内容 URI,
    //如 content://com.example.app.provider/table3/6 对应由 6 标识的行的内容 URI。
    

    方法 addURI() 会将权限和路径映射到一个整型值。 方法 match() 会返回 URI 的整型值。switch 语句会在查询整个表与查询单个记录之间进行选择:

    public class ExampleProvider extends ContentProvider {
          ...
        // Creates a UriMatcher object.
        private static final UriMatcher sUriMatcher;
    
        sUriMatcher.addURI("com.example.app.provider", "table3", 1);
    
        sUriMatcher.addURI("com.example.app.provider", "table3/#", 2);
        ...
        // Implements ContentProvider.query()
        public Cursor query(Uri uri, String[] projection, String selection, 
                    String[] selectionArgs, String sortOrder) {
            ...
            switch (sUriMatcher.match(uri)) {
                // If the incoming URI was for all of table3
                case 1:
                    if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID ASC";
                    break;
                // If the incoming URI was for a single row
                case 2:
                    /*
                     Because this URI was for a single row, the _ID value part is
                     present. Get the last path segment from the URI;
                     this is the _ID value.Then, append the value to the WHERE 
                     clause for the query
                     */
                    selection = selection + "_ID = " uri.getLastPathSegment();
                    break;
    
                default:
                ...
                    // If the URI is not recognized, you should do some error handling here.
            }
            // call the code to actually do the query
        }
    
    创建ContentProvider

    在Android中,如果要创建自己的内容提供者的时候,需要扩展抽象类ContentProvider,并重写其中定义的各种方法。然后在AndroidManifest.xml文件中注册该ContentProvider。

    创建ContentProvider的步骤:

    1. 创建一个ContentProvider的子类。
    1. 定义内容Uri
    1. 创建SQLiteOpenHelper的子类,创建一个用于存储内容的数据库。
    1. 在ContentProvider的子类中实现query()、insert()、update()、delete()、getType()、onCreate()方法。
    1. 在AndroidManifest.xml文件中注册自定义的ContentProvider。
      <provider.../>:一般只需要设置两个属性即可访问,一些额外的属性就是为了设置访问权限而存在的:
      android:name:provider的响应类。
      android:authorities:Provider的唯一标识,用于Uri匹配,一般为ContentProvider类的全名。

    在实现ContentProvider的方法时需要注意一下几点:

    • 所有这些方法(onCreate() 除外)都可由多个线程同时调用,因此它们必须是线程安全方法。
    • 避免在 onCreate() 中执行长时间操作。将初始化任务推迟到实际需要时进行。
    • 尽管必须实现这些方法,但代码只需返回要求的数据类型,无需执行任何其他操作。 例如,可能想防止其他应用向某些表插入数据。 要实现此目的,可以忽略 insert() 调用并返回 0。

    相关文章

      网友评论

          本文标题:android contentProvider

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