你的位置:首页 > 操作系统

[操作系统]内容提供者

内容提供者

参考:

Android四大组件之内容提供者--ContentProvider - java小兵 - CSDN博客

B程序通过内容提供者来访问联系人程序的数据。

 

1,什么是ContentProvider  

        ContentProvider将应用中的数据对其它应用进行共享, 提供增删改查的方法  

        ContentProvider统一了数据的访问方式,不必针对不同数据类型采取不同的访问策略  

        ContentProvider将数据封装,只暴露出我们希望提供给其它程序的数据  

        ContentProvider中可以注册观察者, 监听数据的变化   

2,怎么创建  

        2.1定义类继承ContentProvider, 实现抽象方法,抽象方法中对数据库操作的增删改查都有。  

        2.2在清单文件中注册:在清单文件的<application>节点下进行配置<provider>标签,标签中需要指定name和authorities属性  

            name:完整的类名。可以省略包名(manifest节点的package值),注意:省略后的类名是以"."开头的。  

            authorities:主机,是访问Provider时的路径,要唯一  

 

B程序需要通过com.baidu这个url来实现访问修改读取联系人程序。

完整类名就是继承ContentProvider类的那个类的完整类名。

这样配置也是告诉计算机,我这个类是内容提供者,后面要被别人访问,并且可以通过com.baidu这个主机访问我。

我们在B程序中通过内容解析者和主机名访问联系人程序。

 

3,在手机上注册
将应用安装到手机上即可, 不用运行程序

4,其它应用怎么访问
外部应用使用ContentResolver类对ContentProvider中的数据进行访问(CRUD操作)
获取解析器ContentResolver
ContentResolver resolver = Context.getContentResolver();
通过resolver.insert(), delete(), update(), query()方法访问Uri关联的ContentProvider

 

 

5,Uri的处理
  URI代表要操作的数据,由scheme、authorites、path三部分组成
  eg:
    content://com.jxn.provider/person
    scheme | authorites | path

  1,schema:表明要访问ContentProvider。固定为:"content://"
  2,Authority(主机名或授权):定义了是哪个ContentProvider提供这些数据。
  3,path:路径,可根据业务逻辑自定义。eg: person、person/insert、person/insert/10等等
  4,ID:通常定义URI时使用"#"号占位符代替, 使用时替换成对应的数字
    "content://com.jxn.provider/person/#" #表示数据id(#代表任意数字)
    "content://com.jxn.provider/person/*" *来匹配任意文本


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

  1,UriMatcher类用于匹配Uri,用法如下:

    第一步:把你需要匹配的Uri路径全部给注册上,如下:

      //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
      UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
      //如果match()方法匹配content://com.jxn.provider.personprovider/person路径,返回匹配码为1
      matcher.addURI("com.jxn.provider.personprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
      //如果match()方法匹配content://com.jxn.provider.personprovider/person/230路径,返回匹配码为2
      matcher.addURI("com.jxn.provider.personprovider", "person/#", 2);//#号为通配符

    第二步:使用matcher.match(uri)方法对输入的Uri进行匹配,如果匹配成功就返回匹配码
      switch (matcher.match(Uri.parse("content://com.jxn.provider.personprovider/person/10"))) {
        case 1
        // 相应的业务操作
        break;
        case 2
        // 相应的业务操作
        break;
        default:
        // 相应的业务操作
        break;
        }

    2,ContentUris类用于为路径加上ID和获取路径的ID

      给Uri加上id: ContentUris.withAppendedId(uri, id)
      获取id: ContentUris.parseId(uri)

 

 

6,监听内容提供者数据变化 

     

        1,如果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); 

                    // 注:如果没有调用notifyChange()方法,即使其它应用注册了ContentObserver,也不会知道ContentProvider中的数据的变化 

                    getContext().getContentResolver().notifyChange(uri, null); 

                } 

            } 

             

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

            getContentResolver().registerContentObserver(Uri.parse("content://com.jxn.providers.personprovider/person"),true, new PersonObserver(new Handler())); 

            public class PersonObserver extends ContentObserver{ 

                public PersonObserver(Handler handler) { 

                    super(handler); 

                } 

                public void onChange(boolean selfChange) { 

                    //此处可以进行相应的业务处理 

                } 

            }  

 

7,补充 

        getType()方法:主要用于匹配数据类型,返回当前Uri所代表数据的MIME类型。 

            如果返回数据是单条数据:vnd.android.cursor.item  

            如果返回数据是多条数据:vnd.android.cursor.dir  

 

 

  1. 案例:B应用通过A应用提供的ContentProvider访问A应用中的数据  
  2.   
  3.     // 提供ContentProvider的A应用中定义的SQLiteProvider  
  4.     public class SQLiteProvider extends ContentProvider {  
  5.   
  6.         // Uri匹配器, 用来匹配传入的Uri  
  7.         private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);  
  8.           
  9.         private static final int PERSON = 1;  
  10.           
  11.         // DBOpenHelper extends SQLiteOpenHelper  
  12.         private DBOpenHelper helper;  
  13.   
  14.         static {  
  15.             // 设置一个Uri, 如果匹配到person, 返回1  
  16.             matcher.addURI("com.jxn.sqlite.provider", "person", PERSON);  
  17.         }  
  18.           
  19.   
  20.         // 其它应用第一次访问时(此时会创建ContentProvider)执行  
  21.         // 第一次启动时执行, 然后会长期驻留在后台, 除非被杀死, 否则不会再执行  
  22.         @Override  
  23.         public boolean onCreate() {  
  24.             helper = new DBOpenHelper(getContext());  
  25.             return true;  
  26.         }  
  27.   
  28.         // 外部应用使用此方法查询数据  
  29.         @Override  
  30.         public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {  
  31.             SQLiteDatabase db = helper.getReadableDatabase();  
  32.               
  33.             // 用匹配器匹配传入的uri  
  34.             switch (matcher.match(uri)) {  
  35.                 case PERSON:  
  36.                     return db.query("person", projection, selection, selectionArgs, null, null, sortOrder);     // 执行查询  
  37.                 default:  
  38.                     throw new RuntimeException("Uri不能识别: " + uri);  
  39.             }  
  40.         }  
  41.   
  42.         // 外部应用使用此方法添加数据  
  43.         @Override  
  44.         public Uri insert(Uri uri, ContentValues values) {  
  45.             SQLiteDatabase db = helper.getWritableDatabase();  
  46.             switch (matcher.match(uri)) {  
  47.                 case PERSON:  
  48.                     long id = db.insert("person", "id", values);    // 插入记录, 得到id  
  49.                     return ContentUris.withAppendedId(uri, id);     // 把id跟在uri后面返回  
  50.                 default:  
  51.                     throw new RuntimeException("Uri不能识别: " + uri);  
  52.             }  
  53.         }  
  54.   
  55.         @Override  
  56.         public int delete(Uri uri, String selection, String[] selectionArgs) {  
  57.             SQLiteDatabase db = helper.getWritableDatabase();  
  58.             switch (matcher.match(uri)) {  
  59.                 case PERSON:  
  60.                     return db.delete("person", selection, selectionArgs);  
  61.                 default:  
  62.                     throw new RuntimeException("Uri不能识别: " + uri);  
  63.             }  
  64.         }  
  65.   
  66.         @Override  
  67.         public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {  
  68.             SQLiteDatabase db = helper.getWritableDatabase();  
  69.             switch (matcher.match(uri)) {  
  70.                 case PERSON:  
  71.                     return db.update("person", values, selection, selectionArgs);  
  72.                 default:  
  73.                     throw new RuntimeException("Uri不能识别: " + uri);  
  74.             }  
  75.         }  
  76.   
  77.         @Override  
  78.         public String getType(Uri uri) {  
  79.             switch (matcher.match(uri)) {  
  80.                 case PERSON:  
  81.                     return "vnd.android.cursor.dir/person";     // mimetype  
  82.                 default:  
  83.                     throw new RuntimeException("Uri不能识别: " + uri);  
  84.             }  
  85.         }  
  86.     }  
  87.   
  88.   
  89.     // B应用中要访问A应用的数据的测试类  
  90.     public class ProviderTest extends AndroidTestCase {  
  91.           
  92.         public void test() {  
  93.           
  94.             // 获取解析器对象  
  95.             ContentResolver resolver = getContext().getContentResolver();  
  96.               
  97.             // 访问内容提供者  
  98.             Uri uri = Uri.parse("content://com.jxn.sqlite.provider");  
  99.             ContentValues values = new ContentValues();  
  100.   
  101.         }  
  102.           
  103.         public void testQuery() {  
  104.           
  105.             // 获取解析器对象  
  106.             ContentResolver resolver = getContext().getContentResolver();  
  107.             Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");  
  108.               
  109.             // 访问内容提供者  
  110.             Cursor c = resolver.query(uri, new String[]{ "id", "name", "balance" }, "balance>?", new String[]{ "9000" }, "balance DESC");  
  111.             while (c.moveToNext()) {  
  112.                 Person p = new Person(c.getInt(0), c.getString(1), c.getInt(2));  
  113.                 System.out.println(p);  
  114.             }  
  115.         }  
  116.           
  117.         public void testInsert() {  
  118.             ContentResolver resolver = getContext().getContentResolver();  
  119.             Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");  
  120.               
  121.             ContentValues values = new ContentValues();  
  122.             values.put("name", "provider");  
  123.             values.put("balance", 12345);  
  124.               
  125.             // 插入数据, 并且得到这条数据的uri  
  126.             uri = resolver.insert(uri, values);  
  127.               
  128.             System.out.println(uri);  
  129.         }  
  130.           
  131.         public void testUpdate() {  
  132.             ContentResolver resolver = getContext().getContentResolver();  
  133.             Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");  
  134.               
  135.             ContentValues values = new ContentValues();  
  136.             values.put("name", "update");  
  137.             values.put("balance", 54321);  
  138.             int count = resolver.update(uri, values, null, null);  
  139.             System.out.println(count);  
  140.         }  
  141.           
  142.         public void testDelete() {  
  143.             ContentResolver resolver = getContext().getContentResolver();  
  144.             Uri uri = Uri.parse("content://com.jxn.sqlite.provider/person");  
  145.               
  146.             int count = resolver.delete(uri, null, null);  
  147.             System.out.println(count);  
  148.         }  
  149.           
  150.         public void testGetType() {  
  151.             ContentResolver resolver = getContext().getContentResolver();  
  152.             // 获取uri的类型  
  153.             String type = resolver.getType(Uri.parse("content://com.jxn.sqlite.provider/person"));  
  154.             System.out.println(type);  
  155.         }  
  156.     }