ContentProvider虽然与Activity、Service、BroadcastReceiver齐名为Android四大组件。如果你不是特别开发一款与其他APP有数据交互的应用,它的使用频率远没有另外三者高。因为已经介绍了前三大组件,为了完善Android四大组件介绍了解,这次补充下ContentProvider介绍。哈哈~一边在看世界杯,巴西打瑞士。目前巴西1:0。我把所有金币全压巴西了~题外话说完,下面简单介绍下ContentProvider。
一. ContentProvider简介和常见使用场景:
Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。但是我们知道一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,例如我们需要操作系统里的媒体库、通讯录等,这时我们就可能通过ContentProvider来满足我们的需求了。
由此我们知道,ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。使用ContentProvider可以在不同的应用程序之间共享数据。Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。总结就是: ContentProvider一般为存储和获取数据提供统一的接口,可以在不同的应用程序之间共享数据。
二.ContentProvider 常见的几个类:
1.ContentResolver
Android为我们提供了ContentResolver来统一管理与不同ContentProvider间的操作。
调用getContentResolver()
来获得ContentResolver。
ContentResolver是如何来区别不同的ContentProvider的呢?这就涉及到URI(Uniform Resource Identifier)问题。
2.URI
ContentProvider中的URI有固定格式,如下图:
Authority:授权信息,用以区别不同的ContentProvider;
Path:表名,用以区分ContentProvider中不同的数据表;
Id:Id号,用以区别表中的不同数据;
三.ContentProvider查询手机通讯录联系人信息示例:
private TextView tv_query_contacts;
private TextView tv_info_contacts;
String[] premiss = new String[]{
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_info_contacts = findViewById(R.id.tv_info_contacts);
tv_query_contacts = findViewById(R.id.query_contacts);
tv_query_contacts.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
checkPresmissed();
}
});
}
/**
* 查询手机通讯录所有联系人名称
*/
private void queryContacts() {
Uri urlContacts = Uri.parse("content://com.android.contacts/contacts");
ContentResolver contentResolver = getContentResolver();
Cursor cursorsContacts = contentResolver.query(urlContacts, new String[]{ContactsContract.Data._ID}, null, null, null);
StringBuilder stringBuilder = new StringBuilder();
while (cursorsContacts.moveToNext()) {
Uri uriPhone = Uri.parse("content://com.android.contacts/contacts/" + cursorsContacts.getInt(0) + "/data");
Cursor cursorPhone = contentResolver.query(uriPhone, new String[]{ContactsContract.Data.DATA1, ContactsContract.Data.MIMETYPE}, null, null, null);
while (cursorPhone.moveToNext()) {
if(cursorPhone.getString(cursorPhone.getColumnIndex("mimetype")).equals("vnd.android.cursor.item/name")){
//姓名
stringBuilder.append(cursorPhone.getString(cursorPhone.getColumnIndex("data1")));
}
}
}
tv_query_contacts.setText("");
tv_info_contacts.setText(stringBuilder.toString());
}
private void checkPresmissed() {
/**
* 第 1 步: 检查是否有相应的权限
*/
boolean isAllGranted = checkPermissionAllGranted(
new String[]{
Manifest.permission.READ_CONTACTS,
Manifest.permission.WRITE_CONTACTS
}
);
// 如果这3个权限全都拥有, 则直接执行备份代码
if (isAllGranted) {
queryContacts();
} else {
/**
* 第 2 步: 请求权限
*/
// 一次请求多个权限, 如果其他有权限是已经授予的将会自动忽略掉
ActivityCompat.requestPermissions(this, premiss, 11);
}
}
/**
* 检查是否拥有指定的所有权限
*/
private boolean checkPermissionAllGranted(String[] permissions) {
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
// 只要有一个权限没有被授予, 则直接返回 false
return false;
}
}
return true;
}
//授权回调
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 11) {
queryContacts();
}
}