前言:为什么要有ContentProvider?
ContentProvider 内容提供者:可以实现在不同程序之间数据共享的功能,同时还能够保证被访问的数据的安全性。
ContentProvider的理解
相关的API如下所示
两个重要知识点:
1.数据模型: ConentProvider使用基于数据模型的简单表格来提供其中的数据。 每一行代表一条记录,每一列代表特定类型,和含义的数据
2. Uri :统一资源标识符,比较笼统的定位了资源,不局限于客户端和服务器
结构如下:
下面创建一个应用A,提供数据并创建ContentProvider,供应用B进行增删改查的操作
应用A
1、创建PersonContentProvider类
/** * 操作person表的provider类 */ public class PersonContentProvider extends ContentProvider { //用来存放所有合法的Uri容器 private static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); //保存一些合法的Uri //content://com.example.customviewproject.personcontentprovider/person 不根据id操作 //content://com.example.customviewproject.personcontentprovider/person/3 根据id操作 static { uriMatcher.addURI("com.example.customviewproject.personcontentprovider", "/person", 1); uriMatcher.addURI("com.example.customviewproject.personcontentprovider", "/person/#", 2);//#匹配任意数字 } private DBHelper dbHelper; public PersonContentProvider() { Log.i("TAG", "PersonContentProvider() "); } @Override public boolean onCreate() { Log.i("TAG", "onCreate() "); dbHelper = new DBHelper(getContext()); return false; } /** * //content://com.example.customviewproject.personcontentprovider/person 不根据id查询 * //content://com.example.customviewproject.personcontentprovider/person/3 根据id查询 */ @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { Log.i("TAG", "query() "); //得到连接对象 SQLiteDatabase database = dbHelper.getReadableDatabase(); //1.匹配uri,返回code int code = uriMatcher.match(uri); //2.如果合法,进行查询 if (code == 1) {//不根据id查询 Cursor cursor = database.query("person", projection, selection, selectionArgs, null, null, null); return cursor; } else if (code == 2) {//根据id查询 //得到id long id = ContentUris.parseId(uri); //查询 Cursor cursor = database.query("person", projection, "_id=?", new String[]{id + ""}, null, null, null); return cursor; } else {//3.如果不合法,抛出异常 throw new RuntimeException("查询的URI不合法"); } } /** * //content://com.example.customviewproject.personcontentprovider/person 插入 * //content://com.example.customviewproject.personcontentprovider/person/3 根据id插入(没有) */ @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { Log.i("TAG", "insert() "); //得到连接对象 SQLiteDatabase database = dbHelper.getReadableDatabase(); //1.匹配uri,返回code int code = uriMatcher.match(uri); //2.如果合法,进行插入 if (code == 1) { long id = database.insert("person", null, values); //将id添加到uri中 database.close(); return ContentUris.withAppendedId(uri, id); } else { database.close(); throw new RuntimeException("插入的URI不合法"); } } /** * //content://com.example.customviewproject.personcontentprovider/person 不根据id删除 * //content://com.example.customviewproject.personcontentprovider/person/3 根据id删除 */ @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { Log.i("TAG", "delete() "); //得到连接对象 SQLiteDatabase database = dbHelper.getReadableDatabase(); //1.匹配uri,返回code int code = uriMatcher.match(uri); int deleteCount = -1; //2.如果合法,进行删除 if (code == 1) { deleteCount = database.delete("person", selection, selectionArgs); } else if (code == 2) { long id = ContentUris.parseId(uri); deleteCount = database.delete("person", "_id=" + id, null); } else { throw new RuntimeException("删除的URI不合法"); } return deleteCount; } /** * //content://com.example.customviewproject.personcontentprovider/person 不根据id更新 * //content://com.example.customviewproject.personcontentprovider/person/3 根据id更新 */ @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { Log.i("TAG", "update() "); //得到连接对象 SQLiteDatabase database = dbHelper.getReadableDatabase(); //1.匹配uri,返回code int code = uriMatcher.match(uri); int deleteCount = -1; //2.如果合法,进行更新 if (code == 1) {//不根据id更新 deleteCount = database.update("person", values, selection, selectionArgs); } else if (code == 2) { long id = ContentUris.parseId(uri); deleteCount = database.update("person", values, "_id=" + id, null); } return deleteCount; } @Nullable @Override public String getType(@NonNull Uri uri) { Log.i("TAG", "getType() "); return null; } }
2、在AndroidManifest.xml中注册provider
<!--authorities 自定义:一般是内容提供者类的全类名,全部小写--> <!--enabled:表示是否启动内容提供者--> <!--exported:表示是否允许该内容提供者接收本程序以外的对数据的操作 默认不允许false--> <provider android:name=".content.PersonContentProvider" android:authorities="com.example.customviewproject.personcontentprovider" android:enabled="true" android:exported="true" />
当应用A启动后,就会创建PersonContentProvider类对象
打印的日志如下
I/TAG: PersonContentProvider() I/TAG: onCreate()
应用B 通过ContentResolver对应用A中的数据进行增删改查操作
public class MainActivity extends AppCompatActivity { private Button btn_query; private Button btn_insert; private Button btn_delete; private Button btn_update; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_query = findViewById(R.id.btn_query); btn_insert = findViewById(R.id.btn_insert); btn_delete = findViewById(R.id.btn_delete); btn_update = findViewById(R.id.btn_update); btn_query.setOnClickListener(onClickListener); btn_insert.setOnClickListener(onClickListener); btn_delete.setOnClickListener(onClickListener); btn_update.setOnClickListener(onClickListener); } private final View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { case R.id.btn_query: query(); break; case R.id.btn_insert: insert(); break; case R.id.btn_update: update(); break; case R.id.btn_delete: delete(); break; default: break; } } }; /** * 通过ContentResolver调用ContentProvider删除一条记录 */ private void delete() { //1.得到ContentResolver对象 ContentResolver resolver = getContentResolver(); //2.调用其insert Uri uri = Uri.parse("content://com.example.customviewproject.personcontentprovider/person/2"); int deleteCount = resolver.delete(uri, null, null); Toast.makeText(this, "deleteCount=" + deleteCount, Toast.LENGTH_SHORT).show(); } /** * 通过ContentResolver调用ContentProvider更新一条记录 */ private void update() { //1.得到ContentResolver对象 ContentResolver resolver = getContentResolver(); //2.调用其insert Uri uri = Uri.parse("content://com.example.customviewproject.personcontentprovider/person/3"); ContentValues contentValues = new ContentValues(); contentValues.put("name", "Jack2"); int updateCount = resolver.update(uri, contentValues, null, null); Toast.makeText(this, "updateCount=" + updateCount, Toast.LENGTH_SHORT).show(); } /** * 通过ContentResolver调用ContentProvider插入一条记录 */ private void insert() { //1.得到ContentResolver对象 ContentResolver resolver = getContentResolver(); //2.调用其insert Uri uri = Uri.parse("content://com.example.customviewproject.personcontentprovider/person"); ContentValues contentValues = new ContentValues(); contentValues.put("name", "Jack"); uri = resolver.insert(uri, contentValues); Toast.makeText(this, uri.toString(), Toast.LENGTH_SHORT).show(); } /** * 通过ContentResolver调用ContentProvider查询所有记录 */ private void query() { //1.得到ContentResolver对象 ContentResolver resolver = getContentResolver(); //2.调用其query,得到cursor // Uri uri = Uri.parse("content://com.example.customviewproject.personcontentprovider/person/1"); //查询所有 Uri uri = Uri.parse("content://com.example.customviewproject.personcontentprovider/person"); Cursor cursor = resolver.query(uri, null, null, null, null); //3.取出cursor中的数据,并显示 while (cursor.moveToNext()) { int id = cursor.getInt(0); String name = cursor.getString(1); // Toast.makeText(this, id + ":" + name, Toast.LENGTH_SHORT).show(); Log.i("TAG", id + ":" + name); } cursor.close(); } }
效果就不展示了,能对应用A中的数据库表进行CRUD操作。
接下来我们通过Content Provider 读取通讯录中所有的联系人姓名:
布局代码就不贴出来了。
主要是Activity代码:
详细注解已经在代码中给出
public class ContentProviderActivity extends AppCompatActivity { private TextView tv_phone; private String name = ContactsContract.Contacts.DISPLAY_NAME;//获得通讯录中的姓名 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_content_provider); tv_phone = findViewById(R.id.tv_phone); //显示获取的通讯录信息 tv_phone.setText(getQueryData()); } private CharSequence getQueryData(){ //用于保存获取的联系人姓名 StringBuilder stringBuilder = new StringBuilder(); ContentResolver resolver = getContentResolver(); //通过通讯录进行查询 Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null); //获得姓名记录的索引值 int displayNameIndex = cursor.getColumnIndex(name); for (cursor.moveToFirst(); !cursor.isAfterLast() ; cursor.moveToNext()) { String display = cursor.getString(displayNameIndex); stringBuilder.append(display+"\n"); } cursor.close(); //返回查询的结果 return stringBuilder.toString(); } }
从通讯录中便获取到了联系人姓名: