现在Android6.0以上系统的手机都需要申请权限啦.开发者再也不能随意的上传用户的手机信息,不能随意的拿到存储空间,通讯录等信息了,此时就需要对权限做一次申请,当用户同意后才可进行操作.
由于每个Android应用程序都在一个进程沙箱中运行,因此应用程序必须明确请求访问其沙箱外的资源和数据。他们通过声明他们所需的权限来申请这个访问权限,以获得基本沙箱不提供的附加功能。根据区域的敏感程度,系统可以自动授予权限,也可以提示用户批准或拒绝请求。
Google官方权限介绍 https://developer.android.google.cn/guide/topics/permissions/requesting.html#permissions
权限组
普通权限(PROTECTION_NORMAL)
普通权限可以直接在清单文件Manifast
中注册即用,从API级别23开始,以下权限分类为PROTECTION_NORMAL:以下为普通权限:
权限 | 用途 |
---|---|
ACCESS_LOCATION_EXTRA_COMMANDS | 允许应用程序访问额外的位置提供程序命令。 |
ACCESS_NETWORK_STATE | 允许应用程序访问有关网络的信息。 |
ACCESS_NOTIFICATION_POLICY | 对希望访问通知政策的应用程序的标记许可。 |
ACCESS_WIFI_STATE | 允许应用程式存取有关Wi-Fi网路的资讯。 |
BLUETOOTH | 允许应用程序连接到配对的蓝牙设备。 |
BLUETOOTH_ADMIN | 允许应用程式发现并配对蓝牙装置。 |
BROADCAST_STICKY | 允许应用程式广播粘性意图。 |
CHANGE_NETWORK_STATE | 允许应用程序更改网络连接状态。 |
CHANGE_WIFI_MULTICAST_STATE | 允许应用程序进入Wi-Fi多播模式。 |
CHANGE_WIFI_STATE | 允许应用程式更改Wi-Fi连线状态。 |
DISABLE_KEYGUARD | 允许应用程序在不安全的情况下禁用键盘锁。 |
EXPAND_STATUS_BAR | 允许应用程序展开或折叠状态栏。 |
GET_PACKAGE_SIZE | 允许应用程序查找任何包使用的空间。 |
INSTALL_SHORTCUT | 允许应用程序在Launcher中安装快捷方式。 |
INTERNET | 允许应用程序使用网络。 |
KILL_BACKGROUND_PROCESSES | 允许应用程序调用 killBackgroundProcesses(String)。 |
MODIFY_AUDIO_SETTINGS | 允许应用修改全局音频设置。 |
NFC | 允许应用程序通过NFC执行I / O操作。 |
READ_SYNC_SETTINGS | 允许应用程式读取同步设定。 |
READ_SYNC_STATS | 允许应用程序读取同步统计信息。 |
RECEIVE_BOOT_COMPLETED | 允许应用程序ACTION_BOOT_COMPLETED在系统完成启动后接收 广播。 |
REORDER_TASKS | 允许应用程序更改任务的Z顺序。 |
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS | 应用程序必须持有许可才能使用 ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS。 |
REQUEST_INSTALL_PACKAGES | 允许应用程序请求安装软件包。 |
SET_ALARM | 允许应用程序广播一个意图为用户设置警报。 |
SET_TIME_ZONE | 允许应用程序设置系统时区。 |
SET_WALLPAPER | 允许应用程式设定墙纸。 |
SET_WALLPAPER_HINTS | 允许应用程式设定壁纸提示。 |
TRANSMIT_IR | 允许使用设备的红外发射器(如果有的话)。 |
UNINSTALL_SHORTCUT | 此权限不再受支持。 |
USE_FINGERPRINT | 允许应用使用指纹硬件。 |
VIBRATE | 允许访问振动器。 |
WAKE_LOCK | 允许使用电源管理器唤醒锁定功能,让处理器免于睡眠或屏幕变暗。 |
WRITE_SYNC_SETTINGS | 允许应用程式写入同步设定。 |
这些权限直接写到清单文件中即可使用,
危险权限和权限组(Dangerous permissions and permission groups)
权限组中的权限只需申请一个即可使用权限组内其他权限,但是一样的需要在Manifast
中注册
权限组 | 权限 | 说明 |
---|---|---|
CALENDAR | • READ_CALENDAR • WRITE_CALENDAR |
• 用于与用户日历相关的运行时权限。 |
CAMERA | • CAMERA | • 用于与访问摄像头或从设备捕捉图像/视频相关联的权限。 |
CONTACTS | • READ_CONTACTS • WRITE_CONTACTS • GET_ACCOUNTS |
• 用于与此设备上的联系人和配置文件相关的运行时权限。 |
LOCATION | • ACCESS_FINE_LOCATION • ACCESS_COARSE_LOCATION |
• 用于允许访问设备位置的权限。 |
MICROPHONE | • RECORD_AUDIO | • 用于与从设备访问麦克风音频相关联的权限。 |
PHONE | • READ_PHONE_STATE • READ_PHONE_NUMBERS • CALL_PHONE • ANSWER_PHONE_CALLS(必须在运行时请求) • READ_CALL_LOG • WRITE_CALL_LOG • ADD_VOICEMAIL • USE_SIP • PROCESS_OUTGOING_CALLS |
• 用于与电话功能关联的权限。 |
SENSORS | • BODY_SENSORS | • 用于与访问摄像头或从设备捕捉图像/视频相关联的权限。 |
SMS | • SEND_SMS • RECEIVE_SMS • READ_SMS • RECEIVE_WAP_PUSH • RECEIVE_MMS |
• 用于与用户的SMS消息相关的运行时权限。 |
STORAGE | • READ_EXTERNAL_STORAGE • WRITE_EXTERNAL_STORAGE |
• 用于与共享外部存储相关的运行时权限。 |
权限申请
单个权限申请
我们先申请一个内部存储权限READ_EXTERNAL_STORAGE
- 首先在
Manifast.xml
中添加权限
1 | <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> |
检查是否拥有权限
1 | int permissionCheck = ContextCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE); |
完整的检查权限封装1
2
3
4
5
6
7
8
9
10//检查是否拥有单一权限
public static boolean checkPermission(Activity activity, String permission) {
int permissionCheck = ContextCompat.checkSelfPermission(activity, permission);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
return true;
} else if (permissionCheck == PackageManager.PERMISSION_DENIED) {
return false;
}
return false;
}
判断权限是否被拒绝过
1 | ActivityCompat.shouldShowRequestPermissionRationale(activity, permission) |
1 | if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) { |
权限返回状态处理
1 |
|
requestCode是请求权限时的权限码,permissions是权限集合,单个权限的话取`permissions[0]即可
1 | //请求权限返回接口 |
多个权限申请思路
要申请多个权限,可以循环判断权限是否拥有,再将没有拥有的权限添加到集合中
1 | String[] arr = permissionList.toArray(new String[permissionList.size()]); |
权限的返回结果也需要进行判断
第三方权限申请库
RxPermisssion
RxPermission是一个非常好用的第三方权限申请库,由RxJava支持
请在GitHub上使用最新的版本 https://github.com/tbruyelle/RxPermissions
Glide1
compile 'com.tbruyelle.rxpermissions:rxpermissions:0.9.4@aar'
初始化1
RxPermissions rxPermissions = new RxPermissions(this); // where this is an Activity instance
- 请求单个权限
1
2
3
4
5
6
7
8
9
10// 必须在初始化阶段 如onCreate中
rxPermissions
.request(Manifest.permission.CAMERA)
.subscribe(granted -> {
if (granted) { // Always true pre-M
// 已经获取了相机权限
} else {
// 权限被拒绝
}
});
注: granted ->
是Retrolambda 写法,Android Studio3.0已全面支持Java8
请求多个权限并统一处理
1
2
3
4
5
6
7
8
9
10rxPermissions
.request(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.subscribe(granted -> {
if (granted) {
// 获得了所有权限
} else {
// 并未获得所有权限
}
});请求多个权限并分别判定处理
1
2
3
4
5
6
7
8
9
10
11
12
13rxPermissions
.requestEach(Manifest.permission.CAMERA,
Manifest.permission.READ_PHONE_STATE)
.subscribe(permission -> { // will emit 2 Permission objects
if (permission.granted) {
// `permission.name` is granted !
} else if (permission.shouldShowRequestPermissionRationale) {
// Denied permission without ask never again
} else {
// Denied permission with ask never again
// Need to go to the settings
}
});