Android动态权限管理
Android6.0以后,应用权限分为静态权限和动态权限,下表是需要动态申请的权限。
描述 | 权限代码 |
调用相机权限 | CAMERA |
日历权限 | READ_CALENDAR |
WRITE_CALENDAR | |
通讯录权限 | READ_CONTACTS |
WRITE_CONTACTS | |
GET_ACCOUNTS | |
定位权限 | ACCESS_FINE_LOCATION |
ACCESS_COARSE_LOCATION | |
录音权限 | RECORD_AUDIO |
手机状态相关 | READ_PHONE_STATE |
CALL_PHONE | |
READ_CALL_LOG | |
WRITE_CALL_LOG | |
ADD_VOICEMAIL | |
传感器权限 | BODY_SENSORS |
SMS消息权限 | SEND_SMS |
RECEIVE_SMS | |
READ_SMS | |
RECEIVE_WAP_PUSH | |
RECEIVE_MMS | |
外部存储权限 | READ_EXTERNAL_STORAGE |
WRITE_EXTERNAL_STORAGE |
权限注册
要使用相关权限,首先必须在AndroidManifest.xml中注册响应权限,才能在代码中动态申请。
示例:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
权限申请
多数应用在安装后启动的第一时间向用户申请权限,为了方便用户操作,可以在启动页完成权限申请代码。以获取位置信息为例:
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED){
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
//这里可以写个对话框之类的项向用户解释为什么要申请权限,并在对话框的确认键后续再次申请权限
} else {
//申请权限,字符串数组内是一个或多个要申请的权限,1是申请权限结果的返回参数,在onRequestPermissionsResult可以得知申请结果
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
}else {
// TODO
}
权限管理有三种状态
- 允许
- 禁止
- 询问
应用安装时,默认为询问状态,应用可发起申请,用户许可后,状态为允许,用户不许可,则状态更改为禁止。
每次进行相应操作时,都需要判断是否授予了对应的权限,若不作判断,权限状态不为允许时,应用会崩溃。
ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED
返回true即已获取到权限
状态修改
当权限状态处于询问或者禁止时,且部分手机无法收到申请弹窗(生无可恋魅族脸.jpg),这时,需要引导用户跳转到设置界面,手动开启权限。
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
intent.setData(uri);
startActivity(intent);
权限开启了,但功能未开启,同样需要引导用户开启功能,以获取位置信息为例。
检测功能是否开启:
locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)
返回值为Boolean类型,true表示已开启。若返回值为flash,则引导用户跳转到设置页面,开启功能。
// 转到手机设置界面,用户设置GPS
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
// 设置完成后返回到原来的界面
startActivityForResult(intent, 0);