前言
谷歌在2015年8月份時(shí)候拂酣,發(fā)布了Android 6.0版本椅棺,代號(hào)叫做“棉花糖”(Marshmallow )屁擅,其中的很大的一部分變化偿凭,是在用戶權(quán)限授權(quán)上,或許是感覺(jué)之前默認(rèn)授權(quán)的不合理派歌,現(xiàn)在6.0出來(lái)弯囊,使得用戶權(quán)限授權(quán)變得合理。
Android 6.0版本之前
在此版本之前胶果,只要在清單文件(AndroidManifest)中申請(qǐng)需要用到的權(quán)限匾嘱,安裝之后,所申請(qǐng)的權(quán)限將會(huì)被允許早抠。
Android 6.0版本之后
從Android6.0開(kāi)始霎烙,APP可以直接安裝,但所需的權(quán)限則需要?jiǎng)討B(tài)申請(qǐng)蕊连。App在運(yùn)行時(shí)詢問(wèn)用戶授予權(quán)限悬垃,彈出Dialog窗口進(jìn)行詢問(wèn)是否允許,【拒絕】之后甘苍,也可以引導(dǎo)用戶前往設(shè)置界面盗忱。
權(quán)限分類
Google將權(quán)限分為兩類:
一類是Normal Permissions,這類權(quán)限一般不涉及用戶隱私羊赵,是不需要用戶進(jìn)行授權(quán)的趟佃,比如手機(jī)震動(dòng)扇谣、訪問(wèn)網(wǎng)絡(luò)等,所以開(kāi)發(fā)者直接在清單文件中申請(qǐng)即可闲昭;
另一類是Dangerous Permission罐寨,一般是涉及到用戶隱私的,需要用戶進(jìn)行授權(quán)序矩,比如讀取sdcard鸯绿、訪問(wèn)通訊錄等;
但在Dangerous Permission中簸淀,其實(shí)還有比較特殊的兩個(gè)權(quán)限存在瓶蝴,分別是SYSTEM_ALERT_WINDOW(允許一個(gè)程序打開(kāi)窗口,顯示在其他所有程序的頂層)和WRITE_SETTINGS(允許應(yīng)用程序更改主屏幕中的設(shè)置和快捷方式)租幕。
這兩個(gè)權(quán)限也屬于Dangerous Permission舷手,但是在申請(qǐng)上卻有點(diǎn)特殊。這兩個(gè)權(quán)限是不能自動(dòng)授權(quán)劲绪,也不能運(yùn)行時(shí)請(qǐng)求授權(quán)男窟,只能引導(dǎo)用戶去應(yīng)用的設(shè)置頁(yè)手動(dòng)開(kāi)啟。
PS:Dangerous Permission的權(quán)限9大類別
只要授權(quán)某一個(gè)類別中的其中某一個(gè)權(quán)限贾富,則該類別的權(quán)限默認(rèn)全部授權(quán)歉眷,不需要針對(duì)該類別再次詢問(wèn)用戶是否允許。
常用的權(quán)限申請(qǐng)
從Android6.0后颤枪,我們常用的權(quán)限申請(qǐng)汗捡,例如相機(jī)權(quán)限的申請(qǐng),代碼如下:
// 相機(jī)權(quán)限 2017/3/8 11:45
public static final int REQUEST_CAMERA = 4;
private static String[] PERMISSIONS_CAMERA = {
Manifest.permission.CAMERA};
/**
* 申請(qǐng)相機(jī)權(quán)限 2017/3/8 11:48
* @param activity
*/
public static void cameraPermissions(Activity activity) {
logger.debug("Camera permissions.");
int permission = ActivityCompat.checkSelfPermission(activity,
Manifest.permission.CAMERA);
if (permission != PackageManager.PERMISSION_GRANTED) {
logger.debug("Not have camera permissions.");
ActivityCompat.requestPermissions(activity, PERMISSIONS_CAMERA,
REQUEST_CAMERA);
}
}
上面是申請(qǐng)相機(jī)權(quán)限的代碼畏纲,那么在調(diào)用的Activity類中凉唐,重寫如下方法:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == RequestPermissions.REQUEST_CAMERA) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
Toast.makeText(this, "請(qǐng)授予相機(jī)權(quán)限", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
以上就是我們常用的權(quán)限申請(qǐng)。
PermissionsDispatcher
使用
在module.build.gradle中配置台囱,如下:
compile 'com.github.hotchemi:permissionsdispatcher:2.3.2'
annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:2.3.2'
PS
舊版需要在top.build.gradle中配置如下信息:
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
在module.build.gradle中配置,如下:
apply plugin: 'android-apt'
我在最新的版本2.3.2已經(jīng)不需要以上的配置了读整,不然會(huì)生成失敗簿训。等會(huì)在下面會(huì)講。
Activity中的使用
package com.example.chenchubin.mypermission;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.support.annotation.NonNull;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.OnNeverAskAgain;
import permissions.dispatcher.OnPermissionDenied;
import permissions.dispatcher.OnShowRationale;
import permissions.dispatcher.PermissionRequest;
import permissions.dispatcher.RuntimePermissions;
@RuntimePermissions
public class ScanQRActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
// 檢查權(quán)限 2017/4/13 17:22
ScanQRActivityPermissionsDispatcher.getCameraWithCheck(this);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[]
grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// 回調(diào)代理進(jìn)行處理 2017/4/13 17:22
ScanQRActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
}
/**
* 已授權(quán)時(shí)米间,進(jìn)入Activity會(huì)調(diào)用該方法 2017/4/13 17:22
*/
@NeedsPermission(Manifest.permission.CAMERA)
public void getCamera() {
}
/**
* 授權(quán)申請(qǐng)?zhí)崾厩科罚卣{(diào) 2017/4/13 17:22
* @param request
*/
@OnShowRationale(Manifest.permission.CAMERA)
public void showRationaleForCamera(final PermissionRequest request) {
new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("權(quán)限申請(qǐng)")
.setMessage("應(yīng)用需要使用相機(jī)權(quán)限,您是否確定要使用")
.setNegativeButton("拒絕", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
request.cancel();
}
})
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
request.proceed();
}
})
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
})
.show();
}
/**
* 拒絕時(shí)屈糊,回調(diào) 2017/4/13 17:22
*/
@OnPermissionDenied(Manifest.permission.CAMERA)
public void showDeniedForCamera() {
new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("權(quán)限申請(qǐng)")
.setMessage("在設(shè)置-應(yīng)用-當(dāng)前應(yīng)用權(quán)限中開(kāi)啟相機(jī)權(quán)限的榛,以正常使用拍照")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
})
.setPositiveButton("去設(shè)置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//開(kāi)啟設(shè)置頁(yè)
startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
dialog.dismiss();
}
})
.show();
}
/**
* 不再詢問(wèn)時(shí),回調(diào) 2017/4/13 17:23
*/
@OnNeverAskAgain(Manifest.permission.CAMERA)
public void showNeverAskForCamera() {
new AlertDialog.Builder(this)
.setCancelable(false)
.setTitle("權(quán)限申請(qǐng)")
.setMessage("您已禁止不再詢問(wèn)逻锐,請(qǐng)前往設(shè)置-應(yīng)用-當(dāng)前應(yīng)用權(quán)限中開(kāi)啟相機(jī)權(quán)限夫晌,以正常使用拍照")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
finish();
}
})
.setPositiveButton("去設(shè)置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//開(kāi)啟設(shè)置頁(yè)
startActivity(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
dialog.dismiss();
}
})
.show();
}
}
注解的意思
@RuntimePermissions
(必選)運(yùn)行時(shí)雕薪,需要檢查權(quán)限的類。
@NeedsPermission
(必選)當(dāng)進(jìn)入Activity類時(shí)晓淀,如果已授權(quán)所袁,會(huì)直接調(diào)用該注解的方法。
@OnShowRationale
(可選)授權(quán)申請(qǐng)時(shí)凶掰,調(diào)用燥爷。
@OnPermissionDenied
(可選)授權(quán)申請(qǐng)被拒絕時(shí),調(diào)用懦窘。
@OnNeverAskAgain
(可選)授權(quán)申請(qǐng)被勾選不再提示時(shí)前翎,調(diào)用。
PS:
1畅涂,執(zhí)行request.proceed()調(diào)用系統(tǒng)申請(qǐng)權(quán)限的彈窗港华;
如果在系統(tǒng)申請(qǐng)彈窗中勾選了不在提示并且拒絕,會(huì)調(diào)用@OnNeverAskAgain的方法毅戈;
2,執(zhí)行request.cancel()會(huì)調(diào)用@OnPermissionDenied的方法愤惰。
Make Project
Make Project后苇经,編譯器會(huì)在app\build\intermediates\classes\debug目錄下與被注解的Activity同一個(gè)包下生成一個(gè)輔助類,名稱為被注解的Activity名稱+PermissionsDispatcher.class宦言,如圖所示:
PS:
這里需要注意扇单,因?yàn)槲以谶@里遇到了一個(gè)大坑。
就是上面提到的奠旺,新版中已不需要在top.build.gradle中配置android-apt插件蜘澜,要不上面的ScanQRActivityPermissionsDispatcher一直沒(méi)有生成出來(lái),找了我半個(gè)小時(shí)响疚。鄙信。。
生成代理類后忿晕,檢查調(diào)用装诡,代碼如下:
// 檢查權(quán)限 2017/4/13 17:22
ScanQRActivityPermissionsDispatcher.getCameraWithCheck(this);
運(yùn)行效果
這樣使用后鸦采,Android權(quán)限請(qǐng)求這一塊的邏輯就變得比較友好。
以上的所有內(nèi)容就是今天要講的關(guān)于Android6.0權(quán)限處理的內(nèi)容咕幻。
我自己在寫這文章時(shí)渔伯,也有所收獲,同時(shí)希望能對(duì)大家有所幫助肄程。
謝謝支持~~~