在Android6.0系统中引入了运行时权限这个功能,从而更好的保护了用户的安全和隐私
这里为了简单就使用CALL_PHONE这个权限作为示例
在程序运行时申请权限
CALL_PHONE这个权限是编写拨打电话的,在android6.0之前,拨打电话功能的实现非常简单
- activity_main.xml文件中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/make_call"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Make Call"/>
</LinearLayout>
- 当点击这个按钮的时候触发拨打电话的逻辑
- 在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 = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
startActivity(intent);
}catch (SecurityException e){
e.printStackTrace();
}
}
});
}
}
- 点击按钮的时候,构建了一个隐式的Intent,指定为Intent.ACTION_CALL,这是一个系统内置的打电话的动作,然后在data部分指定协议是tel,号码是10086,这个是直接拨打电话,因此需要声明权限,为了防止程序的崩溃,放到try里,
- 在AndroidManifest.xml文件中,声明权限
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.md.d1">
<uses-permission android:name="android.permission.CALL_PHONE" />
<application>
...
</application>
</manifest>
- 这样拨打电话的功能就实现了,在低于Android6.0系统中都是可以的,但是在android6.0以上的话就会出现错误提示
- 接下来就来修复这个问题,在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) {
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:10086"));
startActivity(intent);
}catch (SecurityException e){
e.printStackTrace();
}
}
@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_SHORT).show();
}
break;
default:
}
}
}
- 上面的代码把运行时权限的完整流程都覆盖了,就是运行时权限的核心就是在程序运行过程中由用户授权我们去执行某些危险操作,程序是不可以擅自做主去执行这些危险操作的
- 首先要判断用户是不是已经给我们授权了,借助的是
ContextCompat.checkSelfPermission()
方法,接收两个参数,第一个是Content,第二个参数是具体的权限名,比如打电话的权限名就是Manifest.permission.CALL_PHONE,然后使用方法的返回值和PackageManager.PERMISSION_GRANTED进行比较,相等说明用户授权了,不等就是没有授权 - 授权的话就直接执行call()方法
- 没有授权的话就要调用
ActivityCompat.requestPermissions()
方法来向用户申请授权,这个方法接收三个参数,第一个是Activity的实例,第二个参数是一个String数组,把申请的权限名放在数组就可以了,第三个是请求码,只要是唯一值就可以了, - 调用requestPermissions()方法之后,系统就会弹出一个权限申请的对话框,然后让用户选择同意或者是拒绝,不管用户点击那个,最终都会调用
onRequestPermissionsResult()
方法,而授权的结果则会封装在grantResults参数中,判断最后的授权,如果用户同意的话就用call(),拒绝的话弹出一条失败的提示
-
运行程序,点击按钮,第一次运行的话会弹出一个权限申请的会话框
权限.png
这里点击拒绝的话就会弹出一个提示
拒绝.png
点击同意的话就直接拨打电话了
打电话.png
下次点击这个按钮的时候就不会弹出权限申请对话框了,这个时候后悔了,想把这个权限关闭,我们在设置\应用\权限把电话这个权限关闭就可以了
关闭权限.png
网友评论