《第一行代码Android》(第二版)读书笔记(二):运行时权限

来源:互联网 发布:淘宝网店流量 编辑:程序博客网 时间:2024/05/08 09:15

背景

在AndroidManifest.xml中添加权限(例如,网络,读写权限等),对用户来说可以保护用户设备的安全性。

一方面,用户在低于6.0系统的设备上安装该程序,会在安装界面给出如图所示的提醒,这样用户就可以清楚地知晓该程序申请了哪些权限,从而决定是否安装该程序。


另一方面用户可以在应用程序管理界面查看任意一个程序的权限申请情况。

 

这种不管用不用到,先把权限申请的做法会存在滥用权限的情况。

 运行时权限功能

Android开发者在6.0系统中加入了运行时权限功能,用户不需要在安装软件时一次性授权所有申请的权限,而是可以在软件使用过程中再对某一项权限进行授权。
然而并不是所有权限都需要这样操作,Android现在将所有权限分为两类:1、普通权限;2、危险权限。其中普通权限系统自动授权,而危险权限需要进行运行时权限处理,必须由用户手动点击授权才可以使用。
危险权限如下(9组 24个权限):

上表中危险权限,除了在AndroidManifest.xml中添加权限,还需要在使用时手动授权;
不在上表中的权限,只需在AndroidManifest.xml中添加权限即可使用。

在程序运行时申请权限(案例1)

拨打电话功能案例

(1)在低于6.0系统上运行

 <uses-permission android:name="android.permission.CALL_PHONE" />
主活动代码,如下:
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 v) {                try {                    Intent intent = new Intent(Intent.ACTION_CALL);                    intent.setData(Uri.parse("tel:10086"));                    startActivity(intent);                } catch (SecurityException e) {                    e.printStackTrace();                }            }        });    }}

(2)在6.0或者以上系统运行

如果以上程序在6.0或者高于6.0系统上运行则会报出“Permission Denial”,这是由于权限被禁止导致的错误,因为6.0及以上系统在使用危险权限时都必须进行运行时权限处理。
怎样在6.0及以上系统进行编码,能够达到权限运行时功能呢?代码如下:
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 v) {    //判断用户是否已经给过我们授权                 if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {                //如果没有授权则调用ActivityCompat.requestPermissions来向用户申请授权 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();        }    }    //用户手动点击授权后,都会回调onRequestPermissionsResult方法中,授权的结果会封装到grantResults中    @Override    public void onRequestPermissionsResult(int requestCode, String[] permissions, 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:        }    }}

总结:

6.0以及以上系统的运行时权限步骤:
A.判断用户是否已经给过我们授权,如果授权直接调用call()方法拨打电话;
B.如果没有授权,则调用ActivityCompat.requestPermissions来向用户申请授权;
C.当用户手动点击授权后,都会回调onRequestPermissionsResult方法中,授权的结果会封装到grantResults
D.判断grantResults中的授权结果,如果同意则调用call()方法来拨打电话,如果用户拒绝的话我们只能放弃操作,并且弹出一条失败提示。

在程序运行时申请权限(案例2)

地图定位功能案例
核心部分,其它部分(略)
 List<String> permissionList = new ArrayList<>();        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);        }        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {            permissionList.add(Manifest.permission.READ_PHONE_STATE);        }        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);        }        if (!permissionList.isEmpty()) {            String [] permissions = permissionList.toArray(new String[permissionList.size()]);            ActivityCompat.requestPermissions(MainActivity.this, permissions, 1);        } else {            requestLocation();        }
private void requestLocation() {        initLocation();        mLocationClient.start();    }
@Override    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {        switch (requestCode) {            case 1:                if (grantResults.length > 0) {   //通过循环将申请的每个权限进行判断,如果有任何一个权限被拒绝,则直接调用finish()方法关闭当前程序                    for (int result : grantResults) {                        if (result != PackageManager.PERMISSION_GRANTED) {                            Toast.makeText(this, "必须同意所有权限才能使用本程序", Toast.LENGTH_SHORT).show();                            finish();                            return;                        }                    }    //当所有权限都被用户同意,才会调用 requestLocation()方法                    requestLocation();                } else {                    Toast.makeText(this, "发生未知错误", Toast.LENGTH_SHORT).show();                    finish();                }                break;            default:        }    }









阅读全文
0 0