之前,我们队需要的请求,都不过是在manifest里声明。后来有了运行时权限请求,本来就对权限不太熟,很多都是自顾自的加上去,让程序能跑就好,但有时候,看见国外的程序,那些个简洁的权限列表,就又觉得自己太随意了。之前也有过权限的请求经历,但是都是search->copy->debug,为什么都没有搞得很清楚,反正最终目的不就是run起来么。不过,现在我希望,稍微清楚一些,而不是稀里糊涂的了。
划时代:
在Android 5.1.1(API22)及以前,都是install_time permission request,但是,在Android 6.0(API23)以以后版本,都会是runtime permission request,意味着需要某个危险权限时需要在代码里去检查是否已经granted了。
区别permission和hardware features:
首先,他们都是定义在manifest里,和<application>同级
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.snazzyapp">
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="false" />
<application ...>
...
</application>
</manifest>
根据官方文档,是如果没有uses-feature,则默认认为应用必须需要有这个功能,如果没有,则Google Play不会安装该应用到手机上。否则,像代码里在uses-feature的android:required="false"则可以认为这个功能不必须,则可以安装。当然,对应的在代码里就要检查了。
权限分类:
权限官方分为3+1类:普通,签名,危险 和 特殊权限。普通->系统可以自动授权,危险->需要询问用户。签名->系统应用(具有系统签名)才可以获取得到。不过官方也说了,这不会影响APP的安装,但是实际上你就是获取不到。特殊权限主要是SYSTEM_ALTER_WINDOW和WRITE_SETTINGS,需要去请求。
还有就是,自API-23 后,有了权限组的概念,但是个人认为,既然官方说了分组可能会变,不要依赖这种机制,所以,我觉得他的存在只是让我们能够理解这种行为而已,于开发者而言似乎没有什么用。
国内情况:
由于我国的rom大多是深度定制,很多都有自己的权限管理机制。所以,个人觉得不要太相信申请权限后返回的结果,还是要自己去检查是否有这个权限。
请求权限:
当要适配API level 23 及以上时,需要在代码中处理权限的动态申请。根据官方文档,如果有适配低版本的要求,使用support库就很方便了。
流程:
- 检查权限
- 是否需要解释,是->解释
- 申请权限
- 结果回调处理
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
结果处理:
@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.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
上面两段都是直接copy官网上的例子,足够清晰明了的了。
官网链接
题外话:
相信很多时候我们处理业务都没有在activity里,但是这个权限请求又非得在activity里,而且结果的回调得让activity来重写处理。这让很多人在拥有架构的时候有点烦。对于在fragment里,activity可以直接getActivity(),但是结果还是没办法获取得到。其实这种情况很多时候都有遇到。我基本上是通过interface,listener这样的方式来将业务代码传进activity里,也没想到什么好的解决办法,看网上的例子,不如自己写写。
小结:
在Android6.0(API level 23)及以后,使用危险权限要动态申请。在之前版本,权限在安装时则已经全部granted了。
其实,在国内的rom,早就有权限控制了,不过是在系统级别的控制,至于它是如何与应用交互的,个人觉得是欺骗,事实就是用不了,又不告诉你用不了,哈哈哈哈。