在Android6.0之前,需要声明权限时,我们只需在AndroidManifest.xml中声明即可。但是在Android6.0之后的版本中,我们除了需要在AndroidManifest.xml中声明之外,还需要在使用该权限时动态向用户申请,且只有当用户允许以后,才能够正常使用。
如果我们的应用在使用过程中,必须要使用到外部存储空间,比如下载类、工具类应用,那么如何友好的引导用户开启存储空间权限呢?意外发现UC给出了一个很好的交互设计。
如图所示:
(1).应用开启时,在启动页检查是否开启了存储空间权限。如果已经开启,则直接进入应用;若未开启,弹出对话框引导用户开启权限。
(2).用户在点击下一步按钮时,当前对话框消失,并弹出系统权限请求对话框。如果用户点击允许,此时成功获取权限,直接进入应用;如果用户拒绝,则弹出下一个对话框。
(3).权限被拒绝后,会弹出该对话框。如果用户不愿意开启权限,点击退出会直接退出应用;如果用户想开启权限,点击前往设置按钮,可进入系统设置中选择开启权限,此时打开权限并返回到我们的应用中,会直接进入主界面。
好了,下面我们来使用代码一步步实现。
首先在清单文件中声明读写外部存储的权限。
1.1 检查存储空间权限是否开启。
1.2 我们在Activity的onCreate()方法中,调用如下checkPermission()方法。
2.1 当isPermissionAllowed()返回false时,显示对话框引导用户开启权限。
2.2 当弹出系统权限对话框时,用户可以选择禁止或允许,选择完成后onRequestPermissionsResult()方法被回调,我们重写Activity的onRequestPermissionsResult()方法获取返回结果。
3.1 显示存储空间权限获取失败的对话框。
3.2 上面在进入系统设置界面时,我们将mIsStartSetting变量设为true。当从系统设置界面返回时,Activity的onResume()方法被调用,在这里我们再次判断权限是否开启,如果成功开启就可以进入主界面了。若未开启,则权限授权失败的对话框会一直显示。
最后附上完整工程代码下载链接:
http://download.csdn.net/detail/ruancoder/9718806
如果我们的应用在使用过程中,必须要使用到外部存储空间,比如下载类、工具类应用,那么如何友好的引导用户开启存储空间权限呢?意外发现UC给出了一个很好的交互设计。
如图所示:
(1).应用开启时,在启动页检查是否开启了存储空间权限。如果已经开启,则直接进入应用;若未开启,弹出对话框引导用户开启权限。
(2).用户在点击下一步按钮时,当前对话框消失,并弹出系统权限请求对话框。如果用户点击允许,此时成功获取权限,直接进入应用;如果用户拒绝,则弹出下一个对话框。
(3).权限被拒绝后,会弹出该对话框。如果用户不愿意开启权限,点击退出会直接退出应用;如果用户想开启权限,点击前往设置按钮,可进入系统设置中选择开启权限,此时打开权限并返回到我们的应用中,会直接进入主界面。
好了,下面我们来使用代码一步步实现。
首先在清单文件中声明读写外部存储的权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
1.1 检查存储空间权限是否开启。
private boolean isPermissionAllowed() {
int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
return permission == PackageManager.PERMISSION_GRANTED;
}
ContextCompat是android.support.v4兼容包中的类,调用checkSelfPermission()方法并传入参数WRITE_EXTERNAL_STORAGE检查是否开启了存储空间权限。WRITE_EXTERNAL_STORAGE与READ_EXTERNAL_STORAGE两个权限使用任意一个即可,成功开启一个权限之后,另一个权限也可正常使用。
1.2 我们在Activity的onCreate()方法中,调用如下checkPermission()方法。
private void checkPermission() {
if (isPermissionAllowed()) {
startMainActivity();
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showStorageFailDialog();
} else {
showOpenStorageDialog();
}
}
}
在方法内部,先检查权限是否开启。isPermissionAllowed()方法在6.0之前的系统中会直接返回true,6.0以上系统中只有在手动开启权限后才会返回true。在权限未开启的情况下,调用ActivityCompat.shouldShowRequestPermissionRationale()方法判断用户是否拒绝过该权限,若未拒绝过就显示“引导开启权限”的对话框,若之前已拒绝,则显示“权限授权失败”的对话框。showOpenStorageDialog()和showStorageFailDialog()方法会在后面介绍。
2.1 当isPermissionAllowed()返回false时,显示对话框引导用户开启权限。
private void showOpenStorageDialog() {
final AppCompatDialog dialog = new AppCompatDialog(this, R.style.no_title_dialog);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_open_storage, null);
view.findViewById(R.id.next).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
requestPermission();
dialog.dismiss();
}
});
int screenWidth = getResources().getDisplayMetrics().widthPixels;
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(screenWidth * 4 / 5, ViewGroup.LayoutParams.WRAP_CONTENT);
dialog.setContentView(view, params);
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
private static final int REQUEST_CODE_STORAGE = 1;
private void requestPermission() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_STORAGE);
}
这里将Dialog的Cancelable和CanceledOnTouchOutside都设置为false,用户无法直接取消对话框。当点击下一步时,调用ActivityCompat类的requestPermissions()方法,请求系统权限。
2.2 当弹出系统权限对话框时,用户可以选择禁止或允许,选择完成后onRequestPermissionsResult()方法被回调,我们重写Activity的onRequestPermissionsResult()方法获取返回结果。
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == REQUEST_CODE_STORAGE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startMainActivity();
} else {
showStorageFailDialog();
}
}
}
返回结果通过参数grantResults传递过来。我们判断如果grantResults数组中有值并且等于PERMISSION_GRANTED时,表示用户点击了允许,此时可以直接进入应用了。如果用户拒绝了权限,调用showStorageFailDialog()方法弹出权限获取失败的对话框。
3.1 显示存储空间权限获取失败的对话框。
private void showStorageFailDialog() {
final AppCompatDialog dialog = new AppCompatDialog(this, R.style.no_title_dialog);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_storage_fail, null);
TextView hintText = (TextView) view.findViewById(R.id.hint);
SpannableString hint = new SpannableString(hintText.getText());
hint.setSpan(new ForegroundColorSpan(Color.parseColor("#333333")), 10, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
hintText.setText(hint);
view.findViewById(R.id.exit).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
view.findViewById(R.id.start_setting).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mIsStartSetting = true;
startApplicationDetailsSetting();
}
});
int screenWidth = getResources().getDisplayMetrics().widthPixels;
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(screenWidth * 4 / 5, ViewGroup.LayoutParams.WRAP_CONTENT);
dialog.setContentView(view, params);
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
private boolean mIsStartSetting = false;
private void startApplicationDetailsSetting() {
Uri uri = Uri.parse("package:" + getPackageName());
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, uri);
startActivity(intent);
}
在该对话框中,我们会告诉用户必须要开启权限。用户不愿意,点击退出按钮可退出应用。如果想要进入应用,只能点击前往设置,进入系统的权限管理界面,引导用户开启存储空间权限。
3.2 上面在进入系统设置界面时,我们将mIsStartSetting变量设为true。当从系统设置界面返回时,Activity的onResume()方法被调用,在这里我们再次判断权限是否开启,如果成功开启就可以进入主界面了。若未开启,则权限授权失败的对话框会一直显示。
@Override
protected void onResume() {
super.onResume();
if (mIsStartSetting) {
mIsStartSetting = false;
if (isPermissionAllowed()) {
startMainActivity();
}
}
}
最后附上完整工程代码下载链接:
http://download.csdn.net/detail/ruancoder/9718806