Android笔记— Android 权限详解
资料来源如下
- 第一行代码(第二版)
- android6.0运行时权限详解
编程环境
- Android Studio 2.2.3
导语
- 内容提供器是安全的应用间共享数据途径,在正式进入之前需要了解一下 Android 自6.0以来权限的变化
Android 权限详解
资料来源:
- android6.0运行时权限详解
- Develop-API Guides-系统权限
- 第一行代码(第二版)
Android权限介绍
Android 是一个权限分隔的操作系统
每个应用系统标识(Linux 用户 ID 和组 ID)不同。系统各部分标识亦不相同。Linux 据此将不同的应用以及应用与系统分隔开来。
更详细的安全功能通过“权限”提供,权限 会限制特定进程可以执行的具体操作,并且根据 URI 权限授权临时访问特定的数据段权限声明
最常见的权限声明在 AndroidManifest.xml 文件中一个或多个uses-permission 标记,- 例如 声明短信权限
1
2
3
4
5<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.app.myapp" >
<uses-permission android:name="android.permission.RECEIVE_SMS" />
...
</manifest>
- 例如 声明短信权限
android 6.0 权限机制
android 6.0之前 权限及在安装的时候,根据权限声明产生一个权限列表,用户只有在同意之后才能完成app的安装。
android 6.0 以后 引入了 运行时权限 功能,应用所需权限不再一次性在安装时申请,而是在运行时需要用到那种权限向用户申请,同时用户也可以随时取消该授权权限分类
- Normal Permissions(普通权限)
不涉及用户隐私,不需要用户进行授权的,例如 手机震动、访问网络等 - Dangerous Permission(危险权限)
涉及到用户隐私的,需要用户进行授权,例如 读取sdcard、访问通讯录等
危险权限组如表1
- Normal Permissions(普通权限)
应用运行时申请权限(适用于 Android6.0 及以上版本)
- 通过一个简单的实例来说明过程
实例:
拨打电话 CALL_PHONE _权限为例
- 权限声明
1
<uses-permission android:name="android.permission.CALL_PHONE"/>
- 权限声明
拨打10010
- 代码如下 构建一个隐式intent 启动拨打电话
1
2
3Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10010"));
startActivity(intent);
- 代码如下 构建一个隐式intent 启动拨打电话
在主界面上添加一个Button 在其onClick方法中拨打电话,运行程序!
- 在An’d’roid 6.0 以下版本中 电话都可以正常拨出。Android 6.0 以上版本中 则可能会应用崩溃/无反应,查看logcat的打印日志可以看到 “Permission Denial”权限被禁止的信息,接下来尝试使用 运行时申请权限
检查是否已获得授权
int checkSelfPermission(Context context, String permission)方法- Context context context
String permission 权限具体名称
打电话对应 Manifest.permission.CALL_PHONE _ - 方法返回 PERMISSION_GRANTED / PERMISSION_DENIED
- 例程
1
2
3
4
5
6
7
8if(ContextCompat.checkSelfPermission
(MainActivity.this,Manifest.permission.CALL_PHONE)
!=PackageManager.PERMISSION_GRANTED)
{
;
}else {
;
}
- Context context context
申请权限
void ActivityCompat.requestPermissions (Activity activity, String[] permissions, int requestCode)方法Activity activity Activity实例
String[] permissions 请求权限名
int requestCode 请求码,大于0即可,对应在onRequestPermissionsResult 回掉方法中的requestCode例程
1
2ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CALL_PHONE},1 );
授权后回掉
无论用户是否授权都会进入回掉方法,需要重写该方法。
void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)方法int requestCode 在 requestPermissions 中传入的请求码
String[] permissions 请求的权限,不为空
int[] grantResults 授权结果 只有 PERMISSION_GRANTED / PERMISSION_DENIED 两个值例程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
//请求码 1
case 1:
//授权结果(int) 的 长度是否大于0 与上 授权结果是否等于 PackageManager.PERMISSION_GRANTED
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//授权通过执行
} else {
//授权没有通过
}
break;
default:
}
}
当用户拒绝后再次询问
boolean ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission) (真心太长了)- Activity activity Activity实例
String permission 权限名称
应用第一次需要授权时,用户授权,该方法返回false。当用户拒绝授权,下次需要该权限时,该方法会返回true - 例程
1
2
3
4
5
6
7if (ActivityCompat.shouldShowRequestPermissionRationale
(PermissionActivity.this,Manifest.permission.READ_CONTACTS))
{
//第二次询问用户是否授权
}else{
//用户依旧拒绝后操作
}
- Activity activity Activity实例
例程源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void Button(View view){
if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE},1 );
}else {
call();
}
}
private void call() {
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10010"));
startActivity(intent);
} catch (SecurityException e) {
e.printStackTrace();
}
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] 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
2
3
4
5<Button
android:onClick="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />