Android Compliance Obtaining Device Permissions

1 Overview

Probably last year, I received a report from relevant departments saying that the app frequently pops up permission application pop-up boxes. At first I didn’t quite understand the frequent pop-ups, but then after looking at some big-name apps, they added processing for applying for device permissions. It probably looks like this, such as device read storage permissions,

The first one is like this before processing. When you use storage permissions, a permission pop-up box will open. When you click to deny use, a pop-up box for opening permissions will pop up when you use storage permissions again. The first approach would already be inconsistent with security compliance.

The second method is that when you use storage permissions, a pop-up box will pop up to open the permissions. When you click Deny, another prompt pop-up box will pop up when you use the storage permissions again, allowing you to go to the system to open the app permissions. In addition, When applying for permission, a permission description pop-up box will be added. The second approach is consistent with security compliance. As shown in the picture below (picture source network, infringement and deletion)

2. Realize 

1. Implement ideas

 2.Code

1. Tool class & callback

 import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.provider.Settings;
import androidx.core.content.ContextCompat;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.wangyi.Utils.ChatConstant;
import com.widget.ConfimDialog;
import com.widget.PermissionsDescriptionDialog;
import java.util.ArrayList;
import java.util.List;
 
public class PermissionsUtlis {
    /**
     * 判断是否缺少权限,利用SP存储记录
     */
    public static boolean lacksPermissionNew(Context mContext, String permission) {
        
        if (SpUtil.getBoolean(mContext, ChatConstant.APP_WRITE_EXTERNAL, true)) {
            PermissionsDescriptionDialog.getInstance()
                    .setTitle("存储权限使用说明")
                    .setContent("XX正在申请读取您的存储权限,缓存并同步本地内容,同时保障服务流畅。拒绝或取消不影响您使用XX其他服务。")
                    .show(mContext);
            SpUtil.putBoolean(mContext, ChatConstant.APP_WRITE_EXTERNAL, false);
            return true;
        }
        return !(ContextCompat.checkSelfPermission(mContext, permission) ==
                PackageManager.PERMISSION_DENIED);
    }

    public static void cunChuPermissisons(Context context, String permission, PermissisonsListener permissisonsListener) {
        if (lacksPermissionNew(context, permission)) {
            RxPermissions rxPermissions = new RxPermissions((Activity) context);
            rxPermissions.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                    .subscribe(aBoolean -> {
                        PermissionsDescriptionDialog.getInstance().hide();
                        if (aBoolean) {
                            permissisonsListener.Permissisons(true);
                        } else {
                            PermissionsUtlis.cunChuPermissisons(context);
                        }

                    });
        } else {
            PermissionsUtlis.cunChuPermissisons(context);
        }


    }

    public static void cunChuPermissisons(Context context) {
        ConfimDialog.getInstance().setTitle("XX需要申请存储权限")
                .setContent("XX正在申请读取您的存储权限同时保障服务流畅。拒绝或取消不影响您使用XX其他服务。")
                .setTvCancel("取消")
                .setTvConfim("去设置")
                .setOperateListener(new ConfimDialog.OnOperateListener() {
                    @Override
                    public void onSure() {
                        //引导用户至设置页手动授权
                        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        Uri uri = Uri.fromParts("package", "com.包名", null);
                        intent.setData(uri);
                        context.startActivity(intent);

                    }

                    @Override
                    public void onCancel() {

                    }
                }).show(context);
    }
 
     
}
 
 
public interface PermissisonsListener {
    void Permissisons(boolean flag);
}

2. Pop-up frame & layout

package com.widget;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;

 


public class PermissionsDescriptionDialog {
    private static PermissionsDescriptionDialog minstance;
    public static Dialog dialog;
    private static Handler handler = new Handler(Looper.getMainLooper());
    private String content = "";
    private boolean flag;
    private String title;

    private OnOperateListener operateListener;

    public static PermissionsDescriptionDialog getInstance() {
        minstance = new PermissionsDescriptionDialog();
        return minstance;
    }

    public void show(final Context context) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (dialog != null && dialog.isShowing()) {
                    dialog.dismiss();
                }
                dialog = new Dialog(context, R.style.MyDialogStyle);

                View view = View.inflate(context, R.layout.alert_permissons_dialog, null);
                dialog.setContentView(view);
                initView(view);
                dialog.setCancelable(false);
                Window window = dialog.getWindow(); //得到对话框
                // window.setWindowAnimations(R.style.dialogWindowAnim); //设置窗口弹出动画
                WindowManager.LayoutParams lp = window.getAttributes();
                if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {//横屏
                    lp.width = getScreenHeight(context) / 20 * 17;
                } else {
                    lp.width = getScreenWidth(context) / 20 * 17;
                }
                window.setGravity(Gravity.TOP);
                window.setAttributes(lp);
                dialog.show();
            }
        });
    }

    private void initView(View view) {
        TextView tvTvitle = view.findViewById(R.id.tv_tvitle);
        if (!TextUtils.isEmpty(title)) {
            tvTvitle.setText(title);
            tvTvitle.setVisibility(View.VISIBLE);
        } else {
            tvTvitle.setVisibility(View.GONE);
        }
        TextView tvContent = (TextView) view.findViewById(R.id.tv_content);
        tvContent.setText(content);
    }

    public void hide() {
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (null == dialog)
                    return;
                if (dialog != null && dialog.isShowing()) {
                    dialog.dismiss();
                    dialog = null;
                }
            }
        });
    }

    public void hideDelayed(long delayMillis) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (null == dialog)
                    return;
                if (dialog != null && dialog.isShowing()) {
                    dialog.dismiss();
                    dialog = null;
                }
            }
        }, delayMillis);
    }



    public PermissionsDescriptionDialog setContent(String content) {
        this.content = content;
        return minstance;
    }
    public PermissionsDescriptionDialog setTitle(String title) {
        this.title = title;

        return minstance;
    }
    public PermissionsDescriptionDialog setContent(String content, boolean flag) {
        this.content = content;
        this.flag = flag;
        return minstance;
    }





    public PermissionsDescriptionDialog setOperateListener(OnOperateListener operateListener) {
        this.operateListener = operateListener;
        return minstance;
    }

    public interface OnOperateListener {
        void onSure();

        void onCancel();
    }

    /**
     * 获取屏幕分辨率宽
     */
    public static int getScreenWidth(Context context) {
        DisplayMetrics dm = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
        Log.i("widthPixels", dm.widthPixels + "");
        return dm.widthPixels;

    }

    /**
     * 获取屏幕分辨率高
     */
    public static int getScreenHeight(Context context) {
        DisplayMetrics dm = new DisplayMetrics();
        ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.heightPixels;
    }

}

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/popub_delete" android:paddingTop="30dp" android:paddingBottom="30dp">
<TextView android:id="@+id/tv_tvitle" android:layout_width="match_parent" android:gravity="left" android:layout_height="wrap_content" android:textSize="16sp" android:layout_marginLeft="20dp" android:textStyle="bold" android:textColor="#212832" tools:text="存储权限使用说明"/>
<TextView android:id="@+id/tv_content" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@+id/tv_tvitle" android:layout_marginLeft="20dp" android:layout_marginTop="@dimen/px20" android:layout_marginRight="20dp" android:text="权限说明。。。。。。。。。。。" android:textColor="#333333" android:textSize="@dimen/font32"/>
</RelativeLayout>
<stylename="MyDialogStyle">
<itemname="android:windowBackground">@android:color/transparent</item>
<itemname="android:windowFrame">@null</item>
<itemname="android:windowNoTitle">true</item>
<itemname="android:windowIsFloating">true</item>
<itemname="android:windowIsTranslucent">true</item>
<itemname="android:windowContentOverlay">@null</item>
<item
name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
<itemname="android:backgroundDimEnabled">true</item>
</style>

3. Prompt to go to the system to open the app. The main idea

 public static void cunChuPermissisons(Context context) {
        ConfimDialog.getInstance().setTitle("XX需要申请存储权限")
                .setContent("XX正在申请读取您的存储权限,,缓存并同步本地内容,同时保障服务流畅。拒绝或取消不影响您使用XX其他服务。")
                .setTvCancel("取消")
                .setTvConfim("去设置")
                .setOperateListener(new ConfimDialog.OnOperateListener() {
                    @Override
                    public void onSure() {
                        //引导用户至设置页手动授权,写好对应的包名
                        Intent intent = new 
                        Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                        Uri uri = Uri.fromParts("package", "com.包名", null);
                        intent.setData(uri);
                        context.startActivity(intent);

                    }

                    @Override
                    public void onCancel() {

                    }
                }).show(context);
    }

4. Function call

 PermissionsUtlis.cunChuPermissisons(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, new PermissisonsListener() {
                    @Override
                    public void Permissisons(boolean flag) {
                        if (flag) {
                            //TODO 实现你需要的逻辑
                        }

                    }
                });

5. Third-party components used

 RxPermissions library github address: https://github.com/tbruyelle/RxPermissions

Every developer hopes to bring a better experience to users, provided that user privacy is guaranteed. In the future, we will also publish some other solutions that return to security issues, such as vulnerabilities and information security and other related articles. Some pop-up boxes are not written in detail and can be improved by combining your own code.

Guess you like

Origin blog.csdn.net/u012941592/article/details/126832043
Recommended