android-关于ContentProvider的使用

ContentProvider是用于将数据共享给其他应用。例如在同一部手机里面,有两个APP,第一个APP要访问第二个APP的数据。此时,第二个APP就需要设置ContentProvider。这样,第一个APP就能通过Uri访问第二个APP的数据。

第二部手机的设置,首先需要一个类来继承ContentProvider这个类,继承后需要实现onCreate,query,getType,insert,delete,update这个几个方法,如其名,其作用是给第一个APP调用的,至于第一个APP是如何调用的,下面会提到。

给出一个继承ContentProvider的例子:

1.先是提供的数据类型等数据的类。

package org.juetion.cp;

import android.net.Uri;
import android.provider.BaseColumns;

/**
 * 提供的数据类型等数据。
 * Created by juetionke on 13-12-21.
 */
public class MyProviderMetaData {


    public static final String AUTHORIY = "org.juetion.cp.MyContentProvider";
    /**
     * 数据库名称
     */
    public static final String DATABASE_NAME = "MyProvider.db";
    /**
     * 数据库版本
     */
    public static final int DATABASE_VERSION = 1;
    /**
     * 表名
     */
    public static final String USERS_TABLE_NAME = "users";

    /**
     * 继承了BaseColumns,所以已经有了_ID
     */
    public static final class UserTableMetaData implements BaseColumns {
        /**
         * 表名
         */
        public static final String TABLE_NAME = "users";
        /**
         * 访问该ContentProvider的URI
         */
        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORIY + "/users");
        /**
         * 该ContentProvider所返回的数据类型定义
         */
        public static final String CONTENT_TYPE = "vnd.android.cursor.dir/org.juetion.user";
        public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/org.juetion.user";
        /**
         * 列名
         */
        public static final String USER_NAME = "name";
        public static final String USER_AGE = "age";
        /**
         * 默认的排序方法
         */
        public static final String DEFAULT_SORT_ORDER = "_id desc";
    }
}

2,继承ContentProvider的类:

package org.juetion.cp;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import org.juetion.sqlite3.DatabaseHelper;

import java.util.HashMap;

/**
 * Created by juetionke on 13-12-21.
 */
public class MyContentProvider extends ContentProvider {

    /**
     * 定义规则
     */
    public static final UriMatcher uriMatcher;
    public static final int USERS_COLLECTION = 1;//用于标记
    public static final int USERS_SINGLE = 2;//用于标记
    private DatabaseHelper databaseHelper;//这里的数据共享是共享Sqlite里的数据,当然,可以试用其他,如文本数据共享。
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);//试用一个没有规则的Uri。然后下面自己匹配。
        uriMatcher.addURI(MyProviderMetaData.AUTHORIY,"/users",USERS_COLLECTION);//自己定义的规则,有点像路由器,是uri匹配的方案。
        uriMatcher.addURI(MyProviderMetaData.AUTHORIY,"/users/#",USERS_SINGLE);//同上。
    }

    /**
     * 为列定义别名
     */
    public static HashMap usersMap;
    static {
        usersMap = new HashMap();
        usersMap.put(MyProviderMetaData.UserTableMetaData._ID, MyProviderMetaData.UserTableMetaData._ID);
        usersMap.put(MyProviderMetaData.UserTableMetaData.USER_NAME, MyProviderMetaData.UserTableMetaData.USER_NAME);
        usersMap.put(MyProviderMetaData.UserTableMetaData.USER_AGE, MyProviderMetaData.UserTableMetaData.USER_AGE);
    }


    @Override
    public boolean onCreate() {
        Log.i("juetion","onCreate");
        databaseHelper = new DatabaseHelper(getContext(), MyProviderMetaData.DATABASE_NAME);//这里的实现,常见前篇关于Sqlite的文章。
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Log.i("juetion","query");
        SQLiteQueryBuilder sqLiteQueryBuilder = new SQLiteQueryBuilder();//写入查询条件,有点像Hibernate。
        switch (uriMatcher.match(uri)) {//判断查询的是单个数据还是多个数据。
            case USERS_SINGLE:
                sqLiteQueryBuilder.setTables(MyProviderMetaData.UserTableMetaData.TABLE_NAME);//需要查询的表
                sqLiteQueryBuilder.setProjectionMap(usersMap);//列的别名定义
                sqLiteQueryBuilder.appendWhere(MyProviderMetaData.UserTableMetaData._ID + "=" + uri.getPathSegments().get(1));
                //查询条件,uri.getPathSegments().get(1),getPathSegments是将内容根据/划分成list。
                break;
            case USERS_COLLECTION:
                sqLiteQueryBuilder.setTables(MyProviderMetaData.UserTableMetaData.TABLE_NAME);
                sqLiteQueryBuilder.setProjectionMap(usersMap);
                break;
        }
        String orderBy;//判断sortOrder是否为空,加入默认。
        if (TextUtils.isEmpty(sortOrder)) {
            orderBy = MyProviderMetaData.UserTableMetaData.DEFAULT_SORT_ORDER;
        } else {
            orderBy = sortOrder;
        }
        SQLiteDatabase sqLiteDatabase = databaseHelper.getWritableDatabase();
        Cursor cursor = sqLiteQueryBuilder.query(sqLiteDatabase, projection, selection, selectionArgs, null, null, sortOrder);//可以使用下面的方法,不过此时sqLiteDatabase将会没有用。
        //Cursor cursor = sqLiteDatabase.query(MyProviderMetaData.UserTableMetaData.TABLE_NAME, projection, selection, selectionArgs, null, null, orderBy);
        cursor.setNotificationUri(getContext().getContentResolver(),uri);
        return cursor;
    }

    /**
     * 根据传入的URI,返回URI说表示的数据类型
     * @param uri
     * @return
     */
    @Override
    public String getType(Uri uri) {
        Log.i("juetion","getType");
        switch (uriMatcher.match(uri)) {//匹配uri的规则
            case USERS_COLLECTION:
                return MyProviderMetaData.UserTableMetaData.CONTENT_TYPE;
            case USERS_SINGLE:
                return MyProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM;
            default:
                throw new IllegalArgumentException("Unknown URI" + uri);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        Log.i("juetion","insert");
        SQLiteDatabase sqLiteDatabase = databaseHelper.getWritableDatabase();
        long rowId = sqLiteDatabase.insert(MyProviderMetaData.UserTableMetaData.TABLE_NAME, null, values);
        if (rowId > 0) {
            Uri insertUserUri = ContentUris.withAppendedId(MyProviderMetaData.UserTableMetaData.CONTENT_URI, rowId);//简单来说就是字符串拼凑一下。只不过是uri专用的。
            //通知监听器
            getContext().getContentResolver().notifyChange(insertUserUri,null);
            return insertUserUri;
        }else
            throw new IllegalArgumentException("Failed to insert row into" + uri);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        Log.i("juetion","delete");
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        Log.i("juetion","update");
        return 0;
    }
}

这两个类里面都有的对应的注释,都能看懂吧?

还有重要的一点,再第二个APP的AndroidManifest.xml里面需要添加


        

以上代码都是在第二个APP里面的。

--------我是可爱的分界线------------

以下代码是在第一个APP里面的。

关于使用。只需要将uri的string提供给第一个APP。

例如在第一个APP的Activity调用数据插入:

ContentValues contentValues = new ContentValues();
                    contentValues.put("name","zhangsan");
                    contentValues.put("age",19);
                    Uri uri = getContentResolver().insert(Uri.parse("content://org.juetion.cp.MyContentProvider/users"),contentValues);
                    Log.i("juetion", "insert uri-->" + uri.toString());

例如在第一个APP的Activity调用数据的查询:

Cursor cursor = getContentResolver().query(Uri.parse("content://org.juetion.cp.MyContentProvider/users"),
                            new String[]{"name", "age"},
                            null, null, null);
                    while (cursor.moveToNext()) {
                        Log.i("juetion", cursor.getString(cursor.getColumnIndex("name")));
                    }

正如上面的例子,使用的时候是在Activity里面调用getContentResolver()的。

代码下载链接:http://download.csdn.net/detail/juetion/6752125

今月今日的学习温故到此结束了,谢谢观看。



你可能感兴趣的:(android)