首页 > 其他分享 >Android运行时请求权限封装

Android运行时请求权限封装

时间:2024-11-13 18:56:39浏览次数:1  
标签:封装 String void context new Android 权限 permissions

@

目录

本文目的:“借助透明Activity封装一个易于调用的权限请求模块”

1 介绍

Android权限的校验和申请比较简单,但在实际项目中使用时还要进行系统版本的适配,最不友好的是权限的申请结果需要在 onRequestPermissionsResult 中进行判断,如果项目中有多个地方需要申请权限,或者申请权限的代码在自定义的组件中,而申请结果判断则在activity或fragment中,那代码就会显得很乱,对于后期维护也是很不方便,因此我们就来封装一个简单的权限申请模块。

2 测试用例设计

首页我们还是先设计一个权限申请的测试用例步骤:
1、首先判断所需要的权限是否已经过用户授权;
2、如果没有经过用户授权,则申请权限;
3、如果用户授权,则调用相关功能;
4、如果用户拒绝授权,则提示信息。
解析流程:
输入:需要的权限
输出:授权/拒绝

测试用例的代码实现:

String[] permisstions = new String[];  //申请所需要权限
PermissionHelper.request(context,permisstions,new Listener(){
	void granted(){
		//授权后执行
	}
	void denied(){
		//拒绝后执行
	}
});

测试用例实现了输入、输出,其他步骤就需要在模块中实现,对调用方透明。

3 实现

首先我们先实现PermissionHelper类,功能是判断权限是否被授权,如果没有被授权则申请权限。


/**
 * 权限帮助类
 * Created by lidong on 2019/10/25.
 */
public class PermissionHelper {

    /**
     * 请求权限
     *
     * @param context     context
     * @param permissions 权限
     * @param listener    监听
     */
    public static void request(Context context, String[] permissions, PermissionListener listener) {
        //判断权限,如果所有权限全被授权,直接返回
        if (checkPermission(context, permissions)) {
            if (listener != null) {
                listener.granted();
            }
            return;
        }

        //申请权限
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {  //6.0以下没有申请权限,直接返回拒绝
            if (listener != null) {
                listener.denied();
            }
        } else {  //6.0及以上申请权限
            //为了统一回调需要借用一个activity
            PermissionActivity.open(context, permissions, listener);
        }
    }

    /**
     * 校验权限
     *
     * @param context     context
     * @param permissions 权限
     * @return 所有权限已被授权返回true,否则返回false
     */
    protected static boolean checkPermission(Context context, String[] permissions) {
        for (String per : permissions) {
            int result = PermissionChecker.checkSelfPermission(context, per);
            if (result != PermissionChecker.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    /**
     * 权限监听
     */
    public interface PermissionListener {
        /**
         * 所有权限已被授权
         */
        void granted();

        /**
         * 一个或多个权限被拒绝
         */
        void denied();
    }
}

这里为了方便接收申请权限的结果,我们打开一个新的activity,在新activity中进行权限申请,需要将申请的权限和回调监听传入activity中:

public static void open(Context context, String[] permissions, PermissionHelper.PermissionListener listener) {
        Intent intent = new Intent(context, PermissionActivity.class);
        intent.putExtra("data", permissions);
        context.startActivity(intent);
        mPermissionListener = listener;
    }

PermissionActivity类:


/**
 * 权限申请
 * Created by lidong on 2019/10/25.
 */
public class PermissionActivity extends Activity {

    private static PermissionHelper.PermissionListener mPermissionListener;

    private String[] permissions;
    private AlertDialog mAlertDialog;
    private boolean first = true;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        permissions = getIntent().getStringArrayExtra("data");
    }

    private void requestPermissions(){
        ActivityCompat.requestPermissions(this, permissions, 1);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (first) {
            first = false;
            requestPermissions();
            return;
        }

        //切换页面回来重新校验一下
        showMissingPermissionDefiniteDialog();
    }

    /**
     * 拒绝授权 显示提示对话框
     */
    private void showMissingPermissionDefiniteDialog() {

        if (mAlertDialog != null && mAlertDialog.isShowing()) {
            mAlertDialog.dismiss();
        }

        List<String> deniedList = new ArrayList<>();
        for (String permission : permissions) {
            if (PermissionChecker.checkSelfPermission(this, permission)
                    == PermissionChecker.PERMISSION_GRANTED) {
                continue;
            }
            deniedList.add(permission);
        }

        if (deniedList.size() == 0) {
            granted();
            return;
        }

        List<String> tipList = transformTip(deniedList);
        StringBuilder tip = new StringBuilder();
        int i = 0;
        for (String temp : tipList) {
            if (i > 0) {
                tip.append(",");
            }
            tip.append(temp);
            i++;
        }


        AlertDialog.Builder builder = new AlertDialog.Builder(PermissionActivity.this);
        builder.setMessage("应用程序需要以下权限:\n\r" + tip);

        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                denied();
            }
        });
        builder.setPositiveButton("设置", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                gotoSetting();
            }
        });
        builder.setCancelable(false);
        mAlertDialog = builder.show();
    }

    private List<String> transformTip(List<String> list) {
        Map<String, String> permissionList = new HashMap<>();
        permissionList.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, "「存储空间」");
        permissionList.put(Manifest.permission.READ_PHONE_STATE, "「电话」");
        permissionList.put(Manifest.permission.CAMERA, "「相机」");
        permissionList.put(Manifest.permission.RECORD_AUDIO, "「录音」");
        permissionList.put(Manifest.permission.ACCESS_FINE_LOCATION, "「位置」");
        permissionList.put(Manifest.permission.ACCESS_COARSE_LOCATION, "「位置」");

        List<String> tipList = new ArrayList<>();
        for (String temp : list) {
            String tip = permissionList.get(temp);
            if (!tipList.contains(tip)) {
                tipList.add(tip);
            }
        }

        return tipList;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        //判断所有权限是否被授权
        if (isGranted(grantResults) && PermissionHelper.checkPermission(this, permissions)) {
            granted();
        } else {
            showMissingPermissionDefiniteDialog();
        }
    }

    /**
     * 授权回调
     */
    private void granted(){
        if (mPermissionListener != null) {
            mPermissionListener.granted();
        }
        finish();
    }

    /**
     * 拒绝回调
     */
    private void denied(){
        if (mPermissionListener != null) {
            mPermissionListener.denied();
        }
        finish();
    }

    private boolean isGranted(int[] grantResult) {
        for (int result : grantResult) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    /**
     * 跳转到当前应用对应的设置页面
     */
    private void gotoSetting() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }

    @Override
    public void finish() {
        super.finish();
        overridePendingTransition(0, 0);
        mPermissionListener = null;
    }

    public static void open(Context context, String[] permissions, PermissionHelper.PermissionListener listener) {
        Intent intent = new Intent(context, PermissionActivity.class);
        intent.putExtra("data", permissions);
        context.startActivity(intent);
        mPermissionListener = listener;
    }
}

在 activity 的 onRequestPermissionsResult 方法中,校验授权结果,如果一个或多个权限未被授权,则显示提示对话框,对话框有“设置”按钮跳转到应用程序详情页面,可以进入权限设置页面修改权限。

为了兼容在程序以外的地方手动修改权限,再切换回当前页面的情况,我们在 onResume 方法里增了页面切换回来后重新判断权限是否被授权。

到这里已经封装完成了。

4 用例测试

现在我们完善一下测试用例:

String[] permissions=new String[]{
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.CAMERA,
                Manifest.permission.READ_PHONE_STATE,
        };
        PermissionHelper.request(context, permissions, new PermissionHelper.PermissionListener() {
            @Override
            public void granted() {
                showToast("已授权");
            }

            @Override
            public void denied() {
                showToast("已拒绝");
            }
        });

运行测试用例,发现申请权限的activity是白色背景,我们可以在 AndroidManifest.xml 文件中将 activity 设置成全屏透明窗体,用户体验也会好点。

好了,以后无论在哪里需要申请权限,我们只需要这几行代码就够了!

5 总结

申请权限的封装,主要是利用一个透明的activity来完成需要在 activity 中接收结果的情况。其实微信的支付sdk也有用到透明的activity。使用透明activity可以用来将调用和回调代码组装一起,增加代码的可读性和维护性。

END


本文的技术设计和实现都是基于作者工作中的经验总结,如有错误,请留言指正,谢谢。

标签:封装,String,void,context,new,Android,权限,permissions
From: https://www.cnblogs.com/shuijinglingsos/p/18544574

相关文章

  • [ Linux 命令基础 ] Linux 命令大全-命令前置知识-系统管理-文件和目录管理-文本处理
    ......
  • Rust 在 Android 的编程实践——技术驱动的车云一体化解决方案探索
    Greptime车云一体化解决方案颠覆了从前传统的车云协同模式,采用更加低成本、高效率的方案来满足当前的市场需求。其中GreptimeDBEdge作为核心组件,专为车机环境量身打造。本文旨在详尽探讨在Android平台利用Rust语言进行开发过程中所积累的经验和教训。交叉编译在车机场景......
  • Privilege Escalation(权限提升)
    PrivilegeEscalation(权限提升)WhattheShell?Whatisashellshell是我们与命令行环境(CLI)交互时使用的工具。换句话说,Linux中常见的bash或sh程序都是shell的例子,Windows上的cmd.exe和Powershell也是如此。简而言之,我们可以强制远程服务器向我们发送对服务......
  • VUE 封装axios
    axios官方介绍:https://www.axios-http.cn/docs/intro node.js安装:npminstallaxios封装一个配置文件constinstance=axios.create({baseURL:'https://some-domain.com/api/',timeout:1000,headers:{'X-Custom-Header':'foobar'}});......
  • fastadmin 数据记录行上添加操作按钮并设置权限
    1.一键curd以及配置菜单编写控制器方法-业务逻辑再次一键生成菜单-生成刚刚写审核通过方法的控制器。 2.自定义控制器中方法。3.查看角色组的权限,并授予该角色权限。4.前端修改index页面,因为需要权限所以需要加上一句话data-operate-log="{:$auth->check('......
  • 网页全终端安防视频流媒体播放器EasyPlayer.js无插件H5播放器包含的直播协议支持(封装
    EasyPlayer.jsH5播放器,是一款能够同时支持HTTP、HTTP-FLV、HLS(m3u8)、WS、WEBRTC、FMP4视频直播与视频点播等多种协议,支持H.264、H.265、AAC、G711A、Mp3等多种音视频编码格式,支持MSE、WASM、WebCodec等多种解码方式,支持Windows、Linux、Android、iOS全平台终端的H5播放器,使用简单......
  • Android OpenGL ES详解——立方体贴图
    目录一、概念二、如何使用1、创建立方体贴图2、生成纹理3、设置纹理环绕和过滤方式4、激活和绑定立方体贴图三、应用举例——天空盒1、概念2、加载天空盒3、显示天空盒4、优化四、应用举例——环境映射:反射五、应用举例——环境映射:折射六、应用举例——动态......
  • Android SIM 解锁:如何轻松解锁 Android 上的 SIM 卡
    您的Android手机SIM卡是否已锁定?许多人购买Android手机时并不知道手机是否已锁定SIM卡。您可能想要更改网络服务提供商,但后来发现新的SIM卡无法在Android手机上使用。这会带来不便,因为您无法通过其他线路使用购买的电话。人们可能会问自己,如果遇到此问题,如何在An......
  • 高手技巧:如何在 Android 上绕过人脸识别
    人脸识别是Android引入的一项重要安全功能,可帮助用户保护其设备免遭未经授权的访问。如果您想保证文件安全,它非常有用。通常,面部识别的工作原理是使用您的面部作为生物识别标识符来验证某些操作。但是,有时会由于各种原因而失败。可能是相机坏了,或者设备有问题。发生这种情况......
  • 如何解锁碎屏手机(Android 指南)
    一般来说,电子设备很脆弱,除非它们是为大量使用而设计的。Android智能手机、平板电脑和智能手表也存在这种脆弱性。Android智能手机或平板电脑的触摸屏是您访问和使用手机的最重要部件之一。如果屏幕在锁定时破裂或破裂,肯定会令人不安。您将陷入如何解锁屏幕破损的手机的困......