网上关于安卓动态权限申请的文章很多,但是毕竟眼花缭乱,所以下面我将根据自己的理解和在网上获取到的信息对动态权限申请进行小小的总结,以便以后再次接触安卓的时候能够拿出来看!
- 下面有几组需要动态申请的权限,据说在每一组中,只需要成功申请一组即可。申请需要在AndroidManifest.xml中添加对应的代码:
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
group: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_VOICEMAIL
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
group: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
- 需要注意,无论是动态权限申请还是其他权限的申请,都需要在AndroidManifest.xml文件中进行申请。对于动态权限还需要在对应的java文件中用代码进行动态权限的申请。接下来的内容主要是在.java文件中进行动态权限申请的代码的介绍。
--今天没有进行研究,我想得过几天再进行研究,然后再进行总结,今天带外甥仔忘记了^ _ ^ 早点休息吧(2018/1/17 23:55)
好了,现在继续我们的总结,首先,先给一个链接,这个是google官方的关于运行时动态申请权限的代码,在github上,喜欢的话可以fork到你的github账户中,点这里进行查看。
在下面我的介绍中,我也是基于官方文档的,因为规则是人家定的,你必须遵循人家的标准。总的来说,在java代码中动态申请权限分为三个大的步骤,步骤一是检查是否已经获得了权限,步骤二则在步骤一没有获取到权限的时候进行动态权限的申请,步骤三则在回调函数中实现相应的操作。
下面我将以申请手机拍照的权限作为例子来总结分析:
在官方文档的注释当中,有几句话是很重要的,我摘抄在下面:
* This Activity requests permissions to access the camera ({@link android.Manifest.permission#CAMERA})
* when the 'Show Camera' button is clicked to display the camera preview.
* First, permissions are checked if they have already been granted through {@link
* ActivityCompat#checkSelfPermission(Context, String)}.
* If permissions have not been granted, they are requested through
* {@link ActivityCompat#requestPermissions(Activity, String[], int)} and the return value checked
* in
* a callback to the {@link android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
* interface.
这里表达的意思和我前面总结的三个步骤其实是一样的。
接下来,我们来看具体的代码,首先是一个showCamera()函数:
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语句里面的判断条件所示的代码,在这里拿出来展示,以便看得更加清晰:
ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
其实原理很简单,就是使用ActivityCompat.checkSelfPermission(Context, String)来判断是否已经获得了权限,如果其返回值等于PackageManager.PERMISSION_GRANTED则已经获得,否则没有获得权限。函数中的第一个参数是Context参数,即上下文,这个一般是this(fragment中则一般是getActivity()),第二个参数是String类型的参数,表示的是申请的动态权限的类型,比如这里需要申请Camera的权限,则是Manifest.permission.CAMERA,如果是其他,则填上相应的即可,关于这个我会在文章后面进行一个总结。
判断完之后,如果已经获得了权限,则我们可以用我们定义的方法打开相机,完成相应的操作;否则,我们要动态申请权限,即进行步骤二,我们用了另外一个函数来写申请相机权限的过程,代码如下:
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(this,Manifest.permission.CAMERA)这个函数来检测用户是否设定了申请权限时弹出一些东西来提示是否允许使用相应的权限,如果是,那么就定制相应的提示,比如这里就使用了一个Snackbar来提醒用户进行权限的申请;如果用户没有设定,那么直接进行权限的申请,而不告知用户。申请权限的函数是:
ActivityCompat.requestPermissions(Activity, String[], int)
第一个参数是Context,第二个参数是申请的权限的字符串数组,因为有时需要申请的权限不止一个,第三个参数则是请求码,这里已经定义了它的值:REQUEST_CAMERA = 0,关于不同的权限的请求码将会在文章的后面进行总结。
最后,我们进行最后一个步骤,即实现回调函数,只需要重写onRequestPermissionsResult(int requestCode, String[] permissions, 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)
}
在这个回调函数中,根据申请权限时返回的信息来判断权限是否申请成功,从而用Snackbar来给用户相应的提示,告诉用户权限申请成功与否。