Android运行时权限详解
Android的权限机制并不是什么新鲜事物,从系统的第一个版本开始就已经存在了。但其实之前Android的权限机制在保护用户安全和隐私等方面起到的作用比较有限,尤其是一些大家都离不开的常用软件,非常容易“店大欺客”。为此,Android开发团队在Android 6.0系统中引用了运行时权限这个功能,从而更好地保护了用户的安全和隐私,那么本节我们就来详细学习一下这个6.0系统中引入的新特性。
Android权限机制详解
首先来回顾一下过去Android的权限机制是什么样的。我们在第5章写BroadcastTest项目的时候第一次接触了Android权限相关的内容,当时为了要访问系统的网络状态以及监听开机广播,于是在AndroidManifest.xml文件中添加了这样两句权限声明:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
</manifest>
因为访问系统的网络状态以及监听开机广播涉及了用户设备的安全性,因此必须在AndroidManifest.xml中加入权限声明,否则我们的程序就会崩溃。
那么现在问题来了,加入了这两句权限声明后,对于用户来说到底有什么影响呢?为什么这样就可以保护用户设备的安全性了呢?
其实用户主要在以下两个方面得到了保护,一方面,如果用户在低于6.0系统的设备上安装该程序,会在安装界面给出提醒。这样用户就可以清楚地知晓该程序一共申请了哪些权限,从而决定是否要安装这个程序。如图所示:
另一方面,用户可以随时在应用程序管理界面查看任意一个程序的权限申请情况。这样该程序申请的所有权限就尽收眼底,什么都瞒不过用户的眼睛,以此保证应用程序不会出现各种滥用权限的情况。如图所示:
这种权限机制的设计思路其实非常简单,就是用户如果认可你所申请的权限,那么就会安装你的程序,如果不认可你所申请的权限,那么拒绝安装就可以了。
但是理想是美好的,现实却很残酷,因为很多我们所离不开的常用软件普遍存在着滥用权限的情况,不管到底用不用得到,反正先把权限申请了再说。比如说微信所申请的权限列表如图所示:
这只是微信所申请的一半左右的权限,因为权限太多一屏截不下来。其中有一些权限我并不认可,比如微信为什么要读取我手机的短信和彩信?但是我不认可又能怎样,难道我拒绝安装微信?没错,这种例子比比皆是,当一些软件已经让我们产生依赖的时候就会容易 “店大欺客”,
反正这个权限我就是要了,你自己看着办吧!
Android开发团队当然也意识到了这个问题,于是在6.0系统中加入了运行时权限功能。也就是说,用户不需要在安装软件的时候一次性授权所有申请的权限,而是可以在软件的使用过程中再对某一项权限申请进行授权。比如说一款相机应用在运行时申请了地理位置定位权限,就算我拒绝了这个权限,但是我应该仍然可以使用这个应用的其他功能,而不是像之前那样直接无法安装它。
当然,并不是所有权限都需要在运行时申请,对于用户来说,不停地授权也很烦琐。Android现在将所有的权限归成了两类,一类是普通权限,一类是危险权限。准确地讲,其实还有第三类特殊权限,不过这种权限使用得很少,因此不在本书的讨论范围之内。普通权限指的是那些不会直接威胁到用户的安全和隐私的权限,对于这部分权限申请,系统会自动帮我们进行授权,而不需要用户再去手动操作了,比如在BroadcastTest项目中申请的两个权限就是普通权限。危险权限则表示那些可能会触及用户隐私或者对设备安全性造成影响的权限,如获取设备联系人信息、定位设备的地理位置等,对于这部分权限申请,必须要由用户手动点击授权才可以,否则程序就无法使用相应的功能。但是Android中有一共有上百种权限,我们怎么从中区分哪些是普通权限,哪些是危险权限呢?
其实并没有那么难,因为危险权限总共就那么几个,除了危险权限之外,剩余的就都是普通权限了。下表列出了Android中所有的危险权限,一共是9组24个权限。
这张表格你看起来可能并不会那么轻松,因为里面的权限全都是你没使用过的。不过没有关系,你并不需要了解表格中每个权限的作用,只要把它当成一个参照表来查看就行了。每当要使用一个权限时,可以先到这张表中来查一下,如果是属于这张表中的权限,那么就需要进行运行时权限处理,如果不在这张表中,那么只需要在AndroidManifest.xml文件中添加一下权限声明就可以了。
另外注意一下,表格中每个危险权限都属于一个权限组,我们在进行运行时权限处理时使用的是权限名,但是用户一旦同意授权了,那么该权限所对应的权限组中所有的其他权限也会同时被授权。
在程序运行时申请权限
首先新建一个RuntimePermissionTest项目,我们就在这个项目的基础上来学习运行时权限的使用方法。在开始动手之前还需要考虑一下到底要申请什么权限,其实刚才表中列出的所有权限都是可以申请的,这里简单起见我们就使用CALL_PHONE这个权限来作为本小节中的示例吧。
CALL_PHONE这个权限是编写拨打电话功能的时候需要声明的,因为拨打电话会涉及用户手机的资费问题,因而被列为了危险权限。在Android 6.0系统出现之前,拨打电话功能的实现其实非常简单,修改activity_main.xml布局文件,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android