Android 6.0后,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。Android官网上也有相关教程:在运行时请求权限。但教程是使用支持库来举例的,用支持库的话,APK的大小也会变得很大,实际上,不使用支持库来请求权限也不难。
下面以请求写储存权限来举例。
一、声明权限
必需要在AndriodManifest.xml文件中声明权限,才能申请使用权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
二、检查权限
如果您的应用需要危险权限,则每次执行需要这一权限的操作时您都必须检查自己是否具有该权限,如果用户之前有授予权限,刚会一直具有该权限,除非用户手动在设置中关闭它。这里可以直接调用context对象中的checkPermission()方法来进行是否有某一项权限的检查,如果具有该权限则返回true,因此我们可以直接调用Activity中的checkPermission()方法。具体代码如下:
private boolean doCheckPermission(String permission) {
//检查权限
int permissionCheck = checkPermission(permission, Process.myPid(), Process.myUid());
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
return true;
}
return false;
}
checkPermission()方法有三个参数,参数的说明如下:
String permission:
要检查的权限名称,如:Manifest.permission.WRITE_EXTERNAL_STORAGE。
int pid
进程ID,可以通过Process.myPid()方法获取。
int uid
用户ID,这个可以通过Process.myUid()方法获取。
三、请求权限
检查完权限后,如果具有该权限,则可以直接运行依赖该权限的代码,如果没有该权限则需要申请该权限。可以调用Activity中的requestPermissions()方法来请求权限,具体代码如下:
private final int MY_WRITE_REQUEST_CODE = 0;
private void doRequestPermission(String permission) {
if (Build.VERSION.SDK_INT >= 23) {
//requestPermissions()方法需要SDK23
requestPermissions(new String[]{permission}, MY_WRITE_REQUEST_CODE);
}
}
requestPermissions()方法有两个参数:
String[] permissions
要申请的多个权限。
int requestCode
请求代码,用于处理请求时,唯一识别这个请求,在下面的处理请求模块要用到。
使用requestPermissions()请求权限时,需要注意的是:这个方法的调用是异步的,它会立即返回,并且在用户响应对话框之后,系统会使用结果调用应用的回调方法。也就是说,调用这个方法后,会继续执行接下来的语句,所以不能在这个方法后马上执行依赖该权限的代码。而是要等到用户授权后,系统自动调用相应的回调方法,在回调方法(下面介绍)中处理依赖该权限的代码。
四、处理权限请求响应
我们需要重写Activity中的onRequestPermissionsResult()方法来处理请求的结果。当用户允许或者拒绝该权限时,系统会调用Activity中的onRequestPermissionsResult()方法。具体的代码处理如下:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_WRITE_REQUEST_CODE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "onRequestPermissionsResult: request write permission success!");
//处理依赖权限的代码
} else {
Log.d(TAG, "onRequestPermissionsResult: request write permission fail!");
//请求失败,没有权限,不能运行依赖权限的代码
}
break;
}
}
这个方法中的requestCode就是上面请求权限时的请求代码,在上面的例子中,该请求代码为MY_WRITE_REQUEST_CODE。可以看到,这里用switch语句来接收请求代码来区分不同的权限请求,然后进行相应的处理。
到这里,完整的检查权限、请求权限和处理请求的流程都介绍完了,下面是完整的Demo。
例子程序
AndriodManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.permissionnosupport">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
package com.example.permissionnosupport;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.util.Log;
public class MainActivity extends Activity {
private final String TAG = "test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (doCheckPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Log.d(TAG, "onCreate: 应用具有写外部存储的权限");
//进行依赖权限的代码
} else {
Log.d(TAG, "onCreate: 应用不具有写外部存储的权限");
doRequestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
private boolean doCheckPermission(String permission) {
int permissionCheck = checkPermission(permission, Process.myPid(), Process.myUid());
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
return true;
}
return false;
}
private final int MY_WRITE_REQUEST_CODE = 0;
private void doRequestPermission(String permission) {
if (Build.VERSION.SDK_INT >= 23) {
//requestPermissions()方法需要SDK23
requestPermissions(new String[]{permission}, MY_WRITE_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_WRITE_REQUEST_CODE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "onRequestPermissionsResult: request write permission success!");
//处理依赖权限的代码
} else {
Log.d(TAG, "onRequestPermissionsResult: request write permission fail!");
//请求失败,没有权限,不能运行依赖权限的代码
}
break;
}
}
}