一、Android 6.0以前的权限机制
为了保护用户的安全与隐私,Android从第一个版本开始就提出了权限机制。
当编程时,会存在一些功能需要访问用户的信息与隐私等问题。如因为访问系统的网络状态以及监听开机广播等涉及到用户设备的安全性。此时必须在AndroidManifest.xml文件中加入权限声明:
这样做有两方面的优点:
1、在用户低于Android 6.0系统的设备上安装程序时,Android安装界面会提示该程序一共申请了哪些权限,从而可以决定是否安装该程序。
2、用户可以随时在应用程序管理界面查看一个程序的权限申请情况,防治应用程序出现各种权限滥用。
此时,仍然存在一些问题,一些用户常用的软件仍然存在滥用现象,这些软件在安装时不管程序是否用得到,反正先把权限申请了再说,这时用户如果不同意某个权限的使用时,就无法再使用该程序。
二、Android 6.0以后的运行时权限机制
Android的开发团队意识到这个问题时,在Android 6.0以后加入了运行时权限机制。此时,用户不需要在安装软件时一次性授权所有申请的权限,而是在软件使用过程中在对某一项权限申请时进行授权。
Android现在将权限分为两类:
普通权限:指那些不会直接威胁到用户安全和隐私的权限,对于这部分权限申请,系统会自动帮我们授权,不用用户在去手动操作,与Android 6.0之前保持一致,只需在AndroidManifest.xml文件中加入权限声明即可。
危险权限:指那些可能会触及用户隐私或者对设备安全性造成影响的权限,对于这部分权限,必须由用户手动点击授权,否则程序将无法使用相应功能。
一、Android 6.0以前
1、修改activity_main中的代码定义一个Button,点击按钮出发打电话代码逻辑。
2、修改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.make_call);
makecall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
//隐式Intent,Intent.ACTION_CALL内置打电话的动作
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}catch (SecurityException e){
e.printStackTrace();
}
}
});
}
}
3、在AndroidManifest.xml文件中加入权限声明。
此时的功能在Android 6.0 以前的设备上可以实现,但在Android 6.0以后的设备中点击Make Call按钮就没有任何效果。
一、Android 6.0以后
1、修改activity_main中的代码定义一个Button,点击按钮出发打电话代码逻辑。
2、在AndroidManifest.xml文件中加入权限声明。
3、修改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.make_call);
makecall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// checkSelfPermission()方法返回值与PackageManager.PERMISSION_GRANTED对比判断是否已授权。
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:10000"));
startActivity(intent);
}catch (SecurityException e){
e.printStackTrace();
}
}
//调用完requestPermissions()方法后,会回调该方法。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
switch (requestCode){
case 1:
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
call();
}else {
Toast.makeText(this, "You denied the permission",
Toast.LENGTH_LONG).show();
}
break;
default:
}
}
}
运行时权限的核心是在程序运行过程中有用户去授权我们去执行某些危险操作,程序是不会擅自做主执行危险操作的。
checkSelfPermission()方法:判断是否已经授权。
第一个参数:Context。
第二个参数:具体权限名。
ActivityCompat.requestPermissions()方法:向用户申请授权。
第一个参数:Activity实例。
第二个参数:储存权限名的String数组。
第三个参数:请求码。
调用完requestPermissions()方法后系统会弹出一个权限申请对话框,然后用户可以选择同意或者拒绝申请的权限,无论同意或拒绝都会回调onRequestPermissionsResult()方法,此时授权结果会封装在int[] grantResults中。