权限变更: Android 6.0 开始,Google把权限分为两类: 一类为普通权限: Normal Permission ,这类权限不涉及用户隐私,是不需要用户授权的,在AndroidManifest.xml里 申请权限即可,比如访问网络:
一类为危险权限:Dangerous Permission,涉及隐私的,需要用户授权,比如访问通讯录、定位。这类不仅要在 AndroidManifest.xml里申请权限,还要动态获取权限,需要用户同意!
下面列出危险权限列表:
来源: https://blog.csdn.net/f917386389/article/details/87655811
每个危险权限都有自己的一个权限组,当用户同意获取某个权限时,整个权限组里的权限都获取到了。 比如获取 READ_CALENDAR,用户同意了,则 READ_CALENDAR 对应的权限组的 WRITE_CALENDAR 权限也获取到了。
动态获去危险权限的时候,会用到那么几个方法:
ContextCompat.checkSelfPermission(当前content, 权限名) 检查该权限是否允许,该方法返回 0 或 -1,代表已有该权限 和 没有。 (ps:PackageManager.PERMISSION_GRANTED 为常量,值为 0,通常和上面的方法做判断是否获取权限)
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CALL_PHONE},1): 申请权限。 参数 1 为当前content,参数2 为string数组,放的是要申请的权限,参数3 为 请求码
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 权限结果 , 是当前Activity里的 实现方法,返回申请权限后的结果。 参数 1 是 ActivityCompat.requestPermissions设置的请求码,参数 2为 申请的权限数组, 参数3为 权限的结果数组, ps:参数 2 和 参数 3 是对应的,参数2 为 权限数组,参数3 为 该权限数组的 每个权限的结果,结果为 0 时:用户同意获取,-1时反之
ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.CALL_PHONE) 判断用户对权限的做出了什么选择, 参数 1 为当前content,参数 2为 权限名。 该方法的返回类型为 boolean,返回值的意思有: 先来一张用户可做成对该权限的选择的图:
在第一次申请权限前,返回值为false,也就是说在第一次执行ActivityCompat.requestPermissions 方法前的时候, 还有是Android6.0以下不需要申请的时候,都是返回false
若已经获取了权限,返回false
申请权限时,用户点击 拒绝(并不是永久拒绝不再提示),返回true
永久拒绝后,为false
所以,这个方法的返回值意思就有这么多,有时候我们需要对用户做出的选择做成相应的操作,如拒绝后 怎样提示用户,永久拒绝后该怎样提示用户,允许后做哪些操作, 但因为返回值的意思很多,如何判断是暂时拒绝还是永久拒绝还是允许了。下面提供思路,在用户选择后 判断用户选择了哪个操作,在onRequestPermissionsResult 权限结果的方法里判断:
首先 grantResults 权限结果 为-1时,用户拒绝权限,这个结果不能判断是暂时拒绝还是永久拒绝, 所以,当判断用户拒绝了权限,就可以根据 ActivityCompat.shouldShowRequestPermissionRationale 的值来判断用户是否永久拒绝权限, 因为该 方法返回 true ,用户是暂时拒绝权限,返回false是永久拒绝权限了。
当grantResults 权限结果 为0时 ,那用户就是同意了。
下面来举一个危险权限的 直接拨打号码的权限,也对用户进行各个选择后的判断: Step 1:在配置清单文件AndroidManifest.xml 设置权限:
<uses-permission android:name="android.permission.CALL_PHONE"/>Step 2:activity_main.xml代码:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/bt_tiaozhuan" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="测试"/> </LinearLayout>Step 3 :MainActivity代码:
public class MainActivity extends AppCompatActivity { private final int CALL=1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //==Step 1:获取控件 Button bt = findViewById(R.id.bt_tiaozhuan); bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /** ========Step 2:检查是否获得拨号权限 ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE);这句代 码意思:检查是否获得拨打号码的权限:参数1 为当前content,2为 要验证的权限,当已经获得权限后,返回值为int类型,等于0,反之则为-1。 PackageManager.PERMISSION_GRANTED; 等于 0; */ if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){ //=======没有获得拨打号码的权限,申请获取权限 ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CALL_PHONE}, CALL);//CALL为设置的请求码 }else { //=== 已经获得拨打号码的权限了或者 是Android 6.0 以下,不需要获取权限,直接跳转拨号界面拨打号码 callPhone("10086"); } } }); } //拨打号码 public void callPhone(String number){ Intent intent = new Intent(); intent.setAction(Intent.ACTION_CALL); Uri uri = Uri.parse("tel:"+number); intent.setData(uri); MainActivity.this.startActivity(intent); } //======Step 3:权限的回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode){ case CALL: //==判断是否拒绝权限 if (grantResults[0]==-1){ //为拒绝权限 //==判断是否永久拒绝权限 if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CALL_PHONE)){ //用户已经永久拒绝权限,提醒用户 new AlertDialog.Builder(MainActivity.this) .setTitle("提示") .setMessage("缺少拨号权限,该功能无法使用,若需要,请按【确定】前往应用信息进行权限授权") .setNegativeButton("取消",null) .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //==用户永久拒绝,跳转到应用信息 Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent); } }) .show(); }else { //用户暂时拒绝权限 Toast.makeText(MainActivity.this,"已拒绝权限,无法使用该功能,若需要,请重新操作并允许获取权限",Toast.LENGTH_LONG).show(); } return; } //==权限通过,做想要做的事情 callPhone("10086"); break; } } }