文章目录
- 一 运行时权限
- 2.权限分类
- 3 运行时申请权限
- 二、内容提供器
- 1、 ContentResolver的基本用法
- 2、现有的内容提供器
- 3、创建自己的内容提供器
- 2.1 创建内容提供器的步骤
- 2.2 跨程序数据共享
内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。
一 运行时权限
Android的权限机制,从系统的第一个版本开始就已经存在了。但其实之前Android的权限机制在保护用户安全和隐私等方面起到的作用比较有限,尤其是一些大家都离不开的常用软件,非常容易“店大欺客”。为此,Android开发团队在Android 6.0系统中引用了运行时权限这个功能,从而更好地保护了用户的安全和隐私。
2.权限分类
Android现在将所有的权限归成了三类,一类是普通权限,一类是危险权限,一类是特殊权限(不讨论)
- 普通权限:指的是那些不会直接威胁到用户的安全和隐私的权限,对于这部分权限申请,系统会自动帮我们进行授权,而不需要用户再去手动操作了。
- 危险权限:则表示那些可能会触及用户隐私或者对设备安全性造成影响的权限,如获取设备联系人信息、定位设备的地理位置等,对于这部分权限申请,必须要由用户手动点击授权才可以,否则程序就无法使用相应的功能。
访问:安卓完整权限列表可以查看Android系统中完整的权限列表。
3 运行时申请权限
- 第一步就是要先判断用户是不是已经给过我们授权了。checkSelfPermission(Context,具体权限名)。
- 没有授权的话,则需要调用ActivityCompat. requestPermissions(Activity的实例,申请的权限名,请求码)方法来向用户申请授权
public void onClick(View view) {
if (ContextCompat.checkSelfPermission(MainActivity.this,
android.Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{android.Manifest.permission.CALL_PHONE},1);
}else {
call();
}
}
注:代码相对书本更新,Manifest.permission.CALL_PHONE
改为android.Manifest.permission.CALL_PHONE
否则报错
- 申请授权后不论申请成功还是失败都会回调onRequestPermissionsResult方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
call();
}else {
Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
}
break;
default:
}
}
二、内容提供器
1、 ContentResolver的基本用法
通过Context中的getContentResolver()方法获取到该类的实例。 该类提供一系列方法对数据进行CRUD操作。ContentResolver中的增删改查方法都是不接收表名参数的,而是使用一个Uri参数代替,这个参数被称为内容URI,安卓对一些URI进行了封装。
URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:authority和path。
- authority是用于对不同的应用程序做区分的,一般采用程序包名的方式来进行命名。
- path则是用于对同一应用程序中不同的表做区分的,通常都会添加到authority的后面。
- 一个标准的内容Uri:content://com.example.databasetest.provider/table1,表示想调用方期望访问com.example.databasetest这个应用的table1表中的数据。
- 如果在这个Uri后面加一个id,例如content://com.example.databasetest.provider/table1/1,期望访问table1表中id为1的数据
Uri newUri = getContentResolver().insert(uri, values);
getContentResolver().delete(uri,null,null);
getContentResolver().update(uri,values,null,null);
Cursor cursor = getContentResolver().query(uri, null, null,
null, null);
2、现有的内容提供器
读取和操作相应程序中的数据。如读取系统联系人,系统中有联系人列表的提供器。
-
申请运行时权限,参照1.3部分。
-
查询联系人数据,如下列代码所示,第一个参数为URI对象(系统对这个对象做了封装)
-
在清单文件中声明读取系统联系人的权限
<uses-permission android:name="android.permission.CALL_PHONE"/>
-
效果图
3、创建自己的内容提供器
给我们程序的数据提供外部访问接口。
2.1 创建内容提供器的步骤
-
在com.example.databasetest包下新建MyProvider继承ContentProvider,并重写6个抽象类方法(alt+shift+enter)。
-
在静态代码块中创建UriMatcher的实例
static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY,"book",BOOK_DIR); uriMatcher.addURI(AUTHORITY,"book/#",BOOK_ITEM); uriMatcher.addURI(AUTHORITY,"category",CATEGORY_DIR); uriMatcher.addURI(AUTHORITY,"category/#",CATEGORY_ITEM); }
-
写CRUD方法
-
写getType方法,必须以vnd开头。Uri以路径结尾,vnd后接.android.cursor.dir,Uri以id结尾,vnd后接.android.cursor.item。
@Override
public String getType(Uri uri) {
// TODO: Implement this to handle requests for the MIME type of the data
// at the given URI.
// throw new UnsupportedOperationException("Not yet implemented");
switch (uriMatcher.match(uri)){
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.com.example.databasetest.provider.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.com.example.databasetest.provider.category";
}
return null;
}
- 在清单文件中注册该provider
<provider
android:name=".DatabaseProvider"
android:authorities="com.example.databasetest.provider"
android:enabled="true"
android:exported="true">
</provider>
使用下列方式生成的provider,会在清单文件中自动注册。
2.2 跨程序数据共享
新建ProviderTets 项目,在该项目下访问DatabaseTest中数据库的数据。
代码更新:按照书上的执行报错,解决办法
在ProviderTets 的清单文件中添加如下声明:第一行是内容提供器所在的包名,第二行是内容提供器的authority。
<queries android:name="com.example.databasetest"/>
<queries><provider android:authorities="com.example.databasetest.provider"/></queries>