zoukankan      html  css  js  c++  java
  • 内容提供者

    内容提供者

    参考:

    Android四大组件之内容提供者--ContentProvider - java小兵 - CSDN博客
    http://blog.csdn.net/wodewutai17quiet/article/details/46670597

    Android四大组件之内容提供者--ContentProvider  

    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.     }  
  • 相关阅读:
    linux 中实现两列数据的互换
    linux中 sort h的作用
    max 内置函数,管理uv 编辑器下面的窗口的显示情况
    时时设定 uv 面板的位置,还有就是 关于属性打开界面的大小
    判断贴图大小很好 同时可以判断文件大小
    两条线中画终点
    锁定控制器,一般在绑定的时候很多用到
    用 脚本编辑器读脚本 也是编辑脚本
    进行随机旋转用于和并东西并
    排列顶点 uv 不过有很大问题
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7471659.html
Copyright © 2011-2022 走看看