6.0運(yùn)行時(shí)權(quán)限的總結(jié)與實(shí)踐

運(yùn)行時(shí)權(quán)限.png
運(yùn)行時(shí)權(quán)限.png

為什么需要6.0運(yùn)行時(shí)權(quán)限

  • 更友好

6.0以前的安裝時(shí)權(quán)限,會(huì)在應(yīng)用安裝時(shí)列出所有需要的權(quán)限,當(dāng)列出一些危險(xiǎn)權(quán)限時(shí),用戶不知每個(gè)權(quán)限的具體用途,可能因?yàn)檫@些權(quán)限警告而放棄安裝應(yīng)用。對于一些非裝不可的應(yīng)用,用戶則不得不被迫接受所有權(quán)限,很容易安裝了一些流氓APP,體驗(yàn)不佳。
6.0以后的運(yùn)行時(shí)權(quán)限,可以在調(diào)用相關(guān)功能之前判斷權(quán)限授權(quán)狀態(tài),并自定義提示彈框告知用戶權(quán)限用途,使用戶清楚了解之后,再授權(quán)使用。

5.0和6.0的安裝頁面.png
5.0和6.0的安裝頁面.png
  • 更穩(wěn)定

6.0系統(tǒng)的手機(jī)對于每個(gè)應(yīng)用,都有個(gè)權(quán)限設(shè)置頁面,可以手動(dòng)開關(guān)權(quán)限,如果用戶在設(shè)置頁面誤關(guān)了某個(gè)權(quán)限,若沒在程序運(yùn)行時(shí)做判斷,則會(huì)導(dǎo)致相關(guān)功能的調(diào)用失敗,引起崩潰等。

5.0和6.0的權(quán)限設(shè)置頁面.png
5.0和6.0的權(quán)限設(shè)置頁面.png

如何實(shí)現(xiàn)運(yùn)行時(shí)權(quán)限

  • 設(shè)置targetSdkVersion

只有targetSdkVersion>=23,且安裝在6.0以上的手機(jī)時(shí),運(yùn)行時(shí)權(quán)限機(jī)制才能正常運(yùn)作

手機(jī)系統(tǒng) targetSdkVersion<23 targetSdkVersion>=23
5.0+ 安裝時(shí)權(quán)限 安裝時(shí)權(quán)限
6.0+ 安裝時(shí)權(quán)限 運(yùn)行時(shí)權(quán)限
  • 代碼實(shí)現(xiàn)

在需要使用某項(xiàng)權(quán)限時(shí),通過V4包的checkSelfPermission判斷權(quán)限是否授權(quán),通過requestPermissions申請某項(xiàng)權(quán)限

// 需要執(zhí)行某項(xiàng)需要權(quán)限的操作時(shí)
if (ContextCompat.checkSelfPermission(this, "某項(xiàng)權(quán)限") == PackageManager.PERMISSION_GRANTED) {
   // 執(zhí)行操作
} else {
   // 請求權(quán)限
   ActivityCompat.requestPermissions(this, new String[]{"某項(xiàng)權(quán)限"}, requestCode);
}

在Activity的onRequestPermissionsResult回調(diào)方法中,處理權(quán)限授權(quán)結(jié)果

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
   if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
       // 授權(quán)成功,執(zhí)行操作
   } else {
       // 權(quán)限被拒絕
       if (ActivityCompat.shouldShowRequestPermissionRationale(this, "權(quán)限名稱")) {
           // shouldShowRequestPermissionRationale=true: 表示權(quán)限被拒絕,且沒有勾選"never ask again"
           // 正常的權(quán)限被拒絕流程,可以繼續(xù)申請權(quán)限,重復(fù)以上流程
       } else {
           // shouldShowRequestPermissionRationale=false: 在權(quán)限被拒絕,且勾選"never ask again"的情況下,返回false
           // 繼續(xù)申請權(quán)限的時(shí)候,不會(huì)再彈出默認(rèn)的系統(tǒng)彈框,需要自定義提示彈框,并引導(dǎo)用戶去權(quán)限設(shè)置頁面,手動(dòng)開啟權(quán)限
       }
   }
}

LsPermission工具類的使用

  • 主要實(shí)現(xiàn)邏輯參考PermissionGen,封裝了權(quán)限判斷,請求,結(jié)果處理等通用邏輯,目前只支持context=AppCompatActivity,如果在Fragment中使用時(shí)可以調(diào)用getActivity()獲取上層AppCompatActivity。
demo演示.gif
demo演示.gif
private void normal() {
   final String[] permissions =
       new String[] {Manifest.permission.CALL_PHONE, Manifest.permission.ACCESS_FINE_LOCATION};

   PermissionUtil.request(this, permissions, new OnPermissionAdapter() {
       /**
        * @desc 申請的權(quán)限全被授權(quán)
        */
       @Override
       public void onGrant() {
           showToast("權(quán)限被同意");
           callPhone();
       }

       /**
        * @desc 權(quán)限被拒絕
        */
       @Override
       public void onDeny(List<String> permissions) {
           showToast("用戶拒絕授權(quán)" + permissions.toString());
       }

       /**
        * @desc 權(quán)限被拒絕,且勾選"never ask again"
        */
       @Override
       public void onNeverAsk(List<String> permissions) {
           showToast("用戶拒絕授權(quán), 并勾選 never ask again " + permissions.toString());
           PermissionUtil.showNeverAskDialog(MainActivity.this, "這個(gè)權(quán)限很重要");
       }
       
       /**
        * @desc 無論權(quán)限授權(quán)成功還是失敗,都會(huì)回調(diào)
        */
       @Override
       public void always(List<String> grantPermissions, List<String> denyPermissions,
           List<String> foreverDenyPermissions) {
           showToast("授權(quán): " + grantPermissions.toString() + "\n 拒絕: " + denyPermissions.toString()
               + "\n never ask: " + foreverDenyPermissions.toString());
       }
   });
}

/**
* @desc 將權(quán)限回調(diào)轉(zhuǎn)發(fā)給PermissionUtil處理
* @author listen
* @date 2017/2/24 13:47
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
   PermissionUtil.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
   super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
  • PermissionUtil內(nèi)部通過SparseArray保存了requestCode和權(quán)限回調(diào)的鍵值對,避免了連續(xù)點(diǎn)擊時(shí)重復(fù)回調(diào)情況,對于不同的權(quán)限申請,推薦使用不同的requestCode,避免回調(diào)覆蓋的問題。
private static SparseArray<OnPermissionListener> mPermissionRequestList = new SparseArray<>();

public static void request(final Context context, int requestCode, String[] permissions,
                          OnPermissionListener listener) {
   /** 存在未授權(quán)的權(quán)限 */
   synchronized (mPermissionRequestList) {
       if (null != mPermissionRequestList.get(requestCode)) {
           /** 當(dāng)前權(quán)限請求已經(jīng)存在,不重復(fù)添加 */
           log("the same permission is requesting");
       } else {
           /** 將當(dāng)前權(quán)限請求加入隊(duì)列 */
           /** 如果一個(gè)頁面中存在分別觸發(fā)A, B多個(gè)權(quán)限的情況, 則最好將不同權(quán)限申請對應(yīng)不同的requestCode, 存入SparseArray分別處理 */
           mPermissionRequestList.put(requestCode, listener);

           /** 執(zhí)行權(quán)限申請 */
           ActivityCompat.requestPermissions();
       }
   }
}

在權(quán)限回調(diào)的時(shí)候從SparseArray移除Listener

public static void onRequestPermissionsResult(Context context, int requestCode, String[] permissions,
                                                  int[] grantResults) {
   final OnPermissionListener listener;
   synchronized (mPermissionRequestList) {
       listener = mPermissionRequestList.get(requestCode);
       mPermissionRequestList.remove(requestCode);
   }

   if (null != listener) {
       /** 執(zhí)行回調(diào) */
       listener.onGrant();
       listener.onDeny();
       listener.onNeverAsk();
       listener.always();
   } else {
       log("request is not exists");
   }
}

代碼地址:LsPermission

除了基本的權(quán)限申請邏輯的封裝以外,還寫了類似微信,支付寶,百度地圖等在啟動(dòng)頁的權(quán)限申請Demo,算是PermissionUtil的簡單運(yùn)用。

參考:
Android 6.0 運(yùn)行時(shí)權(quán)限處理完全解析
Android 6.0 運(yùn)行時(shí)權(quán)限管理最佳實(shí)踐
聊一聊Android 6.0的運(yùn)行時(shí)權(quán)限

官方:
在運(yùn)行時(shí)請求權(quán)限
權(quán)限最佳做法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,016評論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,006評論 2 374

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