Android M以上运行时权限(Google官方出品)
转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6690152.html
网上运行时权限的例子、Demo无计其数,但是和Google官方出品的比起来,都显得很啰嗦。作为Android开发人员应该以Google的实例为样本。官方出品,必属精品!!!
Google官方Runtime Permissions Demo地址:https://github.com/googlesamples/android-RuntimePermissions
Demo如下(这里强调一下,Google推荐使用Snackbar代替Toast)

在 Android M 版本(即6.0以后的版本),多了一个特殊权限处理。开发者的开发工具Android Studio 如果是 Android API 23 Platform或以上版本,需要在调用特殊权限的地方手动将权限打开,在 AndroidManifest 直接说明是不好用的。
那么都有哪些权限是需要特殊处理的呢。下面我就把这些特殊权限按类罗列出来,并告诉你如何在代码中进行手动调用。
需要单独申请的权限共分为9组,每组只要有一个权限申请成功,默认整组权限都可以使用了。
①使用您的通讯录
group:android.permission-group.CONTACTS
permission:android.permission.WRITE_CONTACTS
permission:android.permission.GET_ACCOUNTS
permission:android.permission.READ_CONTACTS
②拨打电话和管理通话
group:android.permission-group.PHONE
permission:android.permission.READ_CALL_LOG
permission:android.permission.READ_PHONE_STATE
permission:android.permission.CALL_PHONE
permission:android.permission.WRITE_CALL_LOG
permission:android.permission.USE_SIP
permission:android.permission.PROCESS_OUTGOING_CALLS
permission:com.android.voicemail.permission.ADD_VOICEMAIL
③访问您的日历
group:android.permission-group.CALENDAR
permission:android.permission.READ_CALENDAR
permission:android.permission.WRITE_CALENDAR
④拍摄照片和录制视频
group:android.permission-group.CAMERA
permission:android.permission.CAMERA
⑤访问与您的生命体征相关的传感器数据
group:android.permission-group.SENSORS
permission:android.permission.BODY_SENSORS
⑥使用此设备的位置信息
group:android.permission-group.LOCATION
permission:android.permission.ACCESS_FINE_LOCATION
permission:android.permission.ACCESS_COARSE_LOCATION
⑦访问您设备上的照片、媒体内容和文件
group:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
⑧录制音频
group:android.permission-group.MICROPHONE
permission:android.permission.RECORD_AUDIO
⑨发送和查看短信
group:android.permission-group.SMS
permission:android.permission.READ_SMS
permission:android.permission.RECEIVE_WAP_PUSH
permission:android.permission.RECEIVE_MMS
permission:android.permission.RECEIVE_SMS
permission:android.permission.SEND_SMS
permission:android.permission.READ_CELL_BROADCASTS
废话不多说,让我们一探究竟Google是如何处理Android M以上运行时权限的。
以"联系人权限"为例做演示,其他的权限大同小异。
1.创建一个工具类PermissionUtil
Google对这个工具类作出的解释是 Utility class that wraps access to the runtime permissions API in M and provides basic helper methods.
即:在M中包含对运行时权限API的访问的实用程序类,并提供基本的帮助方法。
public abstract class PermissionUtil {
    /**
     * 检查所有给定的权限是否通过验证给定数组中的每个条目都具有该值*/
    public static boolean verifyPermissions(int[] grantResults) {
        // 至少检查一个结果
        if (grantResults.length < 1) {
            return false;
        }
        // 验证是否已授予每个必需的权限,否则返回false
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }
}
2.联系人权限已在Android M及以上版本中声明。 它们在旧平台上不可用,因此我们隐藏按钮以访问联系人数据库。这显示了如何添加新的运行时权限,不适用于较旧的平台版本。 这对于其他权限可能会提示用户进行升级的自动更新非常有用。
public class RuntimePermissionsFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_main, null);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            root.findViewById(R.id.button_contacts).setVisibility(View.GONE);
        }
        return root;
    }
}
3.主类
public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback {
    private static final String TAG = "MainActivity";
    /**
     * 用于标识请求联系人权限的Id
     */
    private static final int REQUEST_CONTACTS = 0;
    /**
     * 联系人读、写所需的权限
     */
    private static String[] PERMISSIONS_CONTACT = {
            Manifest.permission.READ_CONTACTS,
            Manifest.permission.WRITE_CONTACTS
    };
    /**
     * Activity的根布局
     */
    private View mLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLayout = findViewById(R.id.content_fragment);
        if (savedInstanceState == null) {
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            RuntimePermissionsFragment fragment = new RuntimePermissionsFragment();
            transaction.replace(R.id.content_fragment, fragment);
            transaction.commit();
        }
    }
    /**
     * 当点击“显示联系人”按钮时调用
     * 回调在布局文件中定义
     */
    public void showContacts(View v) {
        Log.i(TAG, "Show contacts button pressed. Checking permissions.");
        // 验证是否已授予所需的联系人权限
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED
                || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            // 尚未被授予联系人权限
            Log.i(TAG, "Contact permissions has NOT been granted. Requesting permissions.");
            requestContactsPermissions();
        } else {
            // 联系权限已被授予。 显示联系人片段
            Log.i(TAG, "Contact permissions have already been granted. Displaying contact details.");
        }
    }
    /**
     * 请求联系人权限
     * 如果以前已经拒绝许可,SnackBar将提示用户授予权限,否则直接请求
     */
    private void requestContactsPermissions() {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)
                || ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_CONTACTS)) {
// 显示一个带有说明和按钮的SnackBar来触发请求
            Snackbar.make(mLayout, R.string.permission_contacts_rationale, Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_CONTACT, REQUEST_CONTACTS);
                        }
                    }).show();
        } else {
            // 联系人权限尚未被授予,直接请求
            ActivityCompat.requestPermissions(this, PERMISSIONS_CONTACT, REQUEST_CONTACTS);
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_CONTACTS) {
            Log.i(TAG, "Received response for contact permissions request.");
            // 已经为联系人请求了权限,因此这些权限都需要检查
            if (PermissionUtil.verifyPermissions(grantResults)) {
                // 已授予所有必需的权限,显示联系人片段
                Snackbar.make(mLayout, R.string.permision_available_contacts, Snackbar.LENGTH_SHORT).show();
            } else {
                Log.i(TAG, "Contacts permissions were NOT granted.");
                Snackbar.make(mLayout, R.string.permissions_not_granted, Snackbar.LENGTH_SHORT).show();
            }
        } else {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
}
4.在AndroidManifest加上需要申请的权限
<!-- 仅当设备在M或更高版本上时,才需要以下权限。在较旧的平台上,这些权限不被请求,并且将不可用。 -->
<uses-permission-sdk-23 android:name="android.permission.READ_CONTACTS" />
<uses-permission-sdk-23 android:name="android.permission.WRITE_CONTACTS" />
以上就是Google官方提供的完整而且简洁的运行时权限Demo
关注我的新浪微博,获取更多Android开发资讯!
关注科技评论家,领略科技、创新、教育以及最大化人类智慧与想象力!
Android M以上运行时权限(Google官方出品)的更多相关文章
- Android权限管理之Android 6.0运行时权限及解决办法
		
前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...
 - Android M Permission 运行时权限 学习笔记
		
Android M Permission 运行时权限 学习笔记 从Android 6.0开始, 用户需要在运行时请求权限, 本文对运行时权限的申请和处理进行介绍, 并讨论了使用运行时权限时新老版本的一 ...
 - Android PermissionUtils:运行时权限工具类及申请权限的正确姿势
		
Android PermissionUtils:运行时权限工具类及申请权限的正确姿势 ifadai 关注 2017.06.16 16:22* 字数 318 阅读 3637评论 1喜欢 6 Permis ...
 - Android 6.0 运行时权限处理完全解析
		
一.概述 随着Android 6.0发布以及普及,我们开发者所要应对的主要就是新版本SDK带来的一些变化,首先关注的就是权限机制的变化.对于6.0的几个主要的变化,查看查看官网的这篇文章http:// ...
 - 谈谈Android 6.0运行时权限理解
		
前言 谷歌在2015年8月份时候,发布了Android 6.0版本,代号叫做“棉花糖”(Marshmallow ),其中的很大的一部分变化,是在用户权限授权上,或许是感觉之前默认授权的不合理,现在6. ...
 - Android 6.0运行时权限
		
一.Runtime Permissions Android 6.0在手机安全方面做的一个处理就是增加了运行时权限(Runtime Permissions). 新的权限机制更好的保护了用户的隐私,Goo ...
 - Android 6.0 运行时权限处理问题
		
序 自从升级到Android M以来,最大的改变就是增加了运行时权限RuntimePermission,6.0以上的系统如果没有做适配,运行了targetSDK=23的App时就会报权限错误.我们知道 ...
 - Android 6.0 运行时权限处理完全解析 (摘抄)
		
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/50709663: 本文出自:[张鸿洋的博客] 一.概述 随着Android 6. ...
 - Android数据存储之Android 6.0运行时权限下文件存储的思考
		
前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...
 
随机推荐
- JavaScript中数组Array方法详解
			
ECMAScript 3在Array.prototype中定义了一些很有用的操作数组的函数,这意味着这些函数作为任何数组的方法都是可用的. 1.Array.join()方法 Array.join()方 ...
 - 【译】Nodejs最好的ORM - TypeORM
			
TypeORM github: https://github.com/typeorm/typeorm 这篇译文是从TypeORM github上的使用说明上翻译过来的,已经提交PR并merge到库中了 ...
 - 定制Maven的ArcheType
			
根据需要定制Maven的ArcheType的好处不言而喻了,我就不再啰嗦.定制一般通过从Maven的项目构建,比手动构建省去了配置文件的编写.资源文件的复制等繁琐的操作,下面我们就说下从Maven项目 ...
 - 在node中使用 ES6
			
ES6+ 太棒了,但是很多高级功能node是不支持的,就需要使用babel转换成ES5, 1.安装babel依赖 npm install babel-core --save-dev 2.安装babel ...
 - 算法模板——splay区间反转 1
			
实现的功能:将序列区间反转,并维护 详见BZOJ3223 var i,j,k,l,m,n,head,a1,a2:longint; s1:ansistring; a,b,c,d,fat,lef,rig: ...
 - Spring Boot启动过程(五):Springboot内嵌Tomcat对象的start
			
标题和上一篇很像,所以特别强调一下,这个是Tomcat对象的. 从TomcatEmbeddedServletContainer的this.tomcat.start()开始,主要是利用Lifecycle ...
 - 配置adb环境变量
			
作为Android开发人员,会经常使用adb命令来进行push.pull.install.看数据库等.记录一下adb配置流程,以备后用. 在没有配置adb之前,我们打开Windows命令处理程序(cm ...
 - PHP语言开发微信公众平台(订阅号)之开启基本功能及获得可用的服务器地址(2)
			
1.开启群发功能(单击功能菜单里的"群发功能",并在右侧页面中点击"同意以上声明") 2.(1)在开启开发者模式之前需要完善个人资料(完成头像上传即可) (2) ...
 - input的type属性引申的日历组件
			
HTML5规范里只规定date新型input输入类型,并没有规定日历弹出框的实现和样式.所以,各浏览器根据自己的设计实现日历.目前只有谷歌浏览器完全实现日历功能.相信这种局面很快就会结束,所有的浏览器 ...
 - TCP/IP笔记(三)数据链路层
			
数据链路的作用 数据链路层的协议定义了通过通信媒介互连的设备之间传输的规范.通信媒介包括双绞线电缆.同轴电缆.光纤.电波以及红外线等介质.此外,各个设备之间有时也会通过交换机.网桥.中继器等中转数据. ...