android權(quán)限處理詳解

寫在前面
對(duì)于android 6.0來(lái)說(shuō),增加了權(quán)限的管理甚淡,能夠更好的保護(hù)用戶的隱私,當(dāng)用戶需要某權(quán)限時(shí)捅厂,才動(dòng)態(tài)的去申請(qǐng)贯卦。用戶也可以在應(yīng)用權(quán)限管理里面關(guān)閉和打開(kāi)资柔。為了方便以后使用,這里對(duì)權(quán)限使用相關(guān)做一個(gè)簡(jiǎn)單的總結(jié)撵割。

android權(quán)限分類

Android6.0系統(tǒng)把權(quán)限分為兩個(gè)級(jí)別:

  • Normal Permissions贿堰,即普通權(quán)限,這類權(quán)限不會(huì)潛藏有侵害用戶隱私和安全的問(wèn)題睁枕,比如官边,訪問(wèn)網(wǎng)絡(luò)的權(quán)限,訪問(wèn)WIFI的權(quán)限等外遇;
  • Dangerous Permissions注簿,即危險(xiǎn)權(quán)限,這類權(quán)限會(huì)直接的威脅到用戶的安全和隱私問(wèn)題跳仿,比如說(shuō)訪問(wèn)短信诡渴,相冊(cè)等權(quán)限。

普通權(quán)限是不會(huì)威脅到用戶安全的菲语,所以這類權(quán)限是可以直接在manifest里面直接的使用妄辩,而且在安裝后也會(huì)直接的生效了。不需要特殊處理山上。危險(xiǎn)權(quán)限在使用時(shí)不僅需要在manifest里面注冊(cè)眼耀,還需要?jiǎng)討B(tài)申請(qǐng),否則程序會(huì)崩潰佩憾,提示沒(méi)有權(quán)限哮伟。
危險(xiǎn)權(quán)限分為9組,總共24個(gè)權(quán)限妄帘,如下:

權(quán)限組名 權(quán)限名
CALENDAR 日歷 READ_CALENDAR
WRITE_CALENDER
CAMERA 相機(jī) CAMERA
CONTACTS 聯(lián)系人 READ_CONTACTS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATION 定位 ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONE 麥克風(fēng) 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 短信 Short Message Service
SEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGE 數(shù)據(jù)存儲(chǔ) READ_EXTRAL_STRORAGE
WRITE_EXTERNAL_STORAGE

申請(qǐng)權(quán)限時(shí):
1楞黄、在清單文件中聲明權(quán)限(如果不在這張表中,聲明完就可以了)
2抡驼、如果在這張表中的權(quán)限需要手動(dòng)來(lái)申請(qǐng)

這些權(quán)限6.0以后需要手動(dòng)申請(qǐng)鬼廓,,每一個(gè)權(quán)限組中的權(quán)限只要有一個(gè)權(quán)限同意授權(quán)了致盟,整個(gè)權(quán)限組中的權(quán)限就不用重復(fù)申請(qǐng)了碎税。
如果如果查看所有的權(quán)限,請(qǐng)參考:
https://developer.android.com/about/versions/marshmallow

android 權(quán)限使用場(chǎng)景

由于android 系統(tǒng)版本太多馏锡,并且用戶使用的手機(jī)版本也無(wú)法確定雷蹂,因此在權(quán)限處理時(shí),需要多方面考慮眷篇。 而對(duì)于開(kāi)發(fā)者而言萎河,最主要考慮的是 targetversion和buildVersion(即真機(jī)系統(tǒng)版本)荔泳。下面從以下方面考慮:

targetVersion BuildVersion 是否需要處理
>=23 >=23 需要?jiǎng)討B(tài)處理
>=23 <23 不需要
< 23 >=23 需要處理
< 23 <23 不需要

權(quán)限基本使用

  1. 在manifest.xml文件中聲明需要的權(quán)限
  2. 檢查是否擁有權(quán)限蕉饼,通過(guò)checkSelfPermission函數(shù)虐杯,如下:
if (ContextCompat.checkSelfPermission(thisActivity,
            Manifest.permission.READ_CONTACTS)
    != PackageManager.PERMISSION_GRANTED) {
    //沒(méi)有授權(quán),編寫申請(qǐng)權(quán)限代碼
}else{
//已經(jīng)授權(quán)昧港,執(zhí)行操作代碼
}   

checkSelfPermission函數(shù)有兩個(gè)參數(shù):context和需要的權(quán)限

  1. 若沒(méi)有權(quán)限則申請(qǐng)權(quán)限擎椰,如下:
ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_CONTACTS},
            1);

這是一個(gè)異步的方法,第一個(gè)參數(shù)是Context创肥;第二個(gè)參數(shù)是需要申請(qǐng)的權(quán)限的字符串?dāng)?shù)組(這個(gè)是支持同時(shí)申請(qǐng)多個(gè)權(quán)限达舒,系統(tǒng)會(huì)逐個(gè)詢問(wèn)是否授權(quán));第三個(gè)參數(shù)為請(qǐng)求碼requestCode叹侄,主要用于回調(diào)的時(shí)候檢測(cè)巩搏。

  1. 處理權(quán)限的回調(diào)結(jié)果
  //權(quán)限回調(diào)方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){

        case 0:
            //grantResults數(shù)組存儲(chǔ)的申請(qǐng)的返回結(jié)果,
            //PERMISSION_GRANTED 表示申請(qǐng)成功
            if (grantResults.length>0&&grantResults[0]== PackageManager.PERMISSION_GRANTED){
                //授權(quán)成功趾代,
                //這里寫相應(yīng)的 操作代碼
            }else{
                //授權(quán)失敗贯底,可以簡(jiǎn)單提示用戶
                Toast.makeText(this, "沒(méi)有授權(quán)繼續(xù)操作", Toast.LENGTH_SHORT).show();
            }
            break;
        default:
            break;
    }
}

注意:申請(qǐng)的時(shí)候是一個(gè)一個(gè)的申請(qǐng)的話,每次申請(qǐng)都有一個(gè)請(qǐng)求碼撒强,這里的grantResults數(shù)組就只有一個(gè)值禽捆,所以都是grantResults[0]來(lái)和PERMISSION_GRANTED來(lái)進(jìn)行比較
如果是一次申請(qǐng)多個(gè)權(quán)限,grantResults數(shù)組返回的值就不止一個(gè)飘哨,但是胚想,直接遍歷它就行,只要全部滿足條件才算申請(qǐng)成功芽隆,才能進(jìn)行相應(yīng)的操作
一般的寫法是:
通過(guò)if判斷權(quán)限是否申請(qǐng)浊服,沒(méi)有申請(qǐng),把它加到一個(gè)集合里面摆马,把所有的權(quán)限都判斷一遍以后臼闻,去遍歷這個(gè)集合,只要有一個(gè)沒(méi)有申請(qǐng)的囤采,就需述呐、要去申請(qǐng)權(quán)限, 把這個(gè)集合轉(zhuǎn)為數(shù)組蕉毯,傳到requestPermissions的第二個(gè)參數(shù)乓搬,然后就處理相應(yīng)結(jié)果就可以了,遍歷grantResults數(shù)組代虾,判斷是不是全部滿足條件

特殊處理

但 targetVersion小于23进肯,但是BuildVersion大于23這個(gè)場(chǎng)景時(shí),若用戶在應(yīng)用權(quán)限設(shè)置里面手動(dòng)關(guān)閉了要使用的權(quán)限棉磨,在應(yīng)用操作時(shí)江掩,檢查權(quán)限會(huì)一直返回true,并且系統(tǒng)崩潰。
導(dǎo)致這個(gè)的原因环形,是 ContextCompat.checkSelfPermission函數(shù)再TargetVersion<23時(shí)策泣,會(huì)一直返回true。因此為了兼容此情形抬吟,V4包里面提供了PermissionChecker.checkSelfPermission函數(shù)萨咕,用來(lái)處理這種情形。因此火本,考慮兩種情形危队,完成的權(quán)限檢查代碼如下:

 /**
     * android 6.0 以上檢查是否有權(quán)限
     * @param context    context
     * @param primission 權(quán)限名稱
     * @return false 沒(méi)有權(quán)限   true 有權(quán)限
     */
    private boolean checkPrimission(Context context ,String primission)
    {
        int targetSdkVersion ;
        boolean result = false;
        PackageInfo info = null;
        try {
            info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            targetSdkVersion = info.applicationInfo.targetSdkVersion;
            if (targetSdkVersion >= Build.VERSION_CODES.M) {  //targetSdkVersion >= 23
                if (ContextCompat.checkSelfPermission(cdActivity, primission) != PackageManager.PERMISSION_GRANTED) {
                    result = false;
                }else{
                    result = true;
                }
            } else { //targetSdkVersion < 23
                if (PermissionChecker.checkSelfPermission(cdActivity, Manifest.permission.CAMERA)
                        != PermissionChecker.PERMISSION_GRANTED) {
                    result = false;
                }else{
                    result = true;
                }
            }

        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG,e.getMessage());
        }


        return result;
    }

多次請(qǐng)求處理

shouldShowRequestPermissionRationale應(yīng)用場(chǎng)景

//參數(shù)是一個(gè)權(quán)限,返回true或false
shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)

?當(dāng)用戶第一次拒絕申請(qǐng)的權(quán)限钙畔,第二次再申請(qǐng)權(quán)限之前彈出一個(gè)對(duì)話框茫陆,給用戶做出一個(gè)解釋,為啥需要申請(qǐng)權(quán)限擎析,根據(jù)用戶的選擇盅弛,再考慮是否申請(qǐng)權(quán)限。

該函數(shù)返回值根據(jù)不同情形有以下情況:
?1. 第一次請(qǐng)求某權(quán)限時(shí)叔锐,返回值為false
?2. 第一次請(qǐng)求某權(quán)限拒絕后挪鹏,返回值為true
?3. 第二次請(qǐng)求某權(quán)限拒絕后,返回值為true
?4. 第三次請(qǐng)求某權(quán)限愉烙,點(diǎn)了不再提醒讨盒,并拒絕,返回值為false
?5. 任何時(shí)候步责,只要允許了權(quán)限返顺,返回值就為false

因此根據(jù)這些情況可以做一下特殊處理

  • 在請(qǐng)求權(quán)限前,調(diào)用此函數(shù)蔓肯,判斷是否需要和用戶解釋(true,表示拒絕過(guò)一次)遂鹊;
  • 在onRequestPermissionsResult里面調(diào)用,判斷用戶是否點(diǎn)了“不在詢問(wèn)”蔗包,并拒絕秉扑。可以彈出對(duì)話框引導(dǎo)用戶去設(shè)置頁(yè)面設(shè)置调限。
    ??不再提醒權(quán)限方法:(用戶勾選拒絕后不再詢問(wèn))
//參數(shù)是一個(gè)權(quán)限舟陆,返回true或false
shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)
  • 返回true表示用戶沒(méi)有勾選 拒絕后不再詢問(wèn),你可以再去調(diào)用requestPermissions申請(qǐng)權(quán)限

  • 返回false分幾種情況:
    1.用戶勾選了 拒絕后不再詢問(wèn)耻矮,你只能引導(dǎo)用戶去設(shè)置中開(kāi)啟權(quán)限了
    2.用戶自己在設(shè)置中把權(quán)限給關(guān)了...
    3.系統(tǒng)禁止應(yīng)用具有該權(quán)限!
    注意:部分手機(jī)會(huì)對(duì)權(quán)限有自己的默認(rèn)處理秦躯,比如小米,該函數(shù)一直返回false裆装,因此踱承,針對(duì)于不同的手機(jī)需要自己適配處理該方法倡缠。

android 8.0 處理

??在android 6.0 之上,最開(kāi)始的處理是: 只要一組權(quán)限中的一個(gè)權(quán)限通過(guò)茎活,該組其他權(quán)限也默認(rèn)通過(guò)毡琉。
??對(duì)于針對(duì)Android O的應(yīng)用,此行為已被糾正妙色。系統(tǒng)只會(huì)授予應(yīng)用明確請(qǐng)求的權(quán)限。然而一旦用戶為應(yīng)用授予某個(gè)權(quán)限慧耍,則所有后續(xù)對(duì)該權(quán)限組中權(quán)限的請(qǐng)求都將被自動(dòng)批準(zhǔn)身辨。
例如,假設(shè)某個(gè)應(yīng)用在其清單中列出READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE芍碧。應(yīng)用請(qǐng)求READ_EXTERNAL_STORAGE煌珊,并且用戶授予了該權(quán)限,如果該應(yīng)用針對(duì)的是API級(jí)別24或更低級(jí)別泌豆,系統(tǒng)還會(huì)同時(shí)授予WRITE_EXTERNAL_STORAGE定庵,因?yàn)樵摍?quán)限也屬于STORAGE權(quán)限組并且也在清單中注冊(cè)過(guò)。如果該應(yīng)用針對(duì)的是Android O踪危,則系統(tǒng)此時(shí)僅會(huì)授予READ_EXTERNAL_STORAGE蔬浙,不過(guò)在該應(yīng)用以后申請(qǐng)WRITE_EXTERNAL_STORAGE權(quán)限時(shí),系統(tǒng)會(huì)立即授予該權(quán)限贞远,而不會(huì)提示用戶畴博。

權(quán)限請(qǐng)求框架

  • RxPermission
  • PermissionsDispatcher
  • EasyPermissions
    具體使用方式后續(xù)補(bǔ)充±吨伲可以github上自行搜索使用方式俱病。

自己也封裝過(guò)一個(gè)框架
github地址:https://github.com/YuanQiCan/PermissionGrant
包含以下功能:

  1. 權(quán)限檢查,targetSdkVersion 大于23和小于23兩種情形
  2. 單個(gè)權(quán)限和多個(gè)權(quán)限申請(qǐng)?zhí)幚?/li>
  3. shouldShowRequestPermissionRationale包含的情形處理
  4. 基本對(duì)畫框顯示和頁(yè)面跳轉(zhuǎn)

有興趣的可以看看袱结,使用方便亮隙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市垢夹,隨后出現(xiàn)的幾起案子溢吻,更是在濱河造成了極大的恐慌,老刑警劉巖果元,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件煤裙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡噪漾,警方通過(guò)查閱死者的電腦和手機(jī)硼砰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)欣硼,“玉大人题翰,你說(shuō)我怎么就攤上這事。” “怎么了豹障?”我有些...
    開(kāi)封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵冯事,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我血公,道長(zhǎng)昵仅,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任累魔,我火速辦了婚禮摔笤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘垦写。我一直安慰自己吕世,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布梯投。 她就那樣靜靜地躺著命辖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪分蓖。 梳的紋絲不亂的頭發(fā)上尔艇,一...
    開(kāi)封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音么鹤,去河邊找鬼漓帚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛午磁,可吹牛的內(nèi)容都是我干的尝抖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼迅皇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼昧辽!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起登颓,我...
    開(kāi)封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤搅荞,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后框咙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體咕痛,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年喇嘱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茉贡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡者铜,死狀恐怖腔丧,靈堂內(nèi)的尸體忽然破棺而出放椰,到底是詐尸還是另有隱情,我是刑警寧澤愉粤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布砾医,位于F島的核電站,受9級(jí)特大地震影響衣厘,放射性物質(zhì)發(fā)生泄漏如蚜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一影暴、第九天 我趴在偏房一處隱蔽的房頂上張望错邦。 院中可真熱鬧,春花似錦坤检、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至讨勤,卻和暖如春箭跳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背潭千。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工谱姓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刨晴。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓屉来,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親狈癞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子茄靠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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