Android6.0权限申请讲解及Demo实例

Android6.0对权限进行了划分,分为普通权限和危险权限,危险权限需要动态申请才能使用

在dos命令行中输入adb shell pm list permissions -d -g便可得到如下危险权限:

C:\Users\Administrator.PC-20160322ZIOG>adb shell pm list permissions -d -g
Dangerous Permissions:

group:com.google.android.gms.permission.CAR_INFORMATION
  permission:com.google.android.gms.permission.CAR_VENDOR_EXTENSION
  permission:com.google.android.gms.permission.CAR_MILEAGE
  permission:com.google.android.gms.permission.CAR_FUEL

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:com.google.android.gms.permission.CAR_SPEED
  permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE
  permission:android.permission.READ_EXTERNAL_STORAGE
  permission:android.permission.WRITE_EXTERNAL_STORAGE

group:com.sina.weibo.permission-group
  permission:com.sina.weibo.permission.USER

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

ungrouped:
  permission:com.huawei.pushagent.permission.RICHMEDIA_PROVIDER
  permission:com.huawei.permission.ACCESS_FM
  permission:com.huawei.motion.permission.MOTION_EX
  permission:org.fidoalliance.uaf.permissions.FIDO_CLIENT
  permission:com.huawei.contacts.permission.CHOOSE_SUBSCRIPTION
通过观察可以发现危险权限都是成组出现的,我们将其称之为权限组,如果用户允许了一组权限中的一个那么就等于允许了这一组中所有的权限(目前是这样的)。

下面我们以申请拨打电话的权限来介绍如何向用户申请授权:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int CALL_PHONE_REQUESTCODE = 0;//申请打电话权限的请求码,≥0即可
    private View mCall;

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

        initView();
        initData();
        initListener();
    }

    public void initView() {
        mCall = findViewById(R.id.call);
    }

    public void initData() {}

    public void initListener() {
        mCall.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.call:
                performClickCall();
                break;

            default:
                break;
        }
    }

    private void performClickCall() {
        //检测是否有拨打电话的权限
        int checkSelfPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
        if (checkSelfPermission == PackageManager.PERMISSION_GRANTED) {
            call();//打电话
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, CALL_PHONE_REQUESTCODE);//动态申请打电话权限
        }
    }

    /**
     * 拨打电话的方法
     */
    private void call() {
        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:10086"));
        startActivity(intent);
    }

    /**
     * 动态申请权限的回调
     *
     * @param requestCode  请求码,如果请求多个权限时,用以区分是哪个权限
     * @param permissions  权限数组
     * @param grantResults 权限是否授权的结果数组
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case CALL_PHONE_REQUESTCODE:
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    call();
                } else {
                    Toast.makeText(this, "用户未允许打电话权限", Toast.LENGTH_SHORT).show();
                    boolean b = shouldShowRequestPermissionRationale(Manifest.permission.CALL_PHONE);
                    if(!b) {
                        //用户没同意授权,还不让下次继续提醒授权了,这是比较糟糕的情况
                        Toast.makeText(this,"用户勾选了下次不再提醒选项", Toast.LENGTH_SHORT).show();
                    }
                }
                break;

            default:
                break;
        }
    }

}
activity_main文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.qj.android60permission.MainActivity">

    <Button
        android:id="@+id/call"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="call"/>
</RelativeLayout>
清单文件中添加:
<uses-permission android:name="android.permission.CALL_PHONE"/>
以上代码很简单,其它权限的申请和这个类似,这里需要说一下其中一个方法,只是我个人的理解,希望读者辩证性的看待:

public boolean shouldShowRequestPermissionRationale(@android.support.annotation.NonNull java.lang.String permission)
这个方法从命名上看表示是否应该向用户展示请求该权限,返回一个布尔值,经测试发现:当请求权限的对话框允许向用户展示的时候返回true,当用户勾选了下次不要再弹框提醒的时候返回false

我对该方法的理解是:

当用户拒绝了我们请求的权限,我们调用该方法判断用户是否勾选了下次不再弹框提醒,这个方法返回的false的处理对我们来说更重要一些。因为如果用户拒绝了权限的请求并且下次也不弹框提醒请求该权限,那么该权限恐怕很难被授权了(这样可能会影响我们app的功能);至于该方法返回true的情况,说明我们还具备向用户申请权限弹框展示的机会,用户看到需要他允许某个权限才能继续操作,一般情况会允许的,若不允许可以给予一定的引导提醒。
下面是Android对该方法的介绍

Gets whether you should show UI with rationale for requesting a permission. You should do this only if you do not have the permission and the context
in which the permission is requested does not clearly communicate to the user what would be the benefit from granting this permission.
For example, if you write a camera app, requesting the camera permission would be expected by the user and no rationale for why it is requested is needed.
If however, the app needs location for tagging photos then a non-tech savvy user may wonder how location is related to taking photos. 
In this case you may choose to show UI with rationale of requesting this permission.
我对该方法的理解不一定正确,若大家有不同的意见尽可畅所欲言!




版权声明:本文为github_2011原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。