设置应用的权限
我使用过的2.3系统的android手机,安装APP的时候会显示一个对话框,里面有这个APP所需要的权限。
如果点击安装,就默认同意了这些权限的请求。
后来系统升级到了5.0时代,这个新的手机新的系统会在安装APP之后显示一个可以操作的对话框,
里面显示APP请求了那些权限,每一个权限你都可以选择确认或者拒绝。如果拒绝了,在操作APP的时候,需要相应权限的时候或说明
“你没有XXX权限”
等类似的东西
以上的说明不一定是普遍情况,可能是不同的厂商对于原始android系统进行更改以后的结果。能操作具体权限当然要更加人性化一些。
这篇笔记是基于学习6.0以上系统开发的时候做的,因此都会更新到最新的6.0以上系统的操作,例如可以在运行的时候选择权限,等等。
声明权限
权限这个很好理解,就是需要使用什么功能,比如摄像头,使用internet,读取短信等等。这些都是系统里面有默认接口
的。
但是,你只需要请求那些你直接使用的权限,如果你的APP是通过一个intent调用其他app,比如调用系统默认照相程序,那么不需要权限。
如果你需要直接调用摄像头,获得摄像头的直接输出,那就需要声明一个权限。
我们可以在Manifast.xml
文件里面声明权限。
添加一个<user-permision>
节点,然后在里面定义。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.snazzyapp">
<uses-permission android:name="android.permission.SEND_SMS"/>
<application ...>
...
</application>
</manifest>
接下来
权限分为normal permissions和dangerous permisions,前者在声明以后,可以自动获取,不需要用户操作。
而后者,都是有关于硬件,用户隐私信息等关键问题的权限,所以需要手动获取。
在6.0之前,是安装的时候确认权限,如果不允许,就只能放弃安装。6.0之后,可以在运行的时候针对某一项权限允许或者拒绝。
注,这是默认系统的运行方式,很多厂商会有一些更改,比如三星的5.1系统就可以在安装的时候对权限进行分开确认
运行时获取权限
Requesting Permissions at Run Time
android Support Library 提供了一些关于权限的方法,这些在Android 6.0 (API level23)也提供。但是Support Library可以提供更广的API LEVEL支持
检查权限
ContextCompat.checkSelfPermission()
方法可以用来检查权限状况,例如
// Assume thisActivity is the current activity
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.WRITE_CALENDAR);
检查是否有这个权限,如果有,就返回PackageManager.PERMISSION_GRANTED
,然后程序可以继续运行。
如果没有,就会返回PERMISSION_DENIED
,那么就必须获得该权限。
获取权限
requestPermissions()
可以用来获取权限,正如文档上所述的使用方法:
// 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.
}
}
注意一点,如果你需要打开一个信息框,向用户解释为什么需要这个权限,你就必须在调用requestPermissions()
之前做,
因为调用这个以后你不能操作你的APP,除非用户选择确认或者拒绝。
确认操作
刚才已经打开了请求权限的对话框,那么如何确认操作以及应对呢
可以在ACTIVITY中覆盖一个方法,onRequestPermissionsResult
。正如文档里的描述
@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
}
}
这里的requestCode
就是之前定义在requestPermissions
方法里面的第三个参数,可以根据自己的设计来自定义。
也就是说,这个方法里面定义了所有关于权限的操作,每个权限对应一个switch的case。
最后,官方文档有关获取权限操作的建议
Permissions Best Practices
备注,关于permission的一些说明
1,当我实际操作的时候发现,在获取权限的时候直接使用requestPermissions
方法,就会在屏幕上打出关于本权限的一些说明,如果选择允许,或者拒绝,就会触发onRequestPermissionsResult
。
也就是说,即便不做任何关于说明的操作,也会给予足够多的说明让用户来了解。
上面将的shouldShowRequestPermissionRationale
实际上是为了给用户更多的信息,比如为什么一个相机应用需要GPS权限,等等。
2,当我需要获取写入系统设定权限的时候,失败了,根本没有执行。
然后我就在官方API文档找到这么一段
WRITE_SETTINGS
Note: If the app targets API level 23 or higher, the app user must explicitly grant this permission >to the app through a permission management screen. The app requests the user’s approval by >sending an intent with action ACTION_MANAGE_WRITE_SETTINGS. The app can check whether it >has this authorization by calling Settings.System.canWrite().
就是说,如果API大于23,那么需要获取WRITE_SETTINGS
权限的时候需要这么操作:发送一个intent
ACTION是 Settings.ACTION_MANAGE_WRITE_SETTINGS
,也就是打开系统的一个菜单,选择是否允许你的APP来控制设定。
检查权限也不一样,需要用方法Settings.System.canWrite()
不知道设计人是怎么想的。