简介:
ContentProvider 是内容提供者
ContentResolver 内容解析者
ContentProvider 在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给其他应用访问,其他应用可以通过ContentProvider 对你应用中的数据进行添删改查。 关于数据共享,以前我们学习过文件操作模式,知道通过指定文件的操作模式为Context.MODE_WORLD_READABLE 或Context.MODE_WORLD_WRITEABLE同样也可以对外共享数据。 那么,这里为何要使用ContentProvider 对外共享数据呢?是这样的,如果采用文件操作模式对外共享数据,数据的访问方式会因数据存储的方式而不同,导致数据的访问方式无法统一,如:采用xml文件对外共享数据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读取数据。 使用ContentProvider对外共享数据的好处是统一了数据的访问方式。 ContentProvider的原理是按照一定规则暴露自己的接口给其它应用来访问自己应用的数据(其实就是自定义增删改查接口并暴露出去,让别的应用访问自己的数据)。 ContentResolver就是按照一定规则访问内容提供者的数据(其实就是调用内容提供者自定义的接口来操作它的数据)。 |
系统中提供的 ContentProvider 都需要使用 ContentResolver 来操作,操作方式,
在任何一个 Context 环境下均可以使用 getContentResolver() 拿到ContentResolver 对象
查询:
private void readSms(){
// 短信的 Uri
Uri uri = Uri.parse("content://sms");
// 查询的字段
String[] columns = {"_id","address","type","body"};
// 查询
Cursor c = getContentResolver().query(uri,columns,null,null,null);
StringBuilder sb = new StringBuilder();
while(c.moveToNext()){
int id = c.getInt(0);
String address = c.getString(1);
int type = c.getInt(2);
String body = c.getString(3);
sb.append(id).append("\t").append(address).append("\t")
.append(type).append("\t").append(body).append("\n");
}
c.close();
tvResult.setText(sb.toString());
}
注意: 6.0 以上针对部分数据(联系人,短信)需要动态申请权限
动态申请权限
1 、检测权限是否被授权
// 检测是否授权
int permissionState = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS);
if(permissionState == PackageManager.PERMISSION_GRANTED){
//已授权
}
2 、如果未授权则需要申请权限
requestPermissions(new String[]{Manifest.permission.READ_SMS},REQUST_READ_SMS);
3 、处理申请结果,需要在 Activity 中重写 onRequestPermissionsResult 方法
以申请读短信为例
检测和申请
// 检测当前系统是否是 6.0 以上
if(Build.VERSION.SDK_INT >= 23){
// 检测是否授权
int permissionState = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS);
if(permissionState == PackageManager.PERMISSION_GRANTED){
// 表示已经授权
readSms();
} else {
// 申请权限
requestPermissions(new String[]{Manifest.permission.READ_SMS},REQUST_READ_SMS);
}
} else {
readSms();
}
结果处理
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if(requestCode == REQUST_READ_SMS){
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
// 授权成功
readSms();
}else{
// 是否需要跟用户解释为什么要申请该权限
if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.READ_SMS)){
// 解释一下
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle(" 警告 ");
b.setMessage(" 不授权将无法显示数据 ");
b.setPositiveButton(" 确认 ", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if(Build.VERSION.SDK_INT >= 23){
requestPermissions(new String[]{Manifest.permission.READ_SMS}
,REQUST_READ_SMS);
}
}
});
b.setNegativeButton(" 取消 ",null);
b.show();
}
}
}
}
[ 附 ]
Android6.0 之后需要单独申请的权限
共分为 9 组,每组只要有一个权限申请成功了,就默认整组权限都可以使用了
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:com.android.voicemail.permission.ADD_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
Android 普通权限,只需要在 AndroidManifest.xml 中声明即可
android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_NOTIFICATION_POLICY
android.permission.ACCESS_WIFI_STATE
android.permission.ACCESS_WIMAX_STATE
android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN
android.permission.BROADCAST_STICKY
android.permission.CHANGE_NETWORK_STATE
android.permission.CHANGE_WIFI_MULTICAST_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.CHANGE_WIMAX_STATE
android.permission.DISABLE_KEYGUARD
android.permission.EXPAND_STATUS_BAR
android.permission.FLASHLIGHT
android.permission.GET_ACCOUNTS
android.permission.GET_PACKAGE_SIZE
android.permission.INTERNET
android.permission.KILL_BACKGROUND_PROCESSES
android.permission.MODIFY_AUDIO_SETTINGS
android.permission.NFC
android.permission.READ_SYNC_SETTINGS
android.permission.READ_SYNC_STATS
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.REORDER_TASKS
android.permission.REQUEST_INSTALL_PACKAGES
android.permission.SET_TIME_ZONE
android.permission.SET_WALLPAPER
android.permission.SET_WALLPAPER_HINTS
android.permission.SUBSCRIBED_FEEDS_READ
android.permission.TRANSMIT_IR
android.permission.USE_FINGERPRINT
android.permission.VIBRATE
android.permission.WAKE_LOCK
android.permission.WRITE_SYNC_SETTINGS
com.android.alarm.permission.SET_ALARM
com.android.launcher.permission.INSTALL_SHORTCUT
com.android.launcher.permission.UNINSTALL_SHORTCUT
加载所有的图片
private void readImages() {
Cursor c = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI
,null, null, null, null);
StringBuilder sb = new StringBuilder();
while (c.moveToNext()) {
int id = c.getInt(c.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
String title = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE));
String data = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
sb.append(id).append("\t").append(title).append("\t").append(data).append("\n");
// 获取缩略图
//Bitmap thumb = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver()
, id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
}
c.close();
tvResult.setText(sb.toString());
}
说明: ActivityCompat 继承自 ContextCompat 均属于 v4 包中的兼容类, ActivityCompat 向低版本提供高版本 Activity 的新功能方法, ContextCompat 向低版本提
供高版本中的 Context 的新功能方法
加载视频
private void readVideo(){
Cursor c = getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI
, null, null, null, null);
StringBuilder sb = new StringBuilder();
while (c.moveToNext()) {
int id = c.getInt(c.getColumnIndexOrThrow(MediaStore.Video.Media._ID));
String title = c.getString(c.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE));
String data = c.getString(c.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
sb.append(id).append("\t").append(title).append("\t").append(data).append("\n");
// 获取缩略图
//if(Build.VERSION.SDK_INT >=10){
// MediaMetadataRetriever mr = new MediaMetadataRetriever();
// mr.setDataSource(data);
// Bitmap b = mr.getFrameAtTime();
//}else{
// Bitmap thumb = ThumbnailUtils.createVideoThumbnail(data
,MediaStore.Images.Thumbnails.MICRO_KIND);
// }
}
c.close();
tvResult.setText(sb.toString());
}
加载所有音频
private void readAudio(){
Cursor c = getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
, null, null, null, null);
StringBuilder sb = new StringBuilder();
while (c.moveToNext()) {
int id = c.getInt(c.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
String title = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
String data = c.getString(c.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
sb.append(id).append("\t").append(title).append("\t").append(data).append("\n");
}
c.close();
tvResult.setText(sb.toString());
}