为了可以方便使用权限申请,并且尽量不要产生不必要的重复代码,在一些开源项目提供的资料帮助下,我对权限申请做了一个进一步的封装,将权限相关的操作封装到类中,最后对外只需要开放一个调用方法即可方便使用。
具体操作步骤如下:
1、将下面的PermissionsUtil这个类的代码拷贝的你的项目中
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.PermissionChecker;
import android.support.v7.app.AlertDialog;
import java.util.HashMap;
import java.util.Map;
/***
* @date 创建时间 2018/8/18 21:21
* @author 作者: W.YuLong
* @description 权限申请的封装
*/
public class PermissionsUtil extends Activity {
private static final int PERMISSION_REQUEST_CODE = 64;
private static final int REQUEST_SETTING_CODE = 121;
private String[] permission;
private String key;
private boolean isShowTip;
private PermissionTipInfo tipInfo;
private static Map<String, OnPermissionCallback> listenersMap = new HashMap<>();
/***
* 权限的申请
* @param context 请求权限的上下文,如果在Activity或fragment中最好传当前Activity实例
* @param permission 需要申请的权限
* @param onPermissionCallback 权限申请后的回调接口
*/
public static void requestPermission(Context context, String[] permission, OnPermissionCallback onPermissionCallback) {
requestPermission(context, null, permission, true, onPermissionCallback);
}
/***
* 权限的申请方法
* @param context 请求权限的上下文,如果在Activity或fragment中最好传当前Activity实例
* @param permission 需要申请的权限
* @param isShowTip 是否显示对话框(当权限被拒绝时)
* @param onPermissionCallback 权限申请后的回调接口
*/
public static void requestPermission(Context context, String[] permission, boolean isShowTip, OnPermissionCallback onPermissionCallback) {
requestPermission(context, null, permission, isShowTip, onPermissionCallback);
}
/***
* 权限的申请方法
* @param context 请求权限的上下文,如果在Activity或fragment中最好传当前Activity实例
* @param tipInfo 拒绝权限或者权限被关闭显示的对话框类型信息
* @param permission 需要申请的权限
* @param isShowTip 是否显示对话框(当权限被拒绝时)
* @param onPermissionCallback 权限申请后的回调接口
*/
public static void requestPermission(Context context, PermissionTipInfo tipInfo, String[] permission, boolean isShowTip, OnPermissionCallback onPermissionCallback) {
Intent intent = new Intent(context, PermissionsUtil.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
if (tipInfo != null) {
intent.putExtra("tipInfo", tipInfo);
}
String key = System.currentTimeMillis() + "";
intent.putExtra("key", key);
intent.putExtra("permission", permission);
intent.putExtra("isShowTip", isShowTip);
listenersMap.put(key, onPermissionCallback);
context.startActivity(intent);
if (context instanceof Activity) {
((Activity) context).overridePendingTransition(0, 0);
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
key = intent.getStringExtra("key");
tipInfo = intent.getParcelableExtra("tipInfo");
permission = intent.getStringArrayExtra("permission");
isShowTip = intent.getBooleanExtra("isShowTip", false);
//直接申请权限
ActivityCompat.requestPermissions(this, permission, PERMISSION_REQUEST_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//部分厂商手机系统返回授权成功时,厂商可以拒绝权限,所以要用PermissionChecker二次判断
if (requestCode == PERMISSION_REQUEST_CODE && isGranted(grantResults)
&& hasPermission(this, permissions)) {
OnPermissionCallback listener = listenersMap.remove(key);
if (listener != null) {
listener.onSuccess(permission);
}
finish();
} else if (isShowTip) {
showMissingPermissionDialog();
} else { //不需要提示用户
permissionsRefused();
}
}
//显示权限被拒绝的对话框
private void showMissingPermissionDialog() {
if (tipInfo == null) {
tipInfo = PermissionTipInfo.newInstance();
}
new AlertDialog.Builder(this).setTitle(tipInfo.getTitle()).setMessage(tipInfo.getMessage())
.setNegativeButton(tipInfo.getCancelText(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
permissionsRefused();
}
})
.setPositiveButton(tipInfo.getOkText(), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_SETTING_CODE);
}
}).setCancelable(false).create().show();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//去设置页面设置完成之后再次请求看是否已打开权限
if (requestCode == REQUEST_SETTING_CODE) {
ActivityCompat.requestPermissions(this, permission, PERMISSION_REQUEST_CODE);
}
}
// 判断权限是否已打开
public static boolean hasPermission(Context context, String... permissions) {
if (permissions.length == 0) {
return false;
}
for (String per : permissions) {
int result = PermissionChecker.checkSelfPermission(context, per);
if (result != PermissionChecker.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
// 权限被拒绝的回调
private void permissionsRefused() {
OnPermissionCallback listener = listenersMap.remove(key);
if (listener != null) {
listener.onRefused(permission);
}
finish();
}
private boolean isGranted(@NonNull int... grantResult) {
if (grantResult.length == 0) {
return false;
}
for (int result : grantResult) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
@Override
protected void onDestroy() {
super.onDestroy();
//当前的Activity被销毁时再次做一些移除传过来的接口,防止内存泄露
listenersMap.remove(key);
}
@Override
public void finish() {
super.finish();
//去掉页面的过度动画
overridePendingTransition(0, 0);
}
/***
*@date 创建时间 2018/8/18 21:37
*@author 作者: W.YuLong
*@description 权限被拒绝封装的内容实体类
*/
public static class PermissionTipInfo implements Parcelable {
private String title = "温馨提示";
private String message = "当前应用缺少必要权限。\n \n 请点击 \"设置\"-\"权限\"-打开所需权限。";
private String cancelText = "取消";
private String okText = "打开权限";
public PermissionTipInfo(String title, String message, String cancelText, String okText) {
this.title = title;
this.message = message;
this.cancelText = cancelText;
this.okText = okText;
}
public PermissionTipInfo() {
}
public static PermissionTipInfo newInstance() {
return new PermissionTipInfo();
}
public String getTitle() {
return title;
}
public PermissionTipInfo setTitle(String title) {
this.title = title;
return this;
}
public String getMessage() {
return message;
}
public PermissionTipInfo setMessage(String message) {
this.message = message;
return this;
}
public String getCancelText() {
return cancelText;
}
public PermissionTipInfo setCancelText(String cancelText) {
this.cancelText = cancelText;
return this;
}
public String getOkText() {
return okText;
}
public PermissionTipInfo setOkText(String okText) {
this.okText = okText;
return this;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.title);
dest.writeString(this.message);
dest.writeString(this.cancelText);
dest.writeString(this.okText);
}
protected PermissionTipInfo(Parcel in) {
this.title = in.readString();
this.message = in.readString();
this.cancelText = in.readString();
this.okText = in.readString();
}
public static final Parcelable.Creator<PermissionTipInfo> CREATOR = new Parcelable.Creator<PermissionTipInfo>() {
@Override
public PermissionTipInfo createFromParcel(Parcel source) {
return new PermissionTipInfo(source);
}
@Override
public PermissionTipInfo[] newArray(int size) {
return new PermissionTipInfo[size];
}
};
}
/***
*@date 创建时间 2018/8/18 21:27
*@author 作者: W.YuLong
*@description 回调接口的实现类,可以防止每次都要实现接口的抽象方法
*/
public static class OnPermissionCallbackImpl implements OnPermissionCallback {
@Override
public void onSuccess(String[] permission) {
}
@Override
public void onRefused(String[] permission) {
}
}
/***
*@date 创建时间 2018/8/18 21:27
*@author 作者: W.YuLong
*@description 回调接口
*/
public interface OnPermissionCallback {
void onSuccess(String[] permission);
void onRefused(String[] permission);
}
}
复制代码
2、在你的 AndroidManifest.xml
文件中添加如下的注册声明
<activity android:name="{你的PermissionsUtil类所在Java包的名称}.PermissionsUtil"
android:theme="@style/transparentTheme"/>复制代码
例如你的APP包名为: 【com.android.demo】,然后PermissionsUtil 在【permission】包中,那么你在
AndroidManifest.xml
文件中添加这个类的注册声明如下:
<activity android:name="com.android.demo.permission.PermissionsUtil"
android:theme="@style/transparentTheme"/>复制代码
3、然后在 style.xml文件中定义这个透明的主题
<style name="transparentTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@color/color_0000</item>
<item name="android:windowIsTranslucent">true</item>
</style>复制代码
这样就大功告成了。然后具体的用法如下:
//这些权限数组建议统一定义到一个常量类中
String[] requestPermission = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
};
PermissionsUtil.requestPermission(this, requestPermission,
new PermissionsUtil.OnPermissionCallbackImpl() {
@Override
public void onSuccess(String[] permission) {
System.out.println("权限申请成功");
}
@Override
public void onRefused(String[] permission) {
System.out.println("权限被拒绝了");
}
});复制代码
效果图如下:
还有其他的2个方法调用,具体的描述已经写在代码的注释当中了。