Android permission 动态申请、授权

Android permission 新特性深度学习

本篇文章介绍android permission系统,并介绍android 6.0 permission的新特性,包括权限动态申请和授权等。

permission system

Android开发者都知道,我们开发的应用默认是没有任何权限的,我们没有办法联网,没有办法进行外部空间存储(内部空间是可以的),除非我们申请了相应的权限(permission)。

比如,我们在Manifest文件中,加入以下语句,我们就可以在我们的应用中连接到网络。

<uses-permission android:name="android.permission.INTERNET" />

那么,android为什么要这么设计呢?笔者认为,这样的设计的最大好处是,由于手机上存储了用户的大量隐秘信息,对于Android的用户来说,每次安装App时,都会提示用户该App拥有什么权限,这样用户对该App就有了大概的认识,该App可能会进行什么操作,会不会窃取我的隐私等(当然,普通的Android用户是没有这个意识的)。

Android将所有的权限分为了两种,一种是Normal,另一种是Dangerous. 关于两者,Developer是这么介绍的,

Normal permissions cover areas where your app needs to access data or resources outside the app’s sandbox, but where there’s very little risk to the user’s privacy or the operation of other apps. For example, permission to set the time zone is a normal permission. If an app declares that it needs a normal permission, the system automatically grants the permission to the app.

总的来说,normal类型的权限会泄露用户的风险会很少,所以Android会默认赋予这些权限。

Dangerous permissions cover areas where the app wants data or resources that involve the user’s private information, or could potentially affect the user’s stored data or the operation of other apps. For example, the ability to read the user’s contacts is a dangerous permission. If an app declares that it needs a dangerous permission, the user has to explicitly grant the permission to the app.

而Dangerous权限是怎样的呢?该类型的权限泄露用户隐私的风险会很大,例如,读取用户的通讯录。
关于Dangerous类的权限,Developer给出的有,
这里写图片描述

权限的赋予

上边介绍了危险权限是要用户的允许才能使用的,

before 6.0

在Android 6.0之前,这些权限的赋予是在用户安装App的时候,用户可以选择赋予该权限,然后安装App,但是如果用户不赋予的话,那么该App就无法安装,这就是所谓的All or Nothing。当然,这是原生系统的特性,据我所知,小米、魅族定制的系统已经可以动态赋予权限。

after 6.0

Android 6.0对该特性进行了修改,毕竟All or Nothing的机制存在较大的弊端,很多用户为了使用该App,就同意了所有权限,并且无法对其进行控制,这样就显得权限的作用并没有显现出来。所以Android 6.0 允许了动态赋予权限。

Developer对其的说明如下,

If the device is running Android 6.0 (API level 23) or higher, and the app’s targetSdkVersion is 23 or higher, the app requests permissions from the user at run-time. The user can revoke the permissions at any time, so the app needs to check whether it has the permissions every time it runs

如果你的设备的Android版本在6.0之上,并且App的目标sdk版本在23之上,那么用户就可以对其权限进行动态赋予。而其他情况下,用户无法动态赋予权限,还是All or Nothing。要不全部赋予,要不就不安装。

那么如何使用该新特性呢?

Check For Permissions

Develper的解释如下,

If your app needs a dangerous permission, you must check whether you have that permission every time you perform an operation that requires that permission. The user is always free to revoke the permission, so even if the app used the camera yesterday, it can’t assume it still has that permission today.

如果我们的应用包括危险权限,那么我们在每次执行对应的操作的时候,就应该检查是否被授予该权限。因为用户可以随时取消App的某个权限,所以我们应该每次都要检查用户是否赋予了该权限。否则,就会崩溃。

该函数的用法如下,

// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,Manifest.permission.WRITE_CALENDAR);

如果用户赋予了该权限,那么该方法会返回PackageManager.PERMISSION_GRANTED,然后我们就可以继续我们的操作;否则会返回PERMISSION_DENIED。如果返回PERMISSION_DENIED,我们就无法直接进行我们的操作,因为我们没有权限。那么应该怎么办呢?此时,我们应该显式的申请权限。

那么怎么显示的申请权限呢?这就用到下面的函数,

requestPermissions

当我们发现,我们的应用没有被授予某个权限的时候,我们就可以显示的申请。
一个例子如下,

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, MY_PERMISSIONS_REQUEST_READ_CONTACTS);

其中MY_PERMISSIONS_REQUEST_READ_CONTACTS是设置的requestCode,用来区分是申请哪个权限,该函数会弹出一个对话框,询问用户是否授权该权限,
这里写图片描述

用户可以选择授权或取消,那么我们如何知道用户的选择呢,这就要求我们重载Acitivity的一个接口,

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    // permission was granted, yay! Do the
                    // contacts-related task you need to do.
                    System.out.println("User granted permission");

                } else {
                    System.out.println("User didn't grante permission");

                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                }
                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request
        }
    }

我们根据requestCode来区分申请的权限。当用户选择后,就会回调该接口,我们就可以知道用户的选择,进而执行下一步操作。

文中的例子,可以通过以下方式获得,
https://github.com/KingPaul/DynamicPermissionDemo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章