Android中应用程序之间的数据共享

来源:互联网 发布:手机淘宝在哪开店 编辑:程序博客网 时间:2024/06/03 18:41

一、概述

      如何将应用程序的数据暴露出去?Android提供了一种统一的接口,即ContentProvider,一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content providers是以类似数据库中表的方式将数据暴露。Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。要想使应用程序的数据公开化,可通过2种方法:创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。

    如何通过统一的接口获取其他APP暴露的数据呢?Android提供了ContentResolver,APP通过ContentResolver访问ContentProvider中的数据(通过Uri查询数据)。

 

二、ContentProvider的使用

2.1 特点:

a、使用ContentProvider对外共享数据的好处是统一了数据的访问方式。
b、ContentProvider基本不需要用户与它的对象交互,系统会自动唤醒所有注册了的provider;

c、ContentProvider的OnCreate方法,并不是一直被系统调用的<网上好多人是误导,本人亲测,只有你第一次安装该apk的时候才会被调用>

d、ContentProvider通过uri来访问数据;


2.2 使用步骤

a、继承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)}

 

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

<manifest.... > <application android:icon="@drawable/icon" android:label="@string/app_name"> <provider android:name=".PersonContentProvider"(需与a中继承的类名一致 android:authorities="com.ljq.providers.personprovider"/> </application></manifest>

 

c、当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver 类提供了与ContentProvider类相同签名的四个方法。

 

三、ContentProvider各种方法的重写

3.1 query

    // 查询    @Override    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,            String sortOrder) {        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();        switch (sUriMatcher.match(uri)) {        // 查询所有        case TASKS:            qb.setTables(TASK_LIST_TABLE_NAME);            qb.setProjectionMap(sTaskListProjectionMap);            break;        // 根据ID查询        case TASK_ID:            qb.setTables(TASK_LIST_TABLE_NAME);            qb.setProjectionMap(sTaskListProjectionMap);            qb.appendWhere(Tasks._ID + "=" + uri.getPathSegments().get(1));            break;        default:            throw new IllegalArgumentException("Uri错误! " + uri);        }        // 使用默认排序        String orderBy;        if (TextUtils.isEmpty(sortOrder)) {            orderBy = TaskList.Tasks.DEFAULT_SORT_ORDER;        } else {            orderBy = sortOrder;        }        // 获得数据库实例        SQLiteDatabase db = mOpenHelper.getReadableDatabase();        // 返回游标集合        Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);        c.setNotificationUri(getContext().getContentResolver(), uri);        return c;    }

 

参数分析:

    uri,查询时传入的uri,它代表了我们要查找的数据源。
    projection,查询时传入的一个字符串数组,通过它来表明我们需要数据表中的哪些row。当查询结束后就会返回包含这些row的结果表。
    selectionArgs,功能不清楚,猜想为表明结果表中各个row的排列顺序。
    sortOrder,表示返回的结果集的排列顺序的语句。

返回值:

       Cursor对象

函数体分析:

        a、SQLiteQueryBuilder:一个用来构造SQL查询语句的辅助类,可以方便的去访问SQLiteDatabase. 在构造SQL查询语句时,它同样也需要指定表名,指定列名,指定where条件。其中的方法使用如下:

              setTables方法设置了它查询工作将要针对的表;

              setProjectionMap方法:不同的uri设置了不同的projection map;

(这个map是对用户查询操作传入的column名和数据表中存在的column名进行了一个映射,这样一来,有些数据库中抽象的表的column名就可以通过这个projection map实现重新命名,以达到方便开发者做一些类似于数据库表联接(join)操作的目的。一般情况下数据库中的表的column名就已经够清晰了,所以你可以不用再在projection map里面做一些column重命名的操作了——也就是说,你可以将这个map对象中的key和value都设为同样的值(接下来的代码会有体现)。)

 

疑问:SQLiteDatabase不是有query吗,为什么要通过SQLiteQueryBuilder来查询呢?SQLiteQueryBuilder能提供什么?

       

         b、UriMatcher类的使用

          首先第一步,初始化:

           private static final UriMatcher sUriMatcher;

          sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);(UriMatcher.NO_MATCH 表示不匹配任何路径的返回码

          第二步注册需要的Uri:

        sUriMatcher.addURI(TaskList.AUTHORITY, "taskLists", TASKS);
        sUriMatcher.addURI(TaskList.AUTHORITY, "taskLists/#", TASK_ID);  (# 号为通配符,* 号为任意字符

          第三部,与已经注册的Uri进行匹配:

          sUriMatcher.match(uri)  (返回TASKS或者TASK_ID)

          match方法匹配后会返回一个匹配码Code,即在使用注册方法addURI时传入的第三个参数。 

 

c、setNotificationUri方法的使用(http://www.myexception.cn/database/487982.html)

 

3.2 insert的实现(以SQLiteDatabase.insert和ContentValues为基础,参见SQLiteDatabase知识点)

3.2.1 函数分析

原型:Uri android.content.ContentResolver.insert(Uri url,ContentValues values);
作用:在给定Uri对应的数据表中插入一行。If the content provider supports transactions the insertion will be atomic.

参数:

            Uri url  要插入的表对应的Uri

            ContentValues values   要插入行的内容。The key is the column name for the field。如果内容为空,将创建一个空行。

返回值:创建的新列的Uri。

3.2.2 实现过程

a、检查Uri的有效性(UriMatcher)

        if (sUriMatcher.match(uri) != TASKS) {            throw new IllegalArgumentException("错误的 URI: " + uri);        }

b、创建ContentValues对象,将参数中传递进来的values传递给该对象

        ContentValues values;        if (initialValues != null) {            values = new ContentValues(initialValues);        } else {            values = new ContentValues();        }

c、创建SQLiteDatabase对象,利用SQLiteDatabase.insert方法插入新行

        // 获得数据库实例        SQLiteDatabase db = mOpenHelper.getWritableDatabase();        // 保存数据返回行ID        long rowId = db.insert(TASK_LIST_TABLE_NAME, Tasks.CONTENT, values);


d、对返回行ID进行检查,如果插入成功,则返回新行的Uri

        if (rowId > 0) {            Uri taskUri = ContentUris.withAppendedId(TaskList.Tasks.CONTENT_URI, rowId);            getContext().getContentResolver().notifyChange(taskUri, null);            return taskUri;        }        throw new SQLException("插入数据失败 " + uri);


疑问:

a、关于监视器的问题还没弄懂,参见

http://www.cnblogs.com/bastard/archive/2012/06/02/2531663.html

http://blog.csdn.net/xiazdong/article/details/7706977

http://blog.csdn.net/java2009cgh/article/details/7367940


b、关于异常的使用也没有深入。




3.3 delete的实现

http://blog.sina.com.cn/s/blog_69092aea0101879o.html

http://www.w3school.com.cn/sql/sql_and_or.asp


四、ContentResolver的使用

4.1 概述

4.2 常用方法





 参看资料:

http://blog.csdn.net/feng88724/article/details/6331396

 

原创粉丝点击