自android 6.0后权限需要动态的去检测,如果6.0不对权限做处理,那么会出现一些意想不到的问题,例如拿不到联系人,拿不到sd卡信息。
Android6.0之后的权限差别
对于6.0以下的权限及在安装的时候,根据权限声明产生一个权限列表,用户只有在同意之后才能完成app的安装。而在6.0以后,我们可以直接安装,当app需要权限是会给予用户提示用户可以选择同意和拒绝。
新的权限机制更好的保护了用户的隐私,Google将权限分为两类,一类是Normal Permissions,这类权限一般不涉及用户隐私,是不需要用户进行授权的,比如访问网络等;另一类是Dangerous Permission,一般是涉及到用户隐私的,需要用户进行授权,比如读取sdcard、打电话等等。
- Normal Permissions举例:
INTERNET
GET_PACKAGE_SIZE
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
CHANGE_WIFI_STATE
VIBRATE
- Dangerous Permissions举例:
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
group:android.permission-group.CAMERA
permission:android.permission.CAMERAgroup:android.permission-group.STORAGE
permission:android.permission.READ_EXTERNAL_STORAGE
permission:android.permission.WRITE_EXTERNAL_STORAGE
你会发现dangerous permissions,危险权限都是一组一组的,这是个什么概念呢?又或是有什么用呢?如果app运行在Android
6.x的机器上,对于授权机制是这样的。如果你申请某个危险的权限,假设你的app早已被用户授权了同一组的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。比如你的app对READ_CONTACTS已经授权了,当你的app申请WRITE_CONTACTS时,系统会直接授权通过。此外,对于申请时弹出的dialog上面的文本说明也是对整个权限组的说明,而不是单个权限(ps:这个dialog貌似现在可以
代码处理
- 先判断有没有这个权限
- 如果有就直接拨打
- 如果没有就需要去申请权限
public void call(View v) {
//首先判断有没有这个权限
int permissionId = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
//返回值只有2个, 授予是PERMISSION_GRANTED,拒绝是PERMISSION_DENIES
if (permissionId == PackageManager.PERMISSION_GRANTED) {
//有这个权限。这里通常是 已经给过权限后,第二次之后点击
callPhone();
} else {
//没有这个权限就去申请
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL_PHONE);
}
}
- 获取用户的反馈,是否授予了
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CALL_PHONE) {
if (grantResults != null && grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
callPhone();
} else {
Toast.makeText(this, "用户拒绝了", Toast.LENGTH_SHORT).show();
}
}
} else {
}
}
完整的简单示例代码
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CALL_PHONE = 0x001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void call(View v) {
int permissionId = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
if (permissionId == PackageManager.PERMISSION_GRANTED) {
callPhone();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CALL_PHONE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CALL_PHONE) {
if (grantResults != null && grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
callPhone();
} else {
Toast.makeText(this, "用户拒绝了", Toast.LENGTH_SHORT).show();
}
}
} else {
}
}
private void callPhone() {
Intent intent = new Intent(Intent.ACTION_CALL);
Uri data = Uri.parse("tel:" + "15003867556");
intent.setData(data);
startActivity(intent);
}
}