zoukankan      html  css  js  c++  java
  • ContentProvider如何实现APP之间的数据共享

    ContentProvider 认识:

      Content providers负责管理结构化数据的访问,Content providers封装数据并且提供一套定义数据安全的机制。

      Content providers是一套在不同进程间进行数据访问的接口。
      Content providers为数据跨进程访问提供了一套安全的访问机制,对数据组织和安全访问提供了可靠的保证。

    Content Providers的使用的:

      通过Content Providers访问数据时,在应用程序的上下文(Context)中使用ContentResolver对象最为客户端(client)与 provider进行交互。

      ContentResolver对象通过实现抽象类ContentProvider的一个实例来访问provider。

      Provider对象从客户端(client)接收数据请求,执行请求操作并且返回请求结果。

      Android通过Content Provider来管理数据诸如音频、视频、图片和通讯录等。

      还可以通过ContentProvider来访问SQLite数据库等,下面来看看Content Provider的基本使用

    在以下情况下你需要使用Content Providers:
    1.你想为其他应用程序提供复杂数据或文件;
    2.你想允许用户从你的应用程序中拷贝复杂数据到其他的应用中
    3.你想使用搜索框架提供自定义的查询建议功能

    一、使用ContentProvider(内容提供者)共享数据

    ContentProvider在android中的作用是对外共享数据, 也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider对你应用中的数据 进行添删改查。关于数据共享,以前我们学习过文件操作模式,知道通过指定文件的操作模式为Context.MODE_WORLD_READABLE或 Context.MODE_WORLD_WRITEABLE同样也可以对外共享数据。那么,这里为何要使用ContentProvider对外共享数据 呢?是这样的,如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用xml文件对外共享数 据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读取数据。
    使用ContentProvider对外共享数据的好处是统一了数据的访问方式。
    当应用需要通过ContentProvider对外共享数据时,第一步需要继承ContentProvider并重写下面方法:

    复制代码
    public class PersonContentProvider extends ContentProvider{
    public boolean onCreate()
    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)
    public String getType(Uri uri)
    }
    复制代码

    第二步需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配置,为了能让其他应用找到该ContentProvider ,ContentProvider采用了authorities(主机名/域名)对它进行唯一标识,你可以把ContentProvider看作是一个网站(想想,网站也是提供数据者),authorities 就是他的域名:

    <manifest.... >
    <application android:icon="@drawable/icon" android:label="@string/app_name">
    <provider android:name=".PersonContentProvider"
    android:authorities="com.ljq.providers.personprovider"/>
    </application>
    </manifest>

              

                 

    二、Uri介绍

    Uri代表了要操作的数据,Uri主要包含了两部分信息:1》需要操作的ContentProvider ,2》对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:          

                     

    ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://
    主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
    路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
    要操作person表中id为10的记录,可以构建这样的路径:/person/10
    要操作person表中id为10的记录的name字段, person/10/name
    要操作person表中的所有记录,可以构建这样的路径:/person
    要操作xxx表中的记录,可以构建这样的路径:/xxx
    当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
    要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
    如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
    Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")

                    

                 

    三、UriMatcher类使用介绍

    因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。
    UriMatcher类用于匹配Uri,它的用法如下:
    首先第一步把你需要匹配Uri路径全部给注册上,如下:

    复制代码
    //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
    UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    //如果match()方法匹配content://com.ljq.provider.personprovider/person路径,返回匹配码为1
    sMatcher.addURI("com.ljq.provider.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
    //如果match()方法匹配content://com.ljq.provider.personprovider/person/230路径,返回匹配码为2
    sMatcher.addURI("com.ljq.provider.personprovider", "person/#", 2);//#号为通配符
    switch (sMatcher.match(Uri.parse("content://com.ljq.provider.personprovider/person/10"))) {
    case 1
    break;
    case 2
    break;
    default://不匹配
    break;
    }
    复制代码

    注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://com.ljq.provider.personprovider/person路径,返回的匹配码为1 

                  

                     

    四、ContentUris类使用介绍

    ContentUris类用于操作Uri路径后面的ID部分,它有两个比较实用的方法:
    withAppendedId(uri, id)用于为路径加上ID部分:

    Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")
    Uri resultUri = ContentUris.withAppendedId(uri, 10);
    //生成后的Uri为:content://com.ljq.provider.personprovider/person/10

    parseId(uri)方法用于从路径中获取ID部分:

    Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person/10")
    long personid = ContentUris.parseId(uri);//获取的结果为:10

              

                  

    五、使用ContentProvider共享数据

    ContentProvider类主要方法的作用:
    public boolean onCreate():该方法在ContentProvider创建后就会被调用,Android开机后,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):该方法用于供外部应用从ContentProvider中获取数据。
    public String getType(Uri uri):该方法用于返回当前Url所代表数据的MIME类型。

    如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,

    例如:要得到所有person记录的Uri为content://com.ljq.provider.personprovider/person,那么返回的MIME类型字符串应该为:"vnd.android.cursor.dir/person"。

    如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,

    例如:得到id为10的person记录,Uri为content://com.ljq.provider.personprovider/person/10,那么返回的MIME类型字符串为:"vnd.android.cursor.item/person"。

                  

                    

    六、使用ContentResolver操作ContentProvider中的数据

    当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver 类提供了与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):该方法用于从ContentProvider中获取数据。

    这些方法的第一个参数为Uri,代表要操作的ContentProvider和对其中的什么数据进行操作,

    假设给定的是:Uri.parse("content://com.ljq.providers.personprovider/person/10"),那么将会对主机名为com.ljq.providers.personprovider的ContentProvider进行操作,操作的数据为person表中id为10的记录。

    使用ContentResolver对ContentProvider中的数据进行添加、删除、修改和查询操作:

    复制代码
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person");
    //添加一条记录
    ContentValues values = new ContentValues();
    values.put("name", "linjiqin");
    values.put("age", 25);
    resolver.insert(uri, values);
    //获取person表中所有记录
    Cursor cursor = resolver.query(uri, null, null, null, "personid desc");
    while(cursor.moveToNext()){
    Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));
    }
    //把id为1的记录的name字段值更改新为zhangsan
    ContentValues updateValues = new ContentValues();
    updateValues.put("name", "zhangsan");
    Uri updateIdUri = ContentUris.withAppendedId(uri, 2);
    resolver.update(updateIdUri, updateValues, null, null);
    //删除id为2的记录
    Uri deleteIdUri = ContentUris.withAppendedId(uri, 2);
    resolver.delete(deleteIdUri, null, null);
    复制代码

                

                   

    七、监听ContentProvider中数据的变化

    如果ContentProvider的访问者需要知道ContentProvider中的数据发生变化,可以在ContentProvider发生数据变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者,例子如下:

    public class PersonContentProvider extends ContentProvider {
    public Uri insert(Uri uri, ContentValues values) {
    db.insert("person", "personid", values);
    getContext().getContentResolver().notifyChange(uri, null);
    }
    }

    如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法:

    复制代码
    getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),
    true, new PersonObserver(new Handler()));
    public class PersonObserver extends ContentObserver{
    public PersonObserver(Handler handler) {
    super(handler);
    }
    public void onChange(boolean selfChange) {
    //此处可以进行相应的业务处理
    }
    }
    复制代码
    Java代码
    1. public class PersonContentProvider extends ContentProvider{  
    2.     private DataBaseOpenHelper dataBaseOpenHelper;  
    3.     private static final int ALLPERSON=1;  
    4.     private static final int PERSON=2;  
    5.     private static final UriMatcher uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);  
    6.     static{  
    7.         uriMatcher.addURI("com.gao.provider.personprovider", "person", ALLPERSON);  
    8.         uriMatcher.addURI("com.gao.provider.personprovider", "person/#", PERSON);  
    9.           
    10.     }  
    11.     @Override  
    12.     public int delete(Uri uri, String selection, String[] selectionArgs) {  
    13.         SQLiteDatabase database=dataBaseOpenHelper.getWritableDatabase();  
    14.         int count=0;  
    15.         switch (uriMatcher.match(uri)) {  
    16.         case ALLPERSON://content://com.gao.provider.personprovider/person  
    17.             count=database.delete("person", selection, selectionArgs);  
    18.             break;  
    19.         case PERSON://content://com.gao.provider.personprovider/person/100  
    20.             long id=ContentUris.parseId(uri);  
    21.             String where=TextUtils.isEmpty(selection)?"personid=?":selection+"and personid=?";  
    22.             String[] params=new String[]{String.valueOf(id)};  
    23.             if (!TextUtils.isEmpty(selection)&&selectionArgs!=null) {  
    24.                 params=new String[selectionArgs.length+1];  
    25.                 for (int i = 0; i < selectionArgs.length; i++) {  
    26.                     params[i]=selectionArgs[i];  
    27.                 }  
    28.                 params[selectionArgs.length+1]=String.valueOf(id);  
    29.             }  
    30.             count=database.delete("person", where, selectionArgs);  
    31.             break;  
    32.         default:  
    33.             throw new IllegalArgumentException("Unkonw uri:"+uri);  
    34.         }  
    35.         return count;  
    36.     }  
    37.     @Override  
    38.     public String getType(Uri uri) {  
    39.         switch (uriMatcher.match(uri)) {  
    40.         case ALLPERSON:  
    41.             return "vnd.android.cursor.dir/personprovider.person";  
    42.         case PERSON:  
    43.             return "vnd.android.cursor.item/personprovider.person";  
    44.         default:  
    45.             break;  
    46.         }  
    47.         return null;  
    48.     }  
    49.     @Override  
    50.     public Uri insert(Uri uri, ContentValues values) {  
    51.         SQLiteDatabase database=dataBaseOpenHelper.getWritableDatabase();  
    52.         long id=0;  
    53.         switch (uriMatcher.match(uri)) {  
    54.         case ALLPERSON://content://com.gao.provider.personprovider/person  
    55.             id=database.insert("person", "name", values);//返回记录的行号,主键是int,实际上就是主键值  
    56.             return ContentUris.withAppendedId(uri, id);  
    57.         case PERSON://content://com.gao.provider.personprovider/person/100  
    58.             id=database.insert("person", "name", values);  
    59.             String path=uri.toString();  
    60.             return Uri.parse(path.substring(0, path.lastIndexOf("/"))+"id");  
    61.         default:  
    62.             throw new IllegalArgumentException("Unkonw uri:"+uri);  
    63.         }  
    64.     }  
    65.     @Override  
    66.     public boolean onCreate() {  
    67.         dataBaseOpenHelper=new DataBaseOpenHelper(this.getContext());  
    68.         return false;  
    69.     }  
    70.     @Override  
    71.     public Cursor query(Uri uri, String[] projection, String selection,  
    72.             String[] selectionArgs, String sortOrder) {  
    73.         SQLiteDatabase database=dataBaseOpenHelper.getReadableDatabase();  
    74.         switch (uriMatcher.match(uri)) {  
    75.         case ALLPERSON:  
    76.             database.query("person", projection, selection, selectionArgs, null, null, sortOrder);  
    77.             break;  
    78.         case PERSON:  
    79.             long id=ContentUris.parseId(uri);  
    80.             String where=TextUtils.isEmpty(selection)?"personid=?":selection+"and personid=?";  
    81.             String[] params=new String[]{String.valueOf(id)};  
    82.             if (!TextUtils.isEmpty(selection)&&selectionArgs!=null) {  
    83.                 params=new String[selectionArgs.length+1];  
    84.                 for (int i = 0; i < selectionArgs.length; i++) {  
    85.                     params[i]=selectionArgs[i];  
    86.                 }  
    87.                 params[selectionArgs.length+1]=String.valueOf(id);  
    88.             }  
    89.             database.query("person", projection, where, params, null, null, sortOrder);  
    90.             break;  
    91.         default:  
    92.             break;  
    93.         }  
    94.         return null;  
    95.     }  
    96.     //update("content://com.gao.provider.personprovider/person/100",values,"name like ? and ...",new String[]{"%gao%"});  
    97.     @Override  
    98.     public int update(Uri uri, ContentValues values, String selection,  
    99.             String[] selectionArgs) {  
    100.         SQLiteDatabase database=dataBaseOpenHelper.getWritableDatabase();  
    101.         int count=0;  
    102.         switch (uriMatcher.match(uri)) {  
    103.         case ALLPERSON://content://com.gao.provider.personprovider/person  
    104.             count=database.update("person", values, selection,selectionArgs);  
    105.             break;  
    106.         case PERSON://content://com.gao.provider.personprovider/person/100  
    107.             long id=ContentUris.parseId(uri);  
    108.             String where=TextUtils.isEmpty(selection)?"personid=?":selection+"and personid=?";  
    109.             String[] params=new String[]{String.valueOf(id)};  
    110.             if (!TextUtils.isEmpty(selection)&&selectionArgs!=null) {  
    111.                 params=new String[selectionArgs.length+1];  
    112.                 for (int i = 0; i < selectionArgs.length; i++) {  
    113.                     params[i]=selectionArgs[i];  
    114.                 }  
    115.                 params[selectionArgs.length+1]=String.valueOf(id);  
    116.             }  
    117.             count=database.update("person", values, where,params);  
    118.             break;  
    119.         default:  
    120.             throw new IllegalArgumentException("Unkonw uri:"+uri);  
    121.         }  
    122.         return count;  
    123.     }  
    124. }  
    AndroidManifest.xml:
    <provider android:name="PersonContentProvider"
    android:authorities="com.gao.provider.personprovider" />
    在另一个程序ContentProviderUser中使用上面的内容提供者:
    Java代码
    1. public void onCreate(Bundle savedInstanceState) {  
    2.        super.onCreate(savedInstanceState);  
    3.        setContentView(R.layout.main);  
    4.        ContentResolver contentResolver=this.getContentResolver();  
    5.        Uri allUri=Uri.parse("content://com.gao.provider.personprovider/person");  
    6.        ContentValues values=new ContentValues();  
    7.        values.put("name", "GGGGG");  
    8.        values.put("age", 19);  
    9.        contentResolver.insert(uri, values);  
    10.        values.put("name", "CCCCCC");  
    11.        values.put("age", 100);  
    12.        Uri uri=Uri.parse("content://com.gao.provider.personprovider/person/9");  
    13.       // contentResolver.update(uri, values, null, null);  
    14.        //contentResolver.delete(uri, null, null);  
    15.        Cursor cursor=contentResolver.query(uri, new String[]{"personid","name","age"}, null, null, "personid desc");  
    16.        while (cursor.moveToNext()) {  
    17.         Log.i(TAG, "psrsonid:"+cursor.getInt(0)+",name:"+cursor.getString(1)+",age"+cursor.getInt(2));  
    18.     }  
    19.        cursor.close();  
    分享到:
  • 相关阅读:
    Python使用SMTP模块、email模块发送邮件
    harbor搭建及使用
    ELK搭建-windows
    ELK技术栈之-Logstash详解
    【leetcode】1078. Occurrences After Bigram
    【leetcode】1073. Adding Two Negabinary Numbers
    【leetcode】1071. Greatest Common Divisor of Strings
    【leetcode】449. Serialize and Deserialize BST
    【leetcode】1039. Minimum Score Triangulation of Polygon
    【leetcode】486. Predict the Winner
  • 原文地址:https://www.cnblogs.com/jasonxcj/p/5002881.html
Copyright © 2011-2022 走看看