Android ContentProvider 的实现步骤

作者:陆金龙    发表时间:2018-04-18 23:37   


1.为ContentProvider提供一个常量类 MyContentProviderMetaData.java
public class MyContentProviderMetaData {
   //URI的指定,此处的字符串必须和声明的authorities一致
public static final String AUTHORITIES = "com.zhuanghongji.app.MyContentProvider";
   //数据库名称
   public static final String DATABASE_NAME = "myContentProvider.db";
   //数据库的版本
   public static final int DATABASE_VERSION = 1;
   //表名 
   public static final String USERS_TABLE_NAME = "user";
   
   public static final class UserTableMetaData implements BaseColumns{
       //表名
       public static final String TABLE_NAME = "user";
       //访问该ContentProvider的URI
       public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITIES + "/user");
       //该ContentProvider所返回的数据类型的定义
       public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.myprovider.user";
       public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.myprovider.user";
       //列名
       public static final String USER_NAME = "name";
       //默认的排序方法
       public static final String DEFAULT_SORT_ORDER = "_id desc";
   } 
}
 
2.自定义一个类,继承ContentProvider,重写6个方法
public class MyContentProvider extends ContentProvider {
   //访问表的多行
   public static final int INCOMING_USER_COLLECTION = 1;
   //访问的单条记录
   public static final int INCOMING_USER_SINGLE = 2;
   //操作URI的类
   public static final UriMatcher uriMatcher;
  
     //为UriMatcher添加自定义的URI
   static{
       uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
       uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user",
           INCOMING_USER_COLLECTION);
       uriMatcher.addURI(MyContentProviderMetaData.AUTHORITIES,"/user/#",
           INCOMING_USER_SINGLE);
   }
   
   private DatabaseHelper dh;
   //为数据库表字段起别名
   public static HashMap userProjectionMap;
   static
   {
       userProjectionMap = new HashMap();
       userProjectionMap.put(UserTableMetaData._ID,UserTableMetaData._ID);
       userProjectionMap.put(UserTableMetaData.USER_NAME, UserTableMetaData.USER_NAME);
   }
 
   /**
   * 删除表数据
   */
   @Override
   public int delete(Uri uri, String selection, String[] selectionArgs) {
       System.out.println("delete");
       //得到一个可写的数据库
       SQLiteDatabase db = dh.getWritableDatabase();
       //执行删除,得到删除的行数
       int count = db.delete(UserTableMetaData.TABLE_NAME, selection, selectionArgs);
       
       return count;
   }
   
   /**
   * 数据库访问类型
   */
   @Override
   public String getType(Uri uri) {
       System.out.println("getType");
       //根据用户请求,得到数据类型
       switch (uriMatcher.match(uri)) {
           case INCOMING_USER_COLLECTION:
               return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE;
           case INCOMING_USER_SINGLE:
               return MyContentProviderMetaData.UserTableMetaData.CONTENT_TYPE_ITEM;
           default:
               throw new IllegalArgumentException("UnKnown URI"+uri);
       }
   }
   
   /**
   * 插入数据
   */
   @Override
   public Uri insert(Uri uri, ContentValues values) {
       //得到一个可写的数据库
       SQLiteDatabase db = dh.getWritableDatabase();
       //向指定的表插入数据,得到返回的Id
       long rowId = db.insert(UserTableMetaData.TABLE_NAME, null, values);
       if(rowId > 0){ // 判断插入是否执行成功
           //如果添加成功,利用新添加的Id和
           Uri insertedUserUri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
           //通知监听器,数据已经改变
           getContext().getContentResolver().notifyChange(insertedUserUri, null);   
           return insertedUserUri;
       }   
       return uri;
   }
   
   /**
   * 创建ContentProvider时调用的回调函数
   */
   @Override
   public boolean onCreate() {
       System.out.println("onCreate");
       //得到数据库帮助类
       dh = new DatabaseHelper(getContext(),MyContentProviderMetaData.DATABASE_NAME);
       return false;
   }
   
   /**
   * 查询数据库
   */
   @Override
   public Cursor query(Uri uri, String[] projection, String selection,
   String[] selectionArgs, String sortOrder) {
       //创建一个执行查询的Sqlite
       SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
       //判断用户请求,查询所有还是单个
       switch(uriMatcher.match(uri)){
           case INCOMING_USER_COLLECTION:
               //设置要查询的表名
               qb.setTables(UserTableMetaData.TABLE_NAME);
               //设置表字段的别名
               qb.setProjectionMap(userProjectionMap);
               break;
           case INCOMING_USER_SINGLE:
               qb.setTables(UserTableMetaData.TABLE_NAME);
               qb.setProjectionMap(userProjectionMap);
               // 追加条件,getPathSegments()得到用户请求的Uri地址截取的数组,
               // get(1)得到去掉地址中/以后的第二个元素
               qb.appendWhere(UserTableMetaData._ID + "=" + uri.getPathSegments().get(1));
               break;
       }
       //设置排序
       String orderBy;
       if(TextUtils.isEmpty(sortOrder)){
           orderBy = UserTableMetaData.DEFAULT_SORT_ORDER;
       } else {
           orderBy = sortOrder;
       }
       //得到一个可读的数据库
       SQLiteDatabase db = dh.getReadableDatabase();
       //执行查询,把输入传入
       Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
       //设置监听
       c.setNotificationUri(getContext().getContentResolver(), uri);
       return c;
   }
   
   /**
   * 更新数据库
   */
   @Override
   public int update(Uri uri, ContentValues values, String selection,
   String[] selectionArgs) {
       System.out.println("update");
       //得到一个可写的数据库
       SQLiteDatabase db = dh.getWritableDatabase();
       //执行更新语句,得到更新的条数
       int count = db.update(UserTableMetaData.TABLE_NAME, values, selection, selectionArgs);
       return count;
   }
  
}
3. 在AndroidMinifest.xml中进行声明

 
4. 使用示例
 
为应用程序添加ContentProvider的访问权限。
通过getContentResolver()方法得到ContentResolver对象。
调用ContentResolver类的query()方法查询数据,该方法会返回一个Cursor对象。
对得到的Cursor对象进行分析,得到需要的数据。
调用Cursor类的close()方法将Cursor对象关闭。
 
public class MyContentProviderDemo extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        insertRecord(”MyUser”);
        displayRecords();
    }
 
    private void insertRecord(String userName) {
        ContentValues values = new ContentValues();
        values.put(MyContentProviderMetaData .UserTableMetaData .USER_NAME, userName);
        getContentResolver().insert(MyContentProviderMetaData .UserTableMetaData .CONTENT_URI, values);
    }
 
    private void displayRecords() {
        String columns[] = new String[] {MyContentProviderMetaData .UserTableMetaData._ID, MyContentProviderMetaData .UserTableMetaData.USER_NAME };
        Uri uri = ContentProviderMetaData .UserTableMetaData.CONTENT_URI;
        Cursor cur =  getContentResolver().query(uri , columns,null, null, null );
        if (cur.moveToFirst()) {
            String id = null;
            String userName = null;
            do {
                id = cur.getString(cur.getColumnIndex(MyContentProviderMetaData .UserTableMetaData._ID));
                userName = cur.getString(cur.getColumnIndex(MyContentProviderMetaData .UserTableMetaData.USER_NAME));
                Toast.makeText(this, id + ” ” + userName, Toast.LENGTH_LONG).show();
           } while (cur.moveToNext());
       }
    }
}