Android 6.0运行时权限小结
来源:互联网 发布:荷兰蒂尔堡大学 知乎 编辑:程序博客网 时间:2024/05/22 04:47
本文基于googlesamples-android-RuntimePermissions进行分析。
一、权限分类
Normal Permissions:普通权限,不需要授权管理
ACCESS_LOCATION_EXTRA_COMMANDSACCESS_NETWORK_STATEACCESS_NOTIFICATION_POLICYACCESS_WIFI_STATEBLUETOOTHBLUETOOTH_ADMINBROADCAST_STICKYCHANGE_NETWORK_STATECHANGE_WIFI_MULTICAST_STATECHANGE_WIFI_STATEDISABLE_KEYGUARDEXPAND_STATUS_BARGET_PACKAGE_SIZEINSTALL_SHORTCUTINTERNETKILL_BACKGROUND_PROCESSESMODIFY_AUDIO_SETTINGSNFCREAD_SYNC_SETTINGSREAD_SYNC_STATSRECEIVE_BOOT_COMPLETEDREORDER_TASKSREQUEST_INSTALL_PACKAGESSET_ALARMSET_TIME_ZONESET_WALLPAPERSET_WALLPAPER_HINTSTRANSMIT_IRUNINSTALL_SHORTCUTUSE_FINGERPRINTVIBRATEWAKE_LOCKWRITE_SYNC_SETTINGS
Dangerous Permission:危险权限,涉及用户隐身,需要授权管理
group:android.permission-group.CONTACTS permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTSgroup:android.permission-group.PHONE permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAILgroup:android.permission-group.CALENDAR permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDARgroup:android.permission-group.CAMERA permission:android.permission.CAMERAgroup:android.permission-group.SENSORS permission:android.permission.BODY_SENSORSgroup:android.permission-group.LOCATION permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATIONgroup:android.permission-group.STORAGE permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGEgroup:android.permission-group.MICROPHONE permission:android.permission.RECORD_AUDIOgroup:android.permission-group.SMS permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS需要说明的是,系统的授权管理是以组为单位来授权的,请求某个组的某个权限,也相当于请求该组权限,如果用户同意授权,就相当于对整组权限都进行了授权,当请求该组其他权限的时候,就不需要请求授权了。
二、权限使用与授权
对应权限的使用,跟以前是一样的,唯一不同的就是增加了授权管理这一环节。
1、AndroidManifest中进行权限声明。
下面来看看android-RuntimePermissions中的AndroidManifest文件。
<!-- BEGIN_INCLUDE(manifest) --><!-- Note that all required permissions are declared here in the Android manifest. On Android M and above, use of these permissions is only requested at run time. --><uses-permission android:name="android.permission.CAMERA"/><!-- The following permissions are only requested if the device is on M or above. On older platforms these permissions are not requested and will not be available. --><uses-permission-sdk-m android:name="android.permission.READ_CONTACTS" /><uses-permission-sdk-m android:name="android.permission.WRITE_CONTACTS" /><!-- END_INCLUDE(manifest) -->可以看到上面有两种声明形式,这个跟之前是有些不同的,uses-permission是普通的权限声明,uses-permission-sdk-m表示只有在Android M及其以上的设备上才声明该权限,在之前的版本是不用该权限,就相当于没有声明一样。
上面可以看到,声明了三种权限,其中READ_CONTACTS和WRITE_CONTACTS在android M及其以上版本才使用。它们都是危险权限。
所以在代码中,先需要进行系统版本判断,如果是低于Android M的系统,就不能使用READ_CONTACTS和WRITE_CONTACTS这两个权限。因为它只在android M及其以上版本才声明。
// BEGIN_INCLUDE(m_only_permission)if (Build.VERSION.SDK_INT < 23) { /* The contacts permissions have been declared in the AndroidManifest for Android M and above only. They are not available on older platforms, so we are hiding the button to access the contacts database. This shows how new runtime-only permissions can be added, that do not apply to older platform versions. This can be useful for automated updates where additional permissions might prompt the user on upgrade. */ root.findViewById(R.id.button_contacts).setVisibility(View.GONE);}// END_INCLUDE(m_only_permission)上面进行判断,如果系统版本低于23,就将READ_CONTACTS和WRITE_CONTACTS请求的按钮隐藏。
二、授权管理的过程
下面来看看授权管理的过程。
当我们需要使用某个权限的时候,例如我们要打开摄像头,这个时候,就需要首先进行CAMERA权限检查,看该权限是否已经授权。这个授权可以在设置中进行设置,默认是没有授权。
public void showCamera(View view) { Log.i(TAG, "Show camera button pressed. Checking permission."); // BEGIN_INCLUDE(camera_permission) // Check if the Camera permission is already available. if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // Camera permission has not been granted. requestCameraPermission(); } else { // Camera permissions is already available, show the camera preview. Log.i(TAG, "CAMERA permission has already been granted. Displaying camera preview."); showCameraPreview(); } // END_INCLUDE(camera_permission)}上面的核心代码就是上面的if判断语句。如果没有授权就会进行权限请求,执行requestCameraPermission()方法。
private void requestCameraPermission() { Log.i(TAG, "CAMERA permission has NOT been granted. Requesting permission."); // BEGIN_INCLUDE(camera_permission_request) if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { // Provide an additional rationale to the user if the permission was not granted // and the user would benefit from additional context for the use of the permission. // For example if the user has previously denied the permission. Log.i(TAG, "Displaying camera permission rationale to provide additional context."); Snackbar.make(mLayout, R.string.permission_camera_rationale, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.ok, new View.OnClickListener() { @Override public void onClick(View view) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA); } }) .show(); } else { // Camera permission has not been granted yet. Request it directly. ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA); } // END_INCLUDE(camera_permission_request)}上面在权限请求之前,执行了ActivityCompat.shouldShowRequestPermissionRationale()方法,当第一次进行某个权限请求的时候,它返回为false,当再次请求该权限的时候,它返回true,目的就是可以给开发者一个接口,来说明为什么屡次请求使用该权限。可以看到在上面代码中,当再次请求的时候,它使用了一个Snackbar弹出一条消息进行说明,如果用户同意就进行请求该权限。说白了,就是为了提供一个比较好的交互效果,并且提供开发者向用户一个解释的机会。
当调用ActivityCompat.requestPermissions()的时候,就会有一个弹框,这个是系统弹出来的,用户需要进行选择是否同意授权,用户选择之后,就会回调onRequestPermissionsResult()方法,它会把用户的选择结果给带回来,所以我们需要实现ActivityCompat.OnRequestPermissionsResultCallback接口的该方法。
@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_CAMERA) { // BEGIN_INCLUDE(permission_result) // Received permission result for camera permission. Log.i(TAG, "Received response for Camera permission request."); // Check if the only required permission has been granted if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Camera permission has been granted, preview can be displayed Log.i(TAG, "CAMERA permission has now been granted. Showing preview."); Snackbar.make(mLayout, R.string.permision_available_camera, Snackbar.LENGTH_SHORT).show(); } else { Log.i(TAG, "CAMERA permission was NOT granted."); Snackbar.make(mLayout, R.string.permissions_not_granted, Snackbar.LENGTH_SHORT).show(); } // END_INCLUDE(permission_result) } else if (requestCode == REQUEST_CONTACTS) { Log.i(TAG, "Received response for contact permissions request."); // We have requested multiple permissions for contacts, so all of them need to be // checked. if (PermissionUtil.verifyPermissions(grantResults)) { // All required permissions have been granted, display contacts fragment. Snackbar.make(mLayout, R.string.permision_available_contacts, Snackbar.LENGTH_SHORT) .show(); } else { Log.i(TAG, "Contacts permissions were NOT granted."); Snackbar.make(mLayout, R.string.permissions_not_granted, Snackbar.LENGTH_SHORT) .show(); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); }}细心的人可能看到,在我们进行权限请求的时候,也就是执行ActivityCompat.requestPermissions()方法的时候,它的第三个参数是一个请求码,在上面onRequestPermissionsResult()方法的回调中,第一个参数就是将这个请求码给带回来了,第二个参数就是用户请求的权限,第三个参数就是用户请求的结果。可以看到返回的结果是一个数组,这个我们可以看看前面的请求函数ActivityCompat.requestPermissions(),它的第二个参数为我们要请求的权限,可以看到,它是一个数组,所以返回的请求结果也是一个数组,它对应的就是每个权限的请求结果。
public static boolean verifyPermissions(int[] grantResults) { // At least one result must be checked. if(grantResults.length < 1){ return false; } // Verify that each required permission has been granted, otherwise return false. for (int result : grantResults) { Log.i("PermissionUtil", "result" + result); if (result != PackageManager.PERMISSION_GRANTED) { return false; } } return true;}它是对返回结果数组的每个结果进行判断,只要有一个权限为拒绝,则就返回为false。
0 0
- Android 6.0运行时权限小结
- Android 6.0运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- Android 6.0+ 运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- android 6.0运行时权限
- android 6.0运行时权限
- Android 6.0 运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- Android 6.0 运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- Android 6.0 运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- Matlab函数重载_变参数个数
- 通过反射机制获取某个类的所有属性,打印属性值,并思考以下问题:可以更改属性值吗?
- Thinkpad E440设置U盘启动的问题
- 【机房重组】 职责链模式
- The server encountered an internal error that prevented it from fulfilling this request的一种解决办法
- Android 6.0运行时权限小结
- red hat忘记管理员密码处理方法
- HDU 5666 Segment(大数+gcd)
- 在CentOS 7 安装Calamari
- KVO/KVC 实现机理分析
- JQuery学习笔记
- 【bzoj1266】【AHOI2006】【上学路线】【最短路+最小割】
- 优化问题的对偶问题
- for循环问题