- 一.权限概述
- 1.Android 权限的含义及安全架构
- 2.权限许可
- 二.权限的分类
- 1.可选硬件功能的权限
- 2.服务许可执行
- 1)activity权限执行
- 2)service权限执行
- 3)广播权限执行
- 4)Content Provider权限执行
- 5)URI权限执行
- 6)其他权限检查
- 三.权限保护水平
- 1.正常权限
- 2.签名权限
- 3.用户ID和文件访问权限
- 4.危险的权限
- 5.特殊权限
- 四.权限分组
- 1.正常权限
- 2.危险权限
- 五.自动权限调整
- 六.自定义权限
- 七.Android 6.0动态申请权限
- 1.检查权限
- 2.请求权限授权
- 3.处理低配设备
- 八.API版本与targetSDKVersion关系
- 1.Normal Permission
- 2.Dangerous Permission
- 3.兼容性处理
- 九.相关问题和资料
1)Android 是一个权限分隔的操作系统,其中每个应用都有其独特的系统标识。
系统各部分也分隔为不同的标识,Linux 据此将不同的应用以及应用与系统分隔开来。
2)在默认情况下任何应用都没有权限执行对其他应用、操作系统或用户有不利影响的任何操作。这包括读取或写入用户的私有数据(例如联系人或电子邮件)、
读取或写入其他应用的文件、执行网络访问、使设备保持唤醒状态等。
由于每个 Android 应用都是在进程沙盒中运行,因此应用必须显式共享资源和数据,即声明需要哪些权限来获取基本沙盒未提供的额外功能
2.权限许可1)Android应用可能需要请求访问敏感用户数据(如联系人和短信)以及某些系统功能(如相机和互联网)的权限。
根据功能,系统可能会自动授予权限,或者可能会提示用户批准请求。
2)应用必须通过 在manifest中明确标记所需的权限。例如需要发送SMS消息的应用在manifest中应包含以下行:
...
如果在manifest中列出了正常权限(即不会对用户的隐私或设备操作造成太大风险的权限),系统会自动将这些权限授予您的应用。
如果在manifest中列出了危险权限(即可能影响用户隐私或设备正常运行的权限),例如SEND_SMS权限,则用户必须明确同意授予这些权限。
二.权限的分类 1.可选硬件功能的权限访问某些硬件功能(如蓝牙或相机)需要应用权限。但是并非所有设备都具有这些硬件功能。因此如果应用请求 CAMERA
权限,
那么还需要在manifest中使用 声明是否确实需要此功能。例如:
1)如果您声明android:required="false"
该功能,则Google Play允许你的应用安装在没有此功能的设备上。
然后你必须检查当前设备在运行时是否具有该功能 PackageManager.hasSystemFeature()
,并在该功能不可用时正常禁用该功能。
2)如果未提供 声明
,那么当Google Play看到应用请求相应的权限时,它会认为应用需要此功能。因此它会从没有
该功能的设备中过滤该应用,就像android:required="true"
在 标记中声明一样 。
有关详细信息,请参阅 Google Play和基于功能的过滤
2.服务许可执行权限不仅适用于请求系统功能。应用提供的服务可以强制执行自定义权限,以限制谁可以使用它们。
有关声明自定义权限的详细信息,请参阅定义自定义应用权限。
1)activity权限执行
在manifest中的activity标签使用android:permission
属性来限制谁可以启动它。在执行Context.startActivity()
和 Activity.startActivityForResult()的时候如果没有需要的权限会抛出
SecurityException异常;
2)service权限执行
在manifest中的service标签使用android:permission
属性来限制谁可以启动或绑定它。在执行Context.startService()、
Context.stopService()
和
Context.bindService()
时检查权限,如果没有需要的权限会抛出
SecurityException异常;
3)广播权限执行
sendBroadcast(new Intent("com.example.NOTIFY"),Manifest.permission.SEND_SMS);
要接收这个广播, 接收方必须在manifest中注册权限
在receiver标签中使用android:permission
属性来限制谁可以发送广播到关联的BroadcastReceiver。系统尝试将提交的广播
传递给给定的接收者,因此权限检查失败不会抛异常给调用者; 它只是不响应这个intent。(这是个例外)
或者在代码中注册接收器Context.registerReceiver()也可以使用权限来限制
谁可以向reveiver发送广播。
IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null );
注意: receiver and a broadcaster 都可以设置需要某权限才可以访问。这时就必须双方权限检查都通过才能将intent传到关联方。
有关更多信息,请参阅 限制具有权限的广播。
4)Content Provider权限执行
在 标签中
使用android:permission
属性来限制谁可以访问 ContentProvider中的
数据 。
(ContentProvider有一个重要的额外安全设施叫做 URI权限,下面将对此进行描述)
ContentProvider
与其他组件不同,可以设置两个单独的权限属性:android:readPermission 限制谁可以从provider读取数据,
android:writePermission 限制谁可以写入数据。
注意:如果provider同时受读取和写入权限保护,则仅有写入权限并不可以从provider读取数据。
检索provider并且在provider上执行操作时将检查权限(如果没有权限则抛出SecurityException
异常)。使用 ContentResolver.query()
需要有读取权限;
使用 ContentResolver.insert()
,ContentResolver.update()
, ContentResolver.delete()
需要写权限。
在所有这些情况下,未获得所需权限会导致SecurityException异常
抛出。
5)URI权限执行
标准的权限系统对于provider来说是不够的。一个provider可能想保护它的读写权限,但与其直接关联的客户端也需要将特定的URI传递给其它应用,
以便其它应用能对该URI进行操作。
例如邮件应用的附件,因为邮件中是敏感的用户数据,所以需要用permission来保护。但是如果有一个指向图片附件的URI需要传递给图片浏览器,
而这个图片浏览器是不会有访问附件的权利的,因为它不可能有邮件的所有权限的。这个问题的解决方案就是per-URI permission:
当启动一个activity或者给一个activity返回结果的时候,调用方可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION和 Intent.FLAG_GRANT_WRITE_URI_PERMISSION。
这就赋予了接收activity访问该Intent指定的URI的权限,而不用关系它是否有权限进入该intent 对应的 provider。
这种机制是实现减少应用所需要的权限而只留下和应用行为直接相关的权限的关键一步,这种用户交互(如打开一个附件、从列表中选择一个联系人)就可以采用这种细微权限的授与。
但是这些URI权限的获取需要持有这些URL的provider来配合,所以建议在provider中实现这种功能,并通过 android:grantUriPermissions
或者标签来声明支持。
Uri uri = FileProvider .getUriForFile(mContext, BuildConfig.APP_LICATION_ID + ".provider", file);
mContext .grantUriPermission(BuildConfig.APP_LICATION_ID , uri , Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
更多的信息可以参考 Context.grantUriPermission()
, Context.revokeUriPermission()
函数。
6)其他权限检查
对其它应用进程的调用都可以强制执行任意细粒度的权限。在执行对其他进程的调用时通过Context.checkCallingPermission()
方法来检查是否已将该权限授予当前调用进程。
如果您具有另一个进程的进程ID(PID),则可以使用该Context.checkPermission()
方法检查针对该PID的权限。
如果您拥有其他应用的包名,则可使用PackageManager.checkPermission()
方法检查该特定程序包是否已被授予特定权限。
权限分为几个保护级别。保护级别会影响是否需要运行时权限请求。
有三种保护级别会影响第三方应用: 正常,签名和危险权限。
1.正常权限普通权限是涵盖应用需要访问应用沙盒外部数据或资源的区域,但用户隐私或其他应用操作的风险很小的权限。例如,设置时区的权限是正常权限。
如果应用在其清单中声明它需要正常权限,则系统会在安装时自动授予应用该权限。系统不会提示用户授予正常权限,用户也无法撤消这些权限。
2.签名权限 所有 发布到应用市场的APK(.apk
文件)都必须使用证书签署,证书用于识别应用的作者;这就允许系统决定应用是否可以有签名级权限的访问权及
是否能获得与另一应用相同的 Linux 身份。
3.用户ID和文件访问权限在安装时系统为每个程序包提供不同的Linux用户ID。在程序包的生命周期内,该标识保持不变。在不同的设备上,同一个包可能有不同的UID;
重要的是每个包在给定设备上具有不同的UID。
正常情况下任何两个软件包需要作为不同的Linux用户运行,所以其代码不能在同一进程中运行。但是可以通过在
每个包的manifest中的 sharedUserId属性为它们分配相同的用户ID,通过这样做,两个包就被视为具有相同用户ID和文件权限的应用了。
注意:为了保持安全性,只有两个应用同时满足使用相同签名和相同的sharedUserId时被赋予相同的用户ID。
应用存储的任何数据都将分配该应用的用户ID,而其他软件包通常无法访问。
有关Android安全模型的更多信息,请参阅Android安全概述
4.危险的权限危险权限包括应用需要涉及用户私人信息的数据或资源的区域,或可能会影响用户存储的数据或其他应用的操作。
例如,读取用户联系人的权限是一种危险的权限。如果应用声明它需要危险权限,则用户必须明确授予该应用的权限。
在用户批准该权限之前,您的应用无法提供依赖该权限的功能。
危险权限授予的方式在Android 6.0系统版本前后发生了巨大的变化,后面详细介绍。
5.特殊权限有一些权限不像正常和危险的权限,在Android 6.0中增加了特殊的权限授予处理方式。像SYSTEM_ALERT_WINDOW和
WRITE_SETTINGS这些权限
特别敏感,
所以一般应用不应该使用它们。如果应用需要其中某个权限,则必须在manifest中声明权限,并且发送请求用户授权的intent。系统通过向用户显示详细的管理屏幕来响应intent。
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS );
在onActivityResult中通过Settings.System.canWrite()方法判断WRITE_SETTINGS权限是否授权,有关如何请求这些权限的详细信息,请参阅参考SYSTEM_ALERT_WINDOW
和 WRITE_SETTINGS
参考条目。
在Android中会把权限分类在不同的权限组中,权限请求是在组级别处理。例如SMS组包括声明READ_SMS、
SEND_SMS和 RECEIVE_SMS
声明,
这样的方式方便用户对权限的理解和作出选择。
无论权限的保护级别如何,所有的权限都属于权限组。但是只有危险权限会影响用户体验。
1.正常权限正常权限在应用需要使用的时候只要在manifest中声明系统就会自动授予应用相应权限,而不需要与用户交互和得到用户的许可。
2.危险权限1)从Android 6.0开始系统加入了动态权限管理机制。如果设备系统是>=6.0且应用的targetSdkVersion>=
23时,则当应用请求危险权限时,以下系统行为适用:
- 如果应用当前在权限组中没有任何权限,系统会向用户显示描述应用要访问的权限组的权限请求对话框。该对话框不会描述该组中的特定权限。 例如如果某个应用请求了该
READ_CONTACTS
权限,系统对话框只会告诉用户该应用需要访问设备的联系人。如果用户授予批准,系统将为应用提供其请求的权限。 - 如果应用已在同一权限组中被授予另一个危险权限,则系统会立即授予权限,而不与用户进行任何交互。例如,如果某个应用先前已请求并已获得该
READ_CONTACTS
权限, 然后它会请求WRITE_CONTACTS
,则系统会立即授予该权限,而不会向用户显示权限对话框。
警告:未来版本的Android SDK可能会将特定权限从一个组移动到另一个组。因此不要将权限组的结构作为应用判断权限逻辑的依据。
即使用户已在同一组中授予了其他权限,虽然组内其它权限申请的时候会自动授权,但是应用仍要明确请求其所需的每个权限。
2)如果设备运行的系统是= 6.0
API = 23
安装时不会获得权限,可以在运行时向用户申请权限。
用户授权以后仍然可以在设置界面中取消授权,用户主动在设置界面取消后,在应用运行过程中可能会出现crash
安装时默认获得权限,且用户无法在安装应用之后取消权限targetSDKVersion =6.0D但targetSDKVersion最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?