序言
在Android5.1及一下系统中,系统会自动为程序赋予权限,只要你在清单文件中标明;
而6.0及以上系统中,若你的程序targetSdkVersion为23或以上,有些 运行时权限 还需要在运行时进行授权。
哪些权限需要申请?
权限组 | 权限 |
---|---|
CALENDAR | READ_CALENDAR |
WRITE_CALENDAR | |
CAMERA | CAMERA |
CONTACTS | READ_CONTACTS |
WRITE_CONTACTS | |
GET_ACCOUNTS | |
LOCATION | ACCESS_FINE_LOCATION |
ACCESS_COARSE_LOCATION | |
MICROPHONE | RECORD_AUDIO |
PHONE | READ_PHONE_STATE |
CALL_PHONE | |
READ_CALL_LOG | |
WRITE_CALL_LOG | |
ADD_VOICEMAIL | |
USE_SIP | |
PROCESS_OUTGOING_CALLS | |
SENSORS | BODY_SENSORS |
SMS | SEND_SMS |
RECEIVE_SMS | |
READ_SMS | |
RECEIVE_WAP_PUSH | |
RECEIVE_MMS | |
STORAGE | READ_EXTERNAL_STORAGE |
WRITE_EXTERNAL_STORAGE |
(详见官方说明,标注 Protection level: dangerous 需要运行时申请)
一般来说,一个组只要有一个权限被赋予,其它权限也就拥有了。所以,同组权限不需要重复申请。
申请代码
这里以 PROCESS_OUTGOING_CALLS 权限为例。
向用户申请权限
代码
private void requestPermission() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(ContextCompat.checkSelfPermission(this,android.Manifest.permission.PROCESS_OUTGOING_CALLS)!=PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.PROCESS_OUTGOING_CALLS}, 1);
}
}
}
分析
首先要判断系统版本,M一下就不用申请了。。。
判断权限是否已拥有,使用的是 ContextCompat.checkSelfPermission(Context context, String permission)
权限名为 android.Manifest.permission.PROCESS_OUTGOING_CALLS
(static int) checkSelfPermission (Context context, String permission)
Determine whether you have been granted a particular permission.
(返回是否拥有该权限)Parameters :
context Context(上下文)
permission String: The name of the permission being checked.(要检查的权限)
Returns :
int PERMISSION_GRANTED if you have the permission(拥有该权限), or PERMISSION_DENIED if not(没有改权限).
有多个权限需要申请,可以直接使用&&连接判断。
申请用 ActivityCompat.requestPermissions(Activity activity, String[] permissions, int requestCode)
申请:
(static void) requestPermissions(Activity activity, String[] permissions, int requestCode)
Requests permissions to be granted to this application. (为本程序申请权限)Parameters:
activity Activity : The target activity.(申请的Activity,可否理解成上下文?)
permissions String[] : The requested permissions.(需要申请的权限名, android.Manifest.permission.* 那个,可有多个)
requestCode int: Application specific request code to match with a result reported to onRequestPermissionsResult(int, String[], int[]).(请求码,多次请求处理请求结果时区分哪次请求的)
后面跟着说明一大串(原文),大概就这么几个意思:
1. 申请的权限必须是清单文件里有的,危险等级为 #PROTECTION_DANGEROUS
2. 没有申请,使用该权限就会被阻止。申请了,无论用户同意与否,都会接收到一个callback,可以实现 ActivityCompat.OnRequestPermissionsResultCallback 接口的 onRequestPermissionsResult(int, String[], int[]) 方法处理它。
3. 申请了不一定会被用户授予(意味着你还是得判断权限不被授予的情况,以免FC)
4. 申请时会弹出一个Activity,当前Activity会被 paused 和 resumed 。此外,一些权限需要重启程序,系统会在系统发送授权之前重新创建程序堆栈(英语水平有限,个人理解如此,有错请指正)。
5. 使用 checkSelfPermission(android.content.Context, String). 检查授权
6. 若程序已经拥有该权限,系统会询问用户是否仍然保持该应用拥有此权限(也就是说已经有该权限了,系统也得问一问咯)
向用户提出申请之后,还是有必要检查是否已经通过了的。使用 onRequestPermissionsResult 。Android Studio创建的Activity默认继承 AppCompatActivity ,而那些手动创建Activity直接继承 Activity 的可能需要实现 ActivityCompat.OnRequestPermissionsResultCallback 接口?我没试过
检查用户是否同意授权
重写 onRequestPermissionsResult 方法。
代码
在这里,用户如果眉头同意授予权限的话,会弹出一个AlertDialog提示用户,说明需要权限的原因。若用户还不同意,那就不再提示了,到需要该权限的地方再做判断,或提示重新授权,或提示该功能无法使用
boolean isFirst = true; //这个是成员变量,用来判断是不是第一次申请权限
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//检查是否完成授权
if(grantResults.length > 0 //此处为申请的权限个数-1,下面是判断申请的第n个是否通过
&& grantResults[0] == PackageManager.PERMISSION_GRANTED){
Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
} else {
//失败--第一次,提示重新授权
if(isFirst){
isFirst = false;
//构建提示授权的Dialog
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("授权申请");
builder.setMessage("说明"); //为什么要这些权限??
builder.setPositiveButton("授权", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
requestPermission();
builder.create().dismiss();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
builder.create().cancel(); //取消和返回一样,归到cancel内处理
}
});
builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
//失败--第二次,提示失败
Toast.makeText(FindActivity.this, "提示:没有足够权限,XX功能将无法使用", Toast.LENGTH_SHORT).show();
}
});
builder.show();
} else {
//失败--第二次,提示失败
Toast.makeText(this, "提示:没有足够权限,XX功能将无法使用", Toast.LENGTH_SHORT).show();
}
}
}
分析
(abstract void) onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
Callback for the result from requesting permissions.
- 申请授权的返回结果。包括了在 requestPermissions(android.app.Activity, String[], int). 方法里面申请的所有权限
- 用户选取消,会收到一个空的权限和空的结果数组(这就是为什么要判断 grantResults.length 而不是直接判断 grantResults 数组内容)
Parameters
requestCode int: The request code passed in requestPermissions(android.app.Activity, String[], int)(申请码,requestPermissions 设置的)
permissions String[]: The requested permissions. Never null.(程序申请的权限,永不为空)
grantResults int: The grant results for the corresponding permissions which is either PERMISSION_GRANTED(成功) or PERMISSION_DENIED(失败). Never null.(与permissions一一对应,每个权限的授权结果。)
恩。。。以我这个英语四级没过的水平,勉强也就能理解到此了,出错难免,欢迎指正。。。百度机翻就是个坑,还不如我自己看。。。