Android 6.0 权限笔记

作者: wxyass 分类: Android 发布时间: 2017-07-30 14:26

Android6.0权限笔记

Android开发团队在6.0系统引用了运行时权限的功能,能更好的保护用户的安全和隐私.

对开发者来说,问题也就来了:

1 这种运行时权限如何使用

2 对低于6.0系统的软件造成什么影响

3 在 Github 上关于权限的封装库推荐

4 不想用运行时权限,还想用之前的默认权限,怎么做


下面是关于权限的笔记,可能会比较乱

一 当手机低于6.0系统

使用某个权限时(比如:拍照,定位等等),直接在清单文件中配置即可

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.wxyaass.homepermission">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    ...

</manifest>  

当应用在手机安装成功,则表示这些权限都申请成功了.

二 Android 6.0 权限分类

1 普通权限: 用法不变,还是在清单文件中注册即可,

2 危险权限: 除了在清单文件中注册,还要做另外的处理,下面讲.

3 特别权限: 很少用,不做介绍

Android中有上百种权限,我们如何区分哪些是普通权限,哪些是危险权限呢? 很简单,下面列出9组24个危险权限,除此之外的就都是普通权限.

CONTACTS(联系人)  
  permission:android.permission.WRITE_CONTACTS
  permission:android.permission.GET_ACCOUNTS
  permission:android.permission.READ_CONTACTS

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

CALENDAR(日历)   
  permission:android.permission.READ_CALENDAR
  permission:android.permission.WRITE_CALENDAR

CAMERA(相机)  
  permission:android.permission.CAMERA

SENSORS(传感器)  
  permission:android.permission.BODY_SENSORS

LOCATION(位置)   
  permission:android.permission.ACCESS_FINE_LOCATION
  permission:android.permission.ACCESS_COARSE_LOCATION

STORAGE(存储卡)  
  permission:android.permission.READ_EXTERNAL_STORAGE
  permission:android.permission.WRITE_EXTERNAL_STORAGE

MICROPHONE(麦克风)  
  permission:android.permission.RECORD_AUDIO

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   

三 以打电话为例,对运行时权限做解析

因为拨打电话会涉及到用户手机资费问题,因而 CALL_PHONE 这个权限被列为危险权限. 在Android 6.0 系统出现之前, 拨打电话的实现其实非常简单.

只需在清单文件中注册该权限即可.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.wxyaass.homepermission">

    <uses-permission android:name="android.permission.CALL_PHONE" />

    <application
       ...
    </application>

</manifest>

可在MainActivity中触发拨打电话的逻辑来测试权限是否申请成功.

Button makeCall = (Button)findViewById(R.id.call);
makeCall.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        try{
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
});

这样我们就将拨打电话的功能成功实现了,并且在低于Android 6.0 系统的手机都是可以正常运行的.

但是如果我们在6.0 或者更高版本系统的手机上运行,点击按钮就没有任何效果,观察日志:

错误信息中提醒我们”Permission Denial”, 可以看出,是由于权限被禁止导致的, 因为 6.0 及以上系统在使用危险权限时都必须进行运行时权限处理.

下面我们尝试修复这个问题, 修改 MainActivity 中的代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button makeCall = (Button)findViewById(R.id.call);
        makeCall.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.
                        permission.CALL_PHONE)!=PackageManager.PERMISSION_GRANTED){
                    ActivityCompat.requestPermissions(MainActivity.this,new
                            String[]{Manifest.permission.CALL_PHONE},1);
                }else{
                    call();;
                }
            }
        });
    }

    private void call(){
        try{
            Intent intent = new Intent(Intent.ACTION_CALL);
            intent.setData(Uri.parse("tel:10086"));
            startActivity(intent);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case 1:
                if(grantResults.length>0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    call();
                }else{
                    Toast.makeText(this,"你拒绝了拨打电话权限",Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }
}

第一步就是要先判断用户是不是已经给过我们授权了,
借助的是 ContextCompat.checkSelfPermission() 方法. checkSelfPermission() 接收两个参数,第一个参数是Context,第二个参数是具体的权限名,比如打电话的权限名就是 Manifest.permission.CALL_PHONE,
然后我们使用方法的返回值和 PackageManager.PERMISSION_GRANTED 做比较,想等就说明用户已经授权,不等就表示用户没有授权.

如果已经授权的话就简单了, 直接去执行拨打电话的逻辑操作就可以了, 如果没有授权的话, 则需要调用此方法的调用 ActivityCompat.requestPermissions() 方法来向用户申请授权, requestPermissions() 方法接收3个参数, 第一个参数要求是 Activity 的实例, 第二个参数是一个 String 数组, 我们把要申请的权限名放在数组中即可, 第三个参数是请求码, 只要是唯一值就可以了, 这里传入了1.

调用完 requestPermissions() 方法之后 , 系统会弹出一个权限申请的对话框, 然后用户可以选择同意或拒绝我们的权限申请, 不论哪种结果, 最终都会回调到 onRequestPermissionsResult() 方法中, 而授权的结果会封装到 grantResults 参数当中. 这里我们只需要判断一下最后的授权结果, 如果用户同意的话就调用 call() 方法来拨打电话, 如果用户拒绝的话我们只能放弃操作, 并且弹出一条失败提示.

当对话框出现时, 用户选择了拒绝授权, 当再次点击按钮, 仍旧会弹出权限申请的对话框.

当用户同意授权,我们就成功进入拨打电话的界面, 之后再次点击按钮就不会再弹出权限申请的对话框了.

四 关于权限库的推荐

RxPermissions
https://github.com/tbruyelle/RxPermissions
MPermissions
https://github.com/hongyangAndroid/MPermissions
PermissionGen
https://github.com/lovedise/PermissionGen

五 自己封装的权限的例子,简单不花哨

例子下载
将例子分别跑到4.0和6.0的手机上,会发现明显不同

博客参考:
http://blog.csdn.net/lmj623565791/article/details/50709663
http://blog.csdn.net/li15225271052/article/details/71076350

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

发表评论

邮箱地址不会被公开。 必填项已用*标注