Android 6.0动态权限申请

Android 6.0动态权限申请_第1张图片
权限申请图

Android 6.0 (API 23) 之前应用的权限在安装时全部授予,运行时应用不再需要询问用户。在 Android 6.0 或更高版本对权限进行了分类,对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。这样就不需要在安装时被强迫同意某些权限。

应用的targetSDKVersion < 23时,权限检查仍是早期的形式(仅在安装时赋予权限,使用时将不被提醒);
应用的targetSDKVersion ≥ 23时,则将使用新的运行时权限规则。

新的权限机制更好的保护了用户的隐私,Google将权限分为三类:

  • Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动、访问网络等;
  • Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、访问通讯录等;
  • Special PermissionsSYSTEM_ALERT_WINDOWWRITE_SETTINGS 这两个权限比较特殊,不能通过代码申请方式获取,必须得用户打开软件设置页手动打开,才能授权。
1. 权限组
权限组 权限
CALENDA READ_CALENDAR
WRITE_CALENDAR
CAMERA CAMERA
CONTACTS READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE RECORD_AUDIO
PHONE READ_PHONE_STATE
READ_PHONE_NUMBERS
CALL_PHONE
ANSWER_PHONE_CALLS (must request at runtime)
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
ANSWER_PHONE_CALLS
SENSORS BODY_SENSORS
SMS SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
2. 权限申请

1)声明权限
在 AndroidManifest.xml 中声明所需权限:


    ... 
      //电话
     //拍照
     //sd卡 
    ...

2)检查权限
方法:

// 检查权限
ContextCompat.checkSelfPermission(Context context, String permission)

返回值PackageManager常量有两种情况:PackageManager.PERMISSION_GRANTED(有权限)、PackageManager.PERMISSION_DENIED(无权限)

示例:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    int permission = ContextCompat.checkSelfPermission(MainActivity.this,
                     Manifest.permission.CALL_PHONE);
    if (permission == PackageManager.PERMISSION_GRANTED) {
        //表示有权限
    } else {
        //表示无权限
    }
}

当应用需要用到危险权限时,在执行权限相关代码前,使用该方法判断是否拥有指定的权限。有权限,则继续执行设计需要权限的代码;无权限,则向用户请求授予权限。

3)解释权限
方法:

// 解释权限
ActivityCompat.shouldShowRequestPermissionRationale(Activity activity, String permission)

示例:

if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)) {
    //拒绝权限
} else {
    //申请对应的权限
}

判断是否有必要向用户解释为什么要这项权限。如果应用第一次请求过此权限,但是被用户拒绝了,则之后调用该方法将返回 true,此时就有必要向用户详细说明需要此权限的原因。如果用户勾选了权限请求对话框的 “不再询问”,则此方法返回 false。如果设备规范禁止应用拥有该权限,此方法也返回 false。

4)请求权限
方法:

// 请求权限
ActivityCompat.requestPermissions(Activity activity, String[] permissions, int requestCode)

示例:

ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, 100);

当检测到应用没有指定的权限时,调用此方法向用户请求权限。调用此方法将弹出权限请求对话框询问用户 “允许” 或 “拒绝” 指定的权限。

5)处理结果
方法:

//处理权限请求结果
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    // ...
}

示例:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 100) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //授权
        } else {
            //拒绝
        }
    }
}

requestCode请求权限时传入的请求码,用于区别是哪一次请求的;
permissions所请求的所有权限的数组;
grantResults权限授予结果,和 permissions 数组参数中的权限一一对应,元素值为两种情况:
授予: PackageManager.PERMISSION_GRANTED,拒绝:PackageManager.PERMISSION_DENIED

3. 代码案例
public class MainActivity extends AppCompatActivity {
    private static final int REQUEST_CODE = 100;
    private Button btn_record;
    private String[] permit = new String[] {
        Manifest.permission.CAMERA,
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.CALL_PHONE
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_record = (Button) findViewById(R.id.btn_record);
        btn_record.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    List mPermissionList = new ArrayList<>();
                    for(String permission : permit) {
                        if(ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {//权限判断
                            permissionLists.add(permission);
                        }
                    }
                    if(!permissionLists.isEmpty()) {
                        ActivityCompat.requestPermissions(this, permissionLists.toArray(new String[permissionLists.size()]), REQUEST_CODE);
                    } else { //表示全都授权了
                        callPhone();
                    }
                } else {
                    callPhone();
                }
            }
        });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,  String[] permissions,  int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE) {
            if(grantResults.length > 0) {
                //存放没授权的权限
                List deniedPermissions = new ArrayList<>();
                for(int i = 0; i < grantResults.length; i++) {
                    int grantResult = grantResults[i];
                    String permission = permissions[i];
                    if(grantResult != PackageManager.PERMISSION_GRANTED) {
                        deniedPermissions.add(permission);
                    }
                }
                if(deniedPermissions.isEmpty()) {
                    //都授权了
                    callPhone();
                } else { //没有授权                 
                    Toast.makeText(MainActivity.this, "被拒绝的权限:" + deniedPermissions.toString(), Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    public void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:" + "10086");
        intent.setData(data);
        startActivity(intent);
    }

}

你可能感兴趣的:(Android 6.0动态权限申请)