Content Provider:内容提供者
- 应用程序间共享数据的一种方式
- 为存储和获取数据提供了统一的接口
- Android为常见的一些数据提供了默认的 Content Provider
- 四大组件之一
定义
- 内容提供者将一些特定的应用程序数据供给其他应用程序使用
- 数据可以存储于文件系统、SQLite数据库或其他方式
- 内容提供者继承于ContentProvider基类,为其他应用程序取用和存储它管理的数据实现了一套标准方法
- 应用程序并不是直接调用这些方法,而是使用ContentResolver对象,调用它的方法作为替代
- ContentResolver 可以与任意内容提供者进行会话,与其合作来对所有相关交互通讯进行管理
ContentProvider实现过程
Database --> Uri --> UriMatcher --> ContentProvider -- > query/insert/update/delete --> AndroidManifest.xml
系统提供的Provider
获取系统的通讯录信息
public class PhoneBookInfo extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_book_info);
ListView lvInfo = (ListView) findViewById(R.id.phoneBookInfo_lvInfo);
List stringList = new ArrayList<>();
ArrayAdapter arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, stringList);
lvInfo.setAdapter(arrayAdapter);
//查询通讯录数据
//由于要读取通讯录,所以要在manifest中加上"android.permission.READ_CONTACTS"的权限
Cursor cursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,null,null,null);
if (cursor!=null && cursor.moveToFirst()){
for (int i = 0; i < cursor.getCount(); i++) {
String disPlayName = cursor.getString(
cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
);
String number = cursor.getString(
cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)
);
arrayAdapter.add(disPlayName + "\n" + number);
cursor.moveToNext();
}
}
}
}
自定义Content Provider
URI后面还以加上 *** 或 #分别表示:
- *:表示匹配任意长度的任意字符
#
:表示匹配任意长度的数字
-
DataBase:创建一个继承SQLiteOpenHelper的类,并创建
user
、book
两个表。public class DataBaseHelper extends SQLiteOpenHelper { public static final String DATABASE = "test.db"; public static final int VERSION = 1; public static final String TABLENAME_USER = "user"; public static final String USER_NAME = TABLENAME_USER + "_name"; public static final String USER_AGE = TABLENAME_USER + "_age"; public static final String TABLENAME_BOOK = "book"; public static final String BOOK_NAME = TABLENAME_BOOK + "_name"; public static final String BOOK_WRITER = TABLENAME_BOOK + "_writer"; public DataBaseHelper(Context context) { super(context, DATABASE, null, VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table " + TABLENAME_USER + " (" + USER_NAME + " TEXT not null, " + USER_AGE + " TEXT not null )" ); db.execSQL("create table " + TABLENAME_BOOK + " (" + BOOK_NAME + " TEXT not null, " + BOOK_WRITER + " TEXT not null ) " ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
-
Uri:创建UriList.java
-
创建一个继承ContentProvider的类,然后设置UriMatcher和完善重构方法:
public class TestContentProvider extends ContentProvider { //初始UriMatcher private static UriMatcher sUriMatcher; public static final int UriMatcher_CODE_USER = 1; public static final int UriMatcher_CODE_BOOK = 2; static { sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); sUriMatcher.addURI(UriList.AUTHORITY, DataBaseHelper.TABLENAME_USER, UriMatcher_CODE_USER); sUriMatcher.addURI(UriList.AUTHORITY, DataBaseHelper.TABLENAME_BOOK, UriMatcher_CODE_BOOK); } private DataBaseHelper mDataBaseHelper; @Override public boolean onCreate() { //获取数据库 mDataBaseHelper = new DataBaseHelper(getContext()); return true; } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //从数据库中query Cursor cursor = mDataBaseHelper.getReadableDatabase().query(getTableName(uri), projection, selection, selectionArgs, null, null, sortOrder); return cursor; } @Nullable @Override public String getType(Uri uri) { return null; } @Nullable @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase sqLiteDatabase = mDataBaseHelper.getWritableDatabase(); Long id; id = sqLiteDatabase.insert(getTableName(uri), null, values); //“withAppendedId”:将uri和id连接起来(即uri/id) //“parseId(Uri contentUri)”:这个方法负责把contentURI 后边的id解析出来,即返回值是“id” return ContentUris.withAppendedId(uri, id); } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { if(TextUtils.isEmpty(getTableName(uri))){ return -1; } int count = mDataBaseHelper.getWritableDatabase().delete(getTableName(uri), selection, selectionArgs); return count; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return mDataBaseHelper.getWritableDatabase().update(getTableName(uri), values, selection, selectionArgs); } //获取表名 private String getTableName(Uri uri) { int code = sUriMatcher.match(uri); String tableName = ""; switch (code) { case UriMatcher_CODE_USER: tableName = DataBaseHelper.TABLENAME_USER; break; case UriMatcher_CODE_BOOK: tableName = DataBaseHelper.TABLENAME_BOOK; break; } return tableName; } }
-
设置完ContentProvider之后就可以在相应功能里进行query/insert/update/delete方法,如:
@Override public void onClick(View v) { ContentResolver contentResolver = getContentResolver(); switch (v.getId()){ //查询 case R.id.provider_btnQuery: mStringList.clear(); Cursor cursor = contentResolver.query(UriList.Book_Uri,null,null,null,null); if (cursor!= null && cursor.moveToFirst()){ String KeyValue1 = cursor.getString(cursor.getColumnIndexOrThrow(DataBaseHelper.BOOK_NAME)); String KeyValue2 = cursor.getString(cursor.getColumnIndexOrThrow(DataBaseHelper.BOOK_WRITER)); mStringList.add(KeyValue1+"\n"+KeyValue2); cursor.moveToNext(); } mAdapter.notifyDataSetChanged(); break; //删除 case R.id.provider_btnDelet: contentResolver.delete(UriList.Book_Uri, null, null); break; //插入 case R.id.provider_btnInsert: ContentValues contentValues = new ContentValues(); contentValues.put(DataBaseHelper.BOOK_NAME, mEdtKeyValue1.getText().toString()); contentValues.put(DataBaseHelper.BOOK_WRITER, mEdtKeyValue2.getText().toString()); contentResolver.insert(UriList.Book_Uri, contentValues); break; //修改 case R.id.provider_btnUpdate: ContentValues values = new ContentValues(); values.put(DataBaseHelper.BOOK_NAME, mEdtKeyValue1.getText().toString()); values.put(DataBaseHelper.BOOK_WRITER, mEdtKeyValue2.getText().toString()); contentResolver.update(UriList.Book_Uri, values, null, null); break; } }
-
最后记得在manifest.xml中声明ContentProvider:
要注意的是authorities
的值是与上面的AUTHORITY
的值一样;
exported
设置为true
可以跨应用使用这个ContentProvider。