Android用户权限之记录是否调起弹窗
记录一个最近在开发中遇到的奇葩需求,需求内容主要是:
记录在申请权限的时候客户端的行为,包括是否弹出了系统权限,以及弹出情况下用户是否同意授权
对于是否弹窗,我们都知道Android权限的几种情况:
我们回过头看一下需求,弹出的情况下用户是否同意授权这个其实很好判断,主要是是否弹出了授权框,我们通过系统的api并不能直接拿到这个结果。因为弹出申请框是一个系统行为,并不是我们自己定义的一个弹框。
我们可以先回顾一下申请权限的原始步骤:
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
然后在回调中处理申请结果:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
}
客户端做的事情起其实只有
所以我们这里只有曲线救国了,我们分析一下现在有的几种可能性:
这里第1,2两种情况是会发起授权的,34两种情况不会再发起授权,所以我们的重点在于如何区分这四种状态。
第四种很好区分,通过ContextCompat.checkSelfPermission()方法就可以检测出
这里介绍一下另一个方法:
ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission)
这个方法返回一个boolean值,表示之前是否已经被拒绝过但是还没有点击不再显示。所以通过这个方法可以区分出来第二种情况。
那我们就剩下第一种和第三种如何区分了,第一种的话其实我们可以发现有一个规律,第一次去请求权限是肯定不会有不再显示按钮的,包括重新将状态设置为询问,这个大家可以测试一下。
所以我们可以根据请求结果做一下文章
请求结果是成功的
这种肯定就是第一种情况,因为如果是第三种情况是肯定不会请求成功的(第二种和第四种在请求结果之前就已经筛选出去了,所以不用考虑)
请求结果失败
这里就可以再次用上这个方法了
ActivityCompat.shouldShowRequestPermissionRationale
如果是第一种情况,那么这个方法应该是返回true,因为第一次是没有不再显示这个按钮的,如果返回false那么就是第三种情况,这样就区分出来了
经过这个需求只能说对于权限系统理解更深了吧。
/(ㄒoㄒ)/~~
附上代码:
定义一个enum表示上面的四种状态
public enum PermissionState{
/**
* 询问状态,展示弹窗
*/
ASKING(true),
/**
* 点击拒绝,未点击不再显示,展示弹窗
*/
MORE_REQUEST(true),
/**
* 已同意,不展示弹窗
*/
HAS_GRANTED(false),
/**
* 点击拒绝,已点击不再显示,不展示弹窗
*/
DEFINED(false);
private boolean mShowDialog;
PermissionState(boolean showDialog){
mShowDialog = showDialog;
}
public boolean isShowDialog(){
return mShowDialog;
}
}
定义一个结果接收权限申请结果:
public interface PermissionListener {
void onSucceed(int var1, @NonNull List var2);
void onFailed(int var1, @NonNull List var2);
}
新增一个装饰类处理结果进行区分:
public class PermissionTrackerListener implements PermissionListener {
private Activity mActivity;
private PermissionListener mListener;
/**
* 权限列表
*/
private List mNeedTrackPermissionList;
/**
* 当前几个权限的状态
*/
private List mNeedTrackPermissionStateList;
public PermissionTrackerListener(Activity activity, PermissionListener listener){
mActivity = activity;
mListener = listener;
mNeedTrackPermissionList = new ArrayList<>();
mNeedTrackPermissionStateList = new ArrayList<>();
}
@Override
public void onSucceed(int i, @NonNull List list) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int j = 0; j < mNeedTrackPermissionList.size(); j++) {
PermissionState state = mNeedTrackPermissionStateList.get(j);
String permission = mNeedTrackPermissionList.get(j);
if (state == null){
state = PermissionState.ASKING;
}
if (state == PermissionState.ASKING || state == PermissionState.MORE_REQUEST) {
Toast.makeText(mActivity, "已弹窗埋点: " + permission, Toast.LENGTH_SHORT).show();
Toast.makeText(mActivity, "点击同意埋点: " + permission, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mActivity, "未弹窗埋点: " + permission, Toast.LENGTH_SHORT).show();
}
}
}
mListener.onSucceed(i, list);
}
@Override
public void onFailed(int i, @NonNull List list) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for (int j = 0; j < mNeedTrackPermissionList.size(); j++) {
String permission = mNeedTrackPermissionList.get(j);
boolean denied = list.contains(permission);
PermissionState state = mNeedTrackPermissionStateList.get(j);
if (state == null) {
if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission)) {
state = PermissionState.ASKING;
} else {
state = PermissionState.DEFINED;
}
}
if (state == PermissionState.ASKING || state == PermissionState.MORE_REQUEST) {
Toast.makeText(mActivity, "已弹窗埋点: " + permission, Toast.LENGTH_SHORT).show();
if (denied) {
Toast.makeText(mActivity, "点击拒绝埋点: " + permission, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mActivity, "点击同意埋点: " + permission, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(mActivity, "未弹窗埋点: " + permission, Toast.LENGTH_SHORT).show();
}
}
}
mListener.onFailed(i, list);
}
/**
* 申请权限之前调用
* @param list 需要申请的权限
*/
public void preRequestPermission(@NonNull List list){
mNeedTrackPermissionList = list;
if (mNeedTrackPermissionList.isEmpty()){
return;
}
for (String permission : mNeedTrackPermissionList) {
PermissionState state = null;
if (ActivityCompat.checkSelfPermission(mActivity, permission) == PackageManager.PERMISSION_GRANTED){
state = PermissionState.HAS_GRANTED;
} else if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permission)){
state = PermissionState.MORE_REQUEST;
}
mNeedTrackPermissionStateList.add(state);
}
}
}