内容提供器(Content Provider)用于在不同的应用程序之间实现数据共享的功能,同时还能保证被访数据的安全性。目前,使用内容提供器是Android实现跨程序共享数据的标准方式。
运行时权限
安卓将权限分成普通权限和危险权限。区别在是否威胁到用户的安全和隐私。
涉及到普通权限的操作系统会自动授权,涉及到危险权限的操作需要向安卓系统申请权限许可。
在安卓6.0之前,涉及到危险的权限,直接在androidmanifest.xml里面写userpermission就可以实现。但是在更高版本的安卓中不可以。
高版本安卓需要申请运行时权限。
public void onCreate(){
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.READ_CONTACTS}, 1);
}
else {
readContacts();
}
}
//内容读取:读取联系人的信息
private void readContacts() {
Cursor cursor = null;
try {
//查询联系人数据:
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
if (cursor != null){
while (cursor.moveToNext()) {
//获取联系人姓名:
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
//获取联系人手机号
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName + "\n" + number);
}
adapter.notifyDataSetChanged();
}
}catch (Exception e){
e.printStackTrace();
}
finally {
if (cursor != null){
cursor.close();
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
readContacts();
}
else {
Toast.makeText(this, "you denied the permission", Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
第一步就是要先判断用户是不是已经给过我们授权了,借助的是ContextCompat.checkSelfPermission()方法。ContextCompat.checkSelfPermission()接受2个参数,第一个参数是context,然后是想要查询的权限。
调用ActivityCompat. requestPermissions()方法来向用户申请授权。
requestPermissions()方法接收3个参数,第一个参数要求是Activity的实例,第二个参数是一个String数组,我们把要申请的权限名放在数组中即可,第三个参数是请求码,只要是唯一值就可以了,这里传入了1。调用完了requestPermissions()方法之后,系统会弹出一个权限申请的对话框,然后用户可以选择同意或拒绝我们的权限申请,不论是哪种结果,最终都会回调到onRequest-PermissionsResult()方法中,而授权的结果则会封装在grantResults参数当中。这里我们只需要判断一下最后的授权结果,如果用户同意的话就调用call()方法来拨打电话,如果用户拒绝的话我们只能放弃操作,并且弹出一条失败提示。
private boolean isStoragePermissionGranted() {
if (Build.VERSION.SDK_INT >= 23) {
final Context context = getApplicationContext();
int readPermissionCheck = ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_EXTERNAL_STORAGE);
int writePermissionCheck = ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (readPermissionCheck == PackageManager.PERMISSION_GRANTED
&& writePermissionCheck == PackageManager.PERMISSION_GRANTED) {
Log.v("juno", "Permission is granted");
return true;
} else {
Log.v("juno", "Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
return false;
}
} else { //permission is automatically granted on sdk<23 upon installation
Log.v(TAG, "Permission is granted");
return true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Log.v("juno", "onRequestPermissionsResult requestCode : " + requestCode
+ " Permission: " + permissions[0] + " was " + grantResults[0]
+ " Permission: " + permissions[1] + " was " + grantResults[1]
);
访问其他程序的数据
使用现有的Content provider
使用简介
要获取设备上的文件,比如多媒体。可以通过2种方式。一种是遍历磁盘目录上的所有文件,通过后缀名找到。一种是通过安卓系统提供的 Media Provider
提出查询请求。当然最简单的方式是使用 Media Provider
.
Content Provider可以为其他程序提供内容。私有的:只能为所在应用程序提供数据访问请求. exported = "false"
。公用的:为所有程序提供数据访问请求。exported = "true"
。使用前注意在AndroidManifest.xml文件中注册。
借助context.getContentResolver()方法获取到ContentResolver实例,定义有insert(), update(), delete(), query()方法。
增删改查方法都是不接收表名参数的,而是使用一个Uri参数代替,这个参数被称为内容URI。内容URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authority和path。authority是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名。比如某个程序的包名是com.example. app,那么该程序对应的authority就可以命名为com.example.app. provider。path则是用于对同一应用程序中不同的表做区分的,通常都会添加到authority的后面。比如某个程序的数据库里存在两张表:table1和table2,这时就可以将path分别命名为/table1和/table2,然后把authority和path进行组合,内容URI就变成了com.example.app.provider/table1和com.example.app.provider/table2。不过,目前还很难辨认出这两个字符串就是两个内容URI,我们还需要在字符串的头部加上协议声明。因此,内容URI最标准的格式写法如下:
传入了URL字符串,需要解析成URI对象,uri
ContentProvider还有notifyChange()方法,提醒数据变动。
https://blog.csdn.net/hb8676086/article/details/50164947
Cursor简介
Cursor是游标,储存数据,是行的集合。
在你理解和使用 Android Cursor 的时候你必须先知道关于 Cursor 的几件事情:
- Cursor 是每行的集合。
- 使用 moveToFirst() 定位第一行。
- 你必须知道每一列的名称。
- 你必须知道每一列的数据类型。
- Cursor 是一个随机的数据源。
- 所有的数据都是通过下标取得。
从cursor对象中取出数据:
向table1中添加数据:先添加数据到values里面,然后通过insert()方法,传入uri(之前已经绑定为table1)和values
项目实现:读取联系人信息
//实现内容接收:
ListView contactsView = (ListView) findViewById(R.id.contacts_view);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, contactsList);//使用ArrayAdapter实现
contactsView.setAdapter(adapter);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_CONTACTS)!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.READ_CONTACTS}, 1);
}
else {
readContacts();
}
//内容读取:读取联系人的信息
private void readContacts() {
Cursor cursor = null;
try {
//查询联系人数据:
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
if (cursor != null){
while (cursor.moveToNext()) {
//获取联系人姓名:
String displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
//获取联系人手机号
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName + "\n" + number);
}
adapter.notifyDataSetChanged();
}
}catch (Exception e){
e.printStackTrace();
}
finally {
if (cursor != null){
cursor.close();
}
}
}
创建自己的Content provider
步骤
新建一个类继承ContentProvider(),重写6大方法,分别是:
- onCreate()
- query()
- delete()
- insert()
- update()
- getType()
项目实现
没必要继续看了。我不是专门写应用程序的,因此不需要知道具体的实现。