Android ContentProvider内容提供者详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android ContentProvider内容提供者详解相关的知识,希望对你有一定的参考价值。

前言:为什么要有ContentProvider?

Android

ContentProvider 内容提供者:可以实现在不同程序之间数据共享的功能,同时还能够保证被访问的数据的安全性。

ContentProvider的理解

Android


相关的API如下所示

Android

Android

Android

Android

两个重要知识点:

1.数据模型: ConentProvider使用基于数据模型的简单表格来提供其中的数据。 每一行代表一条记录,每一列代表特定类型,和含义的数据

2. Uri :统一资源标识符,比较笼统的定位了资源,不局限于客户端和服务器

结构如下:

Android


下面创建一个应用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();

从通讯录中便获取到了联系人姓名:

Android


以上是关于Android ContentProvider内容提供者详解的主要内容,如果未能解决你的问题,请参考以下文章

Android面试四大组件之内容提供者ContentProvider

Android四大组件之一:ContentProvider(内容提供者)

ContentProvider内容提供者-Android

Android 四大组件学习之ContentProvider三

Android组件系列----ContentProvider内容提供者

ContentProvider简要说明