Android6.0權(quán)限處理不再?gòu)?fù)雜

前言

谷歌在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大類別

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

權(quán)限調(diào)度者霍骄。

使用

在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宦言,如圖所示:

ScanQRActivityPermissionsDispatcher

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)行效果

進(jìn)入檢查提示
確定時(shí),提示
拒絕時(shí)践盼,提示

這樣使用后鸦采,Android權(quán)限請(qǐng)求這一塊的邏輯就變得比較友好。

以上的所有內(nèi)容就是今天要講的關(guān)于Android6.0權(quán)限處理的內(nèi)容咕幻。

我自己在寫這文章時(shí)渔伯,也有所收獲,同時(shí)希望能對(duì)大家有所幫助肄程。

謝謝支持~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锣吼,一起剝皮案震驚了整個(gè)濱河市选浑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吐限,老刑警劉巖鲜侥,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異诸典,居然都是意外死亡描函,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門狐粱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)舀寓,“玉大人,你說(shuō)我怎么就攤上這事肌蜻』ツ梗” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蒋搜,是天一觀的道長(zhǎng)篡撵。 經(jīng)常有香客問(wèn)我,道長(zhǎng)豆挽,這世上最難降的妖魔是什么育谬? 我笑而不...
    開(kāi)封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮帮哈,結(jié)果婚禮上膛檀,老公的妹妹穿的比我還像新娘。我一直安慰自己娘侍,他們只是感情好咖刃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著憾筏,像睡著了一般嚎杨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上氧腰,一...
    開(kāi)封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天磕潮,我揣著相機(jī)與錄音,去河邊找鬼容贝。 笑死自脯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斤富。 我是一名探鬼主播膏潮,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼满力!你這毒婦竟也來(lái)了焕参?” 一聲冷哼從身側(cè)響起轻纪,我...
    開(kāi)封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎叠纷,沒(méi)想到半個(gè)月后刻帚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涩嚣,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年崇众,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片航厚。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡顷歌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幔睬,到底是詐尸還是另有隱情眯漩,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布麻顶,位于F島的核電站赦抖,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏辅肾。R本人自食惡果不足惜队萤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宛瞄。 院中可真熱鬧浮禾,春花似錦交胚、人聲如沸份汗。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)杯活。三九已至,卻和暖如春熬词,著一層夾襖步出監(jiān)牢的瞬間旁钧,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工互拾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歪今,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓颜矿,卻偏偏與公主長(zhǎng)得像寄猩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子骑疆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容