Android 6.0 - 动态权限管理的解决方案

Android - 动态权限管理的解决方案(Android 6.0) Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应用权限. 时代总是不断发展, 程序总是以人为本, 让我们为应用添加动态权限管理吧! 这里提供了一个非常不错的解决方案.Android系统包含默认的授权提示框, 但是我们仍需要设置自己的页面. 原因是系统 阅读详情

Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应用权限. 时代总是不断发展, 程序总是以人为本, 让我们为应用添加动态权限管理吧! 这里提供了一个非常不错的解决方案, 提供源码, 项目可以直接使用.


Permissions

Android系统包含默认的授权提示框, 但是我们仍需要设置自己的页面. 原因是系统提供的授权框, 会有不再提示的选项. 如果用户选择, 则无法触发授权提示. 使用自定义的提示页面, 可以给予用户手动修改授权的指导.

本文示例的GitHub下载地址

在Api 23中, 权限需要动态获取, 核心权限必须满足. 标准流程:


流程图

如果用户点击, 不再提示, 则系统授权弹窗将不会弹出. 流程变为:


流程图

流程就这些, 让我们看看代码吧.


1. 权限

在AndroidManifest中, 添加两个权限, 录音和修改音量.

    <!--危险权限-->
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>

    <!--一般权限-->
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>

危险权限必须要授权, 一般权限不需要.

检测权限类

/**
 * 检查权限的工具类
 * <p/>
 * Created by wangchenlong on 16/1/26.
 */
public class PermissionsChecker {
    private final Context mContext;

    public PermissionsChecker(Context context) {
        mContext = context.getApplicationContext();
    }

    // 判断权限集合
    public boolean lacksPermissions(String... permissions) {
        for (String permission : permissions) {
            if (lacksPermission(permission)) {
                return true;
            }
        }
        return false;
    }

    // 判断是否缺少权限
    private boolean lacksPermission(String permission) {
        return ContextCompat.checkSelfPermission(mContext, permission) ==
                PackageManager.PERMISSION_DENIED;
    }
}

2. 首页

假设首页需要使用权限, 在页面显示前, 即onResume时, 检测权限,
如果缺少, 则进入权限获取页面; 接收返回值, 拒绝权限时, 直接关闭.

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_CODE = 0; // 请求码

    // 所需的全部权限
    static final String[] PERMISSIONS = new String[]{
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.MODIFY_AUDIO_SETTINGS
    };

    @Bind(R.id.main_t_toolbar) Toolbar mTToolbar;

    private PermissionsChecker mPermissionsChecker; // 权限检测器

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        setSupportActionBar(mTToolbar);

        mPermissionsChecker = new PermissionsChecker(this);
    }

    @Override protected void onResume() {
        super.onResume();

        // 缺少权限时, 进入权限配置页面
        if (mPermissionsChecker.lacksPermissions(PERMISSIONS)) {
            startPermissionsActivity();
        }
    }

    private void startPermissionsActivity() {
        PermissionsActivity.startActivityForResult(this, REQUEST_CODE, PERMISSIONS);
    }

    @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // 拒绝时, 关闭页面, 缺少主要权限, 无法运行
        if (requestCode == REQUEST_CODE && resultCode == PermissionsActivity.PERMISSIONS_DENIED) {
            finish();
        }
    }
}

核心权限必须满足, 如摄像应用, 摄像头权限就是必须的, 如果用户不予授权, 则直接关闭.


3. 授权页

授权页, 首先使用系统默认的授权页, 当用户拒绝时, 指导用户手动设置, 当用户再次操作失败后, 返回继续提示. 用户手动退出授权页时, 给使用页发送授权失败的通知.

/**
 * 权限获取页面
 * <p/>
 * Created by wangchenlong on 16/1/26.
 */
public class PermissionsActivity extends AppCompatActivity {

    public static final int PERMISSIONS_GRANTED = 0; // 权限授权
    public static final int PERMISSIONS_DENIED = 1; // 权限拒绝

    private static final int PERMISSION_REQUEST_CODE = 0; // 系统权限管理页面的参数
    private static final String EXTRA_PERMISSIONS =
            "me.chunyu.clwang.permission.extra_permission"; // 权限参数
    private static final String PACKAGE_URL_SCHEME = "package:"; // 方案

    private PermissionsChecker mChecker; // 权限检测器
    private boolean isRequireCheck; // 是否需要系统权限检测

    // 启动当前权限页面的公开接口
    public static void startActivityForResult(Activity activity, int requestCode, String... permissions) {
        Intent intent = new Intent(activity, PermissionsActivity.class);
        intent.putExtra(EXTRA_PERMISSIONS, permissions);
        ActivityCompat.startActivityForResult(activity, intent, requestCode, null);
    }

    @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) {
            throw new RuntimeException("PermissionsActivity需要使用静态startActivityForResult方法启动!");
        }
        setContentView(R.layout.activity_permissions);

        mChecker = new PermissionsChecker(this);
        isRequireCheck = true;
    }

    @Override protected void onResume() {
        super.onResume();
        if (isRequireCheck) {
            String[] permissions = getPermissions();
            if (mChecker.lacksPermissions(permissions)) {
                requestPermissions(permissions); // 请求权限
            } else {
                allPermissionsGranted(); // 全部权限都已获取
            }
        } else {
            isRequireCheck = true;
        }
    }

    // 返回传递的权限参数
    private String[] getPermissions() {
        return getIntent().getStringArrayExtra(EXTRA_PERMISSIONS);
    }

    // 请求权限兼容低版本
    private void requestPermissions(String... permissions) {
        ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE);
    }

    // 全部权限均已获取
    private void allPermissionsGranted() {
        setResult(PERMISSIONS_GRANTED);
        finish();
    }

    /**
     * 用户权限处理,
     * 如果全部获取, 则直接过.
     * 如果权限缺失, 则提示Dialog.
     *
     * @param requestCode  请求码
     * @param permissions  权限
     * @param grantResults 结果
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) {
            isRequireCheck = true;
            allPermissionsGranted();
        } else {
            isRequireCheck = false;
            showMissingPermissionDialog();
        }
    }

    // 含有全部的权限
    private boolean hasAllPermissionsGranted(@NonNull int[] grantResults) {
        for (int grantResult : grantResults) {
            if (grantResult == PackageManager.PERMISSION_DENIED) {
                return false;
            }
        }
        return true;
    }

    // 显示缺失权限提示
    private void showMissingPermissionDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(PermissionsActivity.this);
        builder.setTitle(R.string.help);
        builder.setMessage(R.string.string_help_text);

        // 拒绝, 退出应用
        builder.setNegativeButton(R.string.quit, new DialogInterface.OnClickListener() {
            @Override public void onClick(DialogInterface dialog, int which) {
                setResult(PERMISSIONS_DENIED);
                finish();
            }
        });

        builder.setPositiveButton(R.string.settings, new DialogInterface.OnClickListener() {
            @Override public void onClick(DialogInterface dialog, int which) {
                startAppSettings();
            }
        });

        builder.show();
    }

    // 启动应用的设置
    private void startAppSettings() {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName()));
        startActivity(intent);
    }
}

注意isRequireCheck参数的使用, 防止和系统提示框重叠.
系统授权提示: ActivityCompat.requestPermissions, ActivityCompat兼容低版本.

效果


自定义授权

关键部分就这些了, 动态权限授权虽然给程序员带来了一些麻烦, 但是对用户还是很有必要的, 我们也应该欢迎, 毕竟每个程序员都是半个产品经理.

危险权限列表


危险权限列表

参考1,http://droidyue.com/blog/2016/01/17/understanding-marshmallow-runtime-permission/

 参考2.https://blog.stylingandroid.com

转载至:http://www.jianshu.com/p/dbe4d37731e6



Open3D:Win10 + VS2017配置Open3D(C++、python) 一、下载源码 地址:https://github.com/intel-isl/Open3D 1.1 克隆源码【笔者的源码路径为D:\Open3D\Open3D】 1.2 切换版本【笔者的版本为0.8.0】 1.3 更新子模块【用于获取第三方库!很重要!】 二、CMake编译 2.1 设置路径 【source code: D:\Open3D\Open3D;build binaries: D:\Open3D】 【笔者设置CMAKE/CMAKE_INSTALL_PREFIX的路径为D:/Open. 阅读详情

相关推荐

【上海大学计算机组成原理实验报告】五、机器语言程序实验

机器语言程序实验//理解计算机执行程序的实际过程//学习编制机器语言简单程序的方法//将R1中的数值左移n次送OUT,其中n是R2中的数值。(指令码从10开始)//完成R3=R0×R1,结果送OUT。(指令码从30开始)//建立“中文汇编指令”需要哪些条件?//上海大学计算机组成原理实验报告

HackerKevon的博客 2188

Android Intent hasExtra()方法的使用

看下源码 /** * Returns true if an extra value is associated with the given name. * @param name the extra's name * @return true if the given extra is present. */ public boolean h...

小牧在一直在学习,在前进的道路上大家一起学习,进步。 1979

基于STM32H750的便携式双通道示波器与信号发生器AFE设计

示波器和信号发生器是电子测量与嵌入式系统调试的基础仪器,其核心在于模拟前端(AFE)对宽动态范围、高精度采样与低失真输出的协同实现。原理上需兼顾输入信号调理(衰减/放大/偏置)、ADC/DAC接口匹配、触发同步及电源完整性设计。技术价值体现在以低成本器件达成±15V输入/±10V输出、16位等效采样精度与85kHz带宽的工程平衡。典型应用场景包括电机驱动波形观测、传感器信号验证、电源环路测试及通信电平分析。本方案聚焦STM32H750平台,深度融合硬件拓扑与片上资源特性,为嵌入式教学与原型开发提供可复现、易

weixin_35755188的博客 109

安卓M 6.0动态权限的问题

项目开发中,相信有同志碰见,往SD卡中写数据总是失败的问题,导致升级失败等问题。安卓6.0之前只需要在清单文件中配置需要的权限即可,当用户在安装app的时候,会列出一大列的权限,甚至包括许多涉及隐私的权限,用户没注意就进行了安装,往往对用户造成损失。为此,google在安卓6.0之后,退出了动态权限的机制,即不仅需要在清单文件中进行配置,对于一些危险的权限还需要再以弹框的形式,询问用户是否开启权限

WinterRunner的博客 991

3DSlicer冠脉分割实战:从DICOM导入到三维重建的完整流程(附常见问题解决)

本文详细介绍了使用3DSlicer进行冠脉分割的完整流程,从DICOM数据导入到三维重建,涵盖环境配置、视图优化、心脏区域分割及冠脉精细分割等关键步骤。针对常见问题提供实用解决方案,帮助医学影像从业者高效完成心血管结构分析,提升诊断准确性。

weixin_29271053的博客 628

22版本Altium Designer导出生产文件的规范化操作指南

本文详细介绍了PCB设计中的Gerber文件导出流程及相关文件生成方法。主要内容包括:1)Gerber文件导出的5个关键设置步骤;2)NC钻孔文件的导出方法;3)坐标文件的生成方式;4)文件打包规范要求必须包含Gerber文件、NC钻孔文件和坐标文件;5)文件提交的两种方式(新手推荐提交原始工程文件,量产推荐仅提交Gerber文件包)。文章还特别强调了单位一致性、精度验证等注意事项,为PCB设计文件的规范输出提供了完整指导。

qq_56506325的博客 1058

Android 6.0以上的权限申请的问题

一直都有权限申请的问题,没有足够的重视,最近总是受到困扰,算了不说了,看代码吧! 1、先判断sdk的版本号 if (Build.VERSION.SDK_INT >= 23) { checkAndRequestPermission();//检查权限 } else { // 如果是Android6.0以下的机器,默认在安装时获得了所有权限,可以

铁树开花 627

Modbus协议全家桶(C#纯原生完整版):ModbusRTU + ModbusTCP + ModbusASCII 协议规范+完整封装+工业级实战

你已经掌握了C#串口/网口原生核心API和工业通信协议本质,而今天的主角Modbus协议,是工业通信领域绝对的王者、通用的标准、入门的必修课,没有之一。凡是做工业通信开发,必会Modbus协议;市面上99%的工业设备(PLC、变频器、温控仪、传感器、流量计、扫码枪)都原生支持Modbus协议。Modbus协议不是单一协议,而是一个「协议家族」,我们常说的就是这个家族的三大核心成员,也是工业现场的全部Modbus应用形态。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 563

android权限缺失,Android 6.0权限适配问题

在Android开发中经常会遇到Android系统适配问题,出现这一问题是因为Android6.0以后对系统的一些权限进行了限制,而在开发中经常会用到这些权限,网上有 许多做法都是用到哪个权限就获取哪个权限,这样的做法会造成代码的紊乱,今天带来一种方法在获取到系统权限的同时又不会造成系统业务代码, 逻辑代码的紊乱。创建一个类(判断是否缺少权限):public class PermissionsCh...

weixin_33277243的博客 717

2026最新YOLO26改进:卷积层、轻量化、注意力机制、损失函数、Backbone、SPPF、Neck、检测头全方位优化汇总

针对YOLO26模型改进痛点,本专栏整理200+实战验证方法,覆盖卷积层、注意力机制等核心模块。 每种方法含原理、性能分析、改进路径及实操流程,代码可直接运行,快速提升模型效果,性价比超高。

魔改工程师的博客 1万+

发那科机器人通信库使用指南与踩坑记录

GitHubNuGet(如本文基于该库,在 C# / .NET 下通过 TCP 与 FANUC 机器人控制器通信,实现读当前位姿、PR 寄存器、以及 DI/DO/GI/GO 等 IO 的读写。GitHubNuGet(如本文基于该库,在 C# / .NET 下通过 TCP 与 FANUC 机器人控制器通信,实现读当前位姿、PR 寄存器、以及 DI/DO/GI/GO 等 IO 的读写。

songhuangong123的博客 323

Android 6.0 - 动态权限管理的解决方案(转)

Android 6.0 - 动态权限管理的解决方案(转)

qq_38472451的博客 87

SAP_SD模块信用管理-最早未清项判断逾期

在 SAP SD 模块的信用管理(Credit Management) 中,系统可以通过 最早未清项(Oldest Open Item) 来判断客户是否存在逾期,从而影响订单的信用检查结果。例如: 定义最大未清项目%为1%,未清天数为1天,即允许客户“逾期1天的未清应收帐款/该客户的应收帐款余额”最大比例为1%,若超过1%则将被信用冻结。的信用检查功能,用于判断客户是否有账龄过长的未清款项,并据此决定是否允许新的销售订单继续处理。然后在查看客户的信贷信息可以看到,最早的未清信息显示在系统中。

我小时候很黑的博客 863

android权限管理页面,Android 6.0 - 动态权限管理的解决方案

欢迎Follow我的GitHub, 关注我的简书. 其余参考Android目录.PermissionsAndroidAndroid 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应用权限. 时代总是不断发展, 程序总是以人为本, 让我们为应用添加动态权限管理吧! ...

weixin_27070451的博客 290

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Android 6.0: 动态权限管理的解决方案

Android精品源码 封面图: Android 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应用权限. 时代总是不断发展, 程序总是以人为本, 让我们为应用添加动态权限管理吧! 这里提供了一个非常

Nicholas_Nick的博客 686

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

解决android 动态权限,android 6.0 动态权限管理的解决方案

Android 6.0版本(Api 23)推出了不少新的特性, 大幅提高了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制本身的隐私, 一方面须要从新适配应用权限. 时代老是不断发展, 程序老是以人为本, 让咱们为应用添加动态权限管理吧! 这里提供了一个很是不错的解决方案, 提供源码, 项目能够直接使用.java PermissionsandroidAn...

weixin_32757449的博客 403

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

android 获取权限管理,Android 6.0 - 动态权限管理的解决方案

欢迎Follow我的GitHub, 关注我的简书. 其余参考Android目录.PermissionsAndroidAndroid 6.0版本(Api 23)推出了很多新的特性, 大幅提升了用户体验, 同时也为程序员带来新的负担. 动态权限管理就是这样, 一方面让用户更加容易的控制自己的隐私, 一方面需要重新适配应用权限. 时代总是不断发展, 程序总是以人为本, 让我们为应用添加动态权限管理吧! ...

weixin_33260484的博客 255

Android 6.0-kotlin 动态权限管理的解决方案

参考博客:https://www.cnblogs.com/dubo-/p/6018262.html 1、MainAcitivity处理调用权限判断: package com.bai.gifmaking import android.Manifest.permission.* import android.support.v7.app.AppCompatActivity import and...

漠天的博客 1447
上一篇: android 事件分发机制
下一篇: 2016 Top 10 Android Library
僤尐僤
博客等级 码龄14年 10粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值