Android 6.0+ 运行时权限探索
来源:互联网 发布:长江师范学院网络教学 编辑:程序博客网 时间:2024/06/05 04:43
引言:去年Android 6.0发布后,其新引入的(Requesting Permissions at Run Time)运行时权限就备受开发者关注,随着今年国内手机厂商对6.0系统的普及,觉得大家有必要了解下这个新特性,因为在TargetSDK23+进行开发不注意这些会造成APP运行在6.0+手机上崩溃,这篇博文将对这个新特性进行探索。
在之前的SDK开发中,如果需要用到一些权限例如打电话,发短信只在AndroidManifest中配置一下就可以了,但是SDK23+以上用到一些危险敏感(Dangerous Permissions)权限就不仅仅是在AndroidManifest配置一下就可以了,需要在操作发生前需要让用户进行授予权限才能进行下一步的操作,跟iOS的权限处理很像,如果没让用户授予权限或用户拒绝了此权限再进行操作例如打电话就会造成软件崩溃。
*如果你的app TargetSDK设置在了23以下那么在6.0+系统中运行是不会崩溃的,当然你也可以TargetSDK一直设置在23以下,那么这篇文章你就没必要继续看了:)
那么到底哪些权限需要进行在运行时进行授权呢?看下官方的说明
Dangerous permissions
以上这些权限不仅仅需要在AndroidManifest配置,还需要在运行时让用户进行授予权限才能使用这些功能。
可以看到打电话是需要进行运行时授权的,我们就做个点击按钮打电话的小demo,看看这个运行时权限到底怎么回事。
1:需要将APP的targetSdkVersion设置到23以上并且在Android6.0以上系统运行
2:在AndroidManifest中配置拨打电话的权限
<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">uses-permission</span> <span class="hljs-attribute">android:name</span>=<span class="hljs-value">"android.permission.CALL_PHONE"</span>></span><span class="hljs-tag"></<span class="hljs-title">uses-permission</span>></span></code>
3:在布局layout中我们就简简单单放个按钮,点击进行拨打电话(略)
4.1:如果不做运行时权限处理会怎么样呢?我们直接进行点击按钮拨打电话
<code class="hljs cs has-numbering"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CallPhone</span>(View v) { Intent intent = <span class="hljs-keyword">new</span> Intent(Intent.ACTION_CALL); Uri data = Uri.parse(<span class="hljs-string">"tel:"</span> + <span class="hljs-string">"10010"</span>); intent.setData(data); startActivity(intent); } </code>
运行效果:
可以看到在android 6.0系统上运行会崩溃
4.2:我们加上运行时权限的处理再运行
<code class="hljs java has-numbering"> <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> REQUESTCODE = <span class="hljs-number">8</span>; <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CallPhone</span>(View v) { <span class="hljs-comment">//检查权限</span> <span class="hljs-keyword">if</span> (ContextCompat.checkSelfPermission(<span class="hljs-keyword">this</span>, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { <span class="hljs-comment">//没有权限,申请权限</span> ActivityCompat.requestPermissions(<span class="hljs-keyword">this</span>, <span class="hljs-keyword">new</span> String[]{Manifest.permission.CALL_PHONE}, REQUESTCODE); } <span class="hljs-keyword">else</span> { <span class="hljs-comment">//已经拥有权限进行拨打</span> call(); } } </code>
API:
REQUESTCODE的作用是为了进行回调处理,因为申请权限是有回调结果的后面会说到。
ContextCompat.checkSelfPermission 主要用于检测某个权限是否已经被授予,方法参数为(context,需要检测的权限)方法返回值为PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED,当返回PackageManager.PERMISSION_DENIED时需要调用API进行权限申请。
ActivityCompat.requestPermissions 用于权限的申请,方法参数为(context,需要申请的权限数组,自定义的请求码),系统会弹出一个申请权限的对话框。
运行效果:可以看到程序已经成功进行了电话的拨打。
4.3 但是如果用户拒绝了此权限并且设置了不再提醒怎么办呢?点击按钮就会没响应了,是非常不友好的,如下。
稍稍改下代码
<code class="hljs java has-numbering"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CallPhone</span>(View v) { <span class="hljs-comment">//检查权限</span> <span class="hljs-keyword">if</span> (ContextCompat.checkSelfPermission(<span class="hljs-keyword">this</span>, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { <span class="hljs-keyword">if</span> (ActivityCompat.shouldShowRequestPermissionRationale(<span class="hljs-keyword">this</span>, Manifest.permission.CALL_PHONE)) { <span class="hljs-keyword">new</span> AlertDialog.Builder(MainActivity.<span class="hljs-keyword">this</span>) .setMessage(<span class="hljs-string">"app需要开启权限才能使用此功能"</span>) .setPositiveButton(<span class="hljs-string">"设置"</span>, <span class="hljs-keyword">new</span> DialogInterface.OnClickListener() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span>(DialogInterface dialogInterface, <span class="hljs-keyword">int</span> i) { Intent intent = <span class="hljs-keyword">new</span> Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse(<span class="hljs-string">"package:"</span> + getPackageName())); startActivity(intent); } }) .setNegativeButton(<span class="hljs-string">"取消"</span>, <span class="hljs-keyword">null</span>) .create() .show(); } <span class="hljs-keyword">else</span> { <span class="hljs-comment">//申请权限</span> ActivityCompat.requestPermissions(<span class="hljs-keyword">this</span>, <span class="hljs-keyword">new</span> String[]{Manifest.permission.CALL_PHONE}, REQUESTCODE); } } <span class="hljs-keyword">else</span> { <span class="hljs-comment">//已经拥有权限进行拨打</span> call(); } } </code>
这里我们在申请权限前加了个判断ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CALL_PHONE)方法参数为(context,需要检测的权限)如果返回true证明用户上次点击已经选了拒绝,所以我们进行一些友好的提示,这里做的是进行进行提示并让用户跳转到设置将权限打开。
5:OK 最后介绍下,申请权限的回调方法处理
<code class="hljs java has-numbering"> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span>(<span class="hljs-keyword">int</span> requestCode, @NonNull String[] permissions, @NonNull <span class="hljs-keyword">int</span>[] grantResults) { <span class="hljs-keyword">switch</span> (requestCode) { <span class="hljs-keyword">case</span> REQUESTCODE: { <span class="hljs-keyword">if</span> (grantResults.length > <span class="hljs-number">0</span> && grantResults[<span class="hljs-number">0</span>] == PackageManager.PERMISSION_GRANTED) { <span class="hljs-comment">//用户同意了授权</span> call(); } <span class="hljs-keyword">else</span> { <span class="hljs-comment">//用户拒绝了授权</span> <span class="hljs-comment">// Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();</span> } <span class="hljs-keyword">return</span>; } } } </code>
这个方法跟onActivityResult比较类似,先判断requestCode,之后在判断用户的授权状态,grantResults数组代表了权限的结果数组,有点绕口,哈哈,之前申请权限是支持数组的,所以 onRequestPermissionsResult的返回结果也放到了一个数组里面,数组grantResults[n] == PackageManager.PERMISSION_GRANTED代表这个权限已经被用户授权了。
final:最后我们看下完整的代码
<code class="hljs java has-numbering"><span class="hljs-javadoc">/** * blog:www.lijizhou.com */</span><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppCompatActivity</span> {</span> <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onCreate</span>(Bundle savedInstanceState) { <span class="hljs-keyword">super</span>.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> REQUESTCODE = <span class="hljs-number">8</span>; <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CallPhone</span>(View v) { <span class="hljs-comment">//检查权限</span> <span class="hljs-keyword">if</span> (ContextCompat.checkSelfPermission(<span class="hljs-keyword">this</span>, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { <span class="hljs-keyword">if</span> (ActivityCompat.shouldShowRequestPermissionRationale(<span class="hljs-keyword">this</span>, Manifest.permission.CALL_PHONE)) { <span class="hljs-keyword">new</span> AlertDialog.Builder(MainActivity.<span class="hljs-keyword">this</span>) .setMessage(<span class="hljs-string">"app需要开启权限才能使用此功能"</span>) .setPositiveButton(<span class="hljs-string">"设置"</span>, <span class="hljs-keyword">new</span> DialogInterface.OnClickListener() { <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span>(DialogInterface dialogInterface, <span class="hljs-keyword">int</span> i) { Intent intent = <span class="hljs-keyword">new</span> Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse(<span class="hljs-string">"package:"</span> + getPackageName())); startActivity(intent); } }) .setNegativeButton(<span class="hljs-string">"取消"</span>, <span class="hljs-keyword">null</span>) .create() .show(); } <span class="hljs-keyword">else</span> { <span class="hljs-comment">//申请权限</span> ActivityCompat.requestPermissions(<span class="hljs-keyword">this</span>, <span class="hljs-keyword">new</span> String[]{Manifest.permission.CALL_PHONE}, REQUESTCODE); } } <span class="hljs-keyword">else</span> { <span class="hljs-comment">//已经拥有权限进行拨打</span> call(); } } <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">call</span>() { Intent intent = <span class="hljs-keyword">new</span> Intent(Intent.ACTION_CALL); Uri data = Uri.parse(<span class="hljs-string">"tel:"</span> + <span class="hljs-string">"10010"</span>); intent.setData(data); startActivity(intent); } <span class="hljs-annotation">@Override</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onRequestPermissionsResult</span>(<span class="hljs-keyword">int</span> requestCode, @NonNull String[] permissions, @NonNull <span class="hljs-keyword">int</span>[] grantResults) { <span class="hljs-keyword">switch</span> (requestCode) { <span class="hljs-keyword">case</span> REQUESTCODE: { <span class="hljs-keyword">if</span> (grantResults.length > <span class="hljs-number">0</span> && grantResults[<span class="hljs-number">0</span>] == PackageManager.PERMISSION_GRANTED) { <span class="hljs-comment">//用户同意了授权</span> call(); } <span class="hljs-keyword">else</span> { <span class="hljs-comment">//用户拒绝了授权</span> <span class="hljs-comment">// Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_SHORT).show();</span> } <span class="hljs-keyword">return</span>; } } }} </code>
OK,一个利用android原始API进行的运行时权限处理就介绍完了,当然你也可以对此进行封装方便使用,欢迎大家在下方留言,本篇源码下载地址 http://download.csdn.net/detail/leejizhou/9532629
- Android 6.0+ 运行时权限探索
- Android 6.0+ 运行时权限探索
- Android 6.0+ 运行时权限探索
- Android 6.0+ 运行时权限探索
- Android 6.0+ 运行时权限探索
- Android 6.0运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- Android 6.0+ 运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- android 6.0运行时权限
- android 6.0运行时权限
- Android 6.0 运行时权限
- Android 6.0运行时权限
- Android 6.0运行时权限
- Android 6.0 运行时权限
- Android 6.0运行时权限
- PHP 模糊搜索
- fragement生命周期
- 从Android代码中来记忆23种设计模式
- 文件编码及UTF-8、BOM、0XFEFF相关问题
- "巴卡斯杯" 中国大学生程序设计竞赛 - 女生专场(重现)解题思路
- Android 6.0+ 运行时权限探索
- 使用Myeclipse 10开发基于JAX-WS的Web service实例
- 微机原理中$求内存数据个数
- ajax库类以及使用方法
- 【Android】27、常见控件的使用方法——TextView
- 网站常用效果
- 常见的八种导致 APP 内存泄漏的问题
- typedef的用法
- 4. Median of Two Sorted Arrays