Android6.0發(fā)布距離現(xiàn)在快2年多了,雖然它市場(chǎng)占有率仍在龜速上升中亭珍,但還是有一些App開(kāi)發(fā)者已經(jīng)在打包應(yīng)用時(shí)將targetSDKVersion設(shè)置到了23杨箭,也就是說(shuō)把App適配到了Android6.0嗜历。以前調(diào)用Android系統(tǒng)中需要聲明權(quán)限的API時(shí)俱济,只需要在AndroidManifest.xml文件中一次性列出來(lái)。但是如果在build.gradle文件里將targetSDKVersion設(shè)為23以后债蜜,除了在AndroidManifest.xml聲明晴埂,我們還需要根據(jù)App運(yùn)行時(shí)所在的手機(jī)的系統(tǒng)版本,在調(diào)用權(quán)限之前向用戶(hù)申請(qǐng)授權(quán)寻定,并在用戶(hù)允許以后邑时,才可以安全的調(diào)用對(duì)應(yīng)的API。
簡(jiǎn)單舉個(gè)例子特姐,我的App有一個(gè)地理位置讀取的功能晶丘,需要ACCESS_COARSE_LOCATION(粗略的地理位置信息)權(quán)限,如果Apk是以targetSDKVersion=22的方式進(jìn)行打包的唐含,那么在安裝時(shí)用戶(hù)將不得授權(quán)我的App這個(gè)權(quán)限浅浮,否則他將無(wú)法安裝這個(gè)應(yīng)用;如果是以targetSDKVersion=23的形式打包的捷枯,而且用戶(hù)使用的手機(jī)是Android6.0的系統(tǒng)滚秩,那么在安裝時(shí)我的App是沒(méi)有獲得讀取地理位置權(quán)限的,我們需要調(diào)用系統(tǒng)提供的requestPermissions接口來(lái)申請(qǐng)權(quán)限淮捆。這時(shí)候你可能會(huì)說(shuō)那我還設(shè)置targetSDKVersion=23干嘛郁油?還不如直接用22打包得了。攀痊。
不要高興得太早桐腌,下面我們會(huì)說(shuō)理由。因?yàn)橹灰脩?hù)使用的是6.0系統(tǒng)的手機(jī)苟径,他是可以在安裝完成以后案站,在手機(jī)的設(shè)置界面取消一些dangerous權(quán)限的。
下圖就是6.0系統(tǒng)上權(quán)限管理的界面棘街。
targetSDKVersion和compileSDKVersion的作用
在build.gradle中有這么一段:
android {
compileSdkVersion23
buildToolsVersion"23.0.2"
...
defaultConfig {
...
targetSdkVersion22
...
}
targetSDKVersion:簡(jiǎn)單來(lái)說(shuō)就代表著你的App能夠適配的系統(tǒng)版本蟆盐,意味著你的App在這個(gè)版本的手機(jī)上做了充分的前向兼容性處理和實(shí)際測(cè)試承边。其實(shí)我們寫(xiě)代碼時(shí)都是經(jīng)常干這么一件事,就是if(Build.VERSION.SDK_INT >= 23) { ... }石挂,這就是兼容性處理最典型的一個(gè)例子博助。如果你的target設(shè)置得越高,其實(shí)調(diào)用系統(tǒng)提供的API時(shí)痹愚,所得到的處理也是不一樣的翔始,甚至有些新的API是只有新的系統(tǒng)才有的,例如前一篇博客里用到WebView的setWebContentsDebuggingEnabled(boolean))方法里伯,這是Android4.4以后才可以用的一個(gè)API。
compileSdkVersion:是你SDK的版本號(hào)渤闷,也就是你在編程時(shí)引用的android.jar的版本疾瓮。一般都會(huì)和targetSDKVersion相等,或者比targetSDKVersion高飒箭。
因此狼电,如果我們要把自己的App適配到Android6.0系統(tǒng)弦蹂,首先要把targetSDKVersion和compileSDKVersion全部設(shè)置為23。
Android6.0運(yùn)行時(shí)權(quán)限系統(tǒng)到底是干嘛的凸椿?
介紹了targetSDKVersion和compileSDKVersion以后削祈,我們就知道什么叫做適配到Android X.X了。那么Android6.0這個(gè)運(yùn)行時(shí)權(quán)限系統(tǒng)和以前最大的不同就在于:將我們以前一股腦兒以標(biāo)簽方式寫(xiě)在AndroidManifest.xml文件中的權(quán)限劃分成了normal permission和dangerous permission脑漫。
Normal Permission:你寫(xiě)在xml文件里髓抑,那么App安裝時(shí)就會(huì)默認(rèn)獲得這些權(quán)限,即使是在Android6.0系統(tǒng)的手機(jī)上优幸,用戶(hù)也無(wú)法在安裝后動(dòng)態(tài)取消這些normal權(quán)限吨拍,這和以前的權(quán)限系統(tǒng)是一樣的,不變网杆。
Dangerous Permission:你還是得寫(xiě)在xml文件里羹饰,但是App安裝時(shí)具體如果執(zhí)行授權(quán)分以下幾種情況:
targetSDKVersion < 23&API(手機(jī)系統(tǒng)) < 6.0:安裝時(shí)默認(rèn)獲得權(quán)限,且用戶(hù)無(wú)法在安裝App之后取消權(quán)限碳却。
targetSDKVersion >= 23&API(手機(jī)系統(tǒng)) < 6.0:安裝時(shí)默認(rèn)獲得權(quán)限队秩,且用戶(hù)無(wú)法在安裝App之后取消權(quán)限。
targetSDKVersion < 23&API(手機(jī)系統(tǒng)) >= 6.0:安裝時(shí)默認(rèn)獲得權(quán)限昼浦,但是用戶(hù)可以在安裝App完成后動(dòng)態(tài)取消授權(quán)(取消時(shí)手機(jī)會(huì)彈出提醒刹碾,告訴用戶(hù)這個(gè)是為舊版手機(jī)打造的應(yīng)用,讓用戶(hù)謹(jǐn)慎操作)座柱。
targetSDKVersion >= 23&API(手機(jī)系統(tǒng)) >= 6.0:安裝時(shí)不會(huì)獲得權(quán)限迷帜,可以在運(yùn)行時(shí)向用戶(hù)申請(qǐng)權(quán)限物舒。用戶(hù)授權(quán)以后仍然可以在設(shè)置界面中取消授權(quán)。
6.0手機(jī)上取消授權(quán)的界面如下戏锹,如果是targetSDKVersion < 23打包的應(yīng)用冠胯,取消權(quán)限時(shí),會(huì):
我們可以看到其實(shí)只有在6.0的機(jī)器上,打包了適配到6.0的App玖翅,才需要做一些明顯的權(quán)限適配工作挑豌。但是實(shí)話(huà)說(shuō),不論是不是適配6.0系統(tǒng)悉盆,我們都應(yīng)該在調(diào)用需要權(quán)限的接口前,檢查一下是否具有具有該權(quán)限馋吗。因?yàn)槲覀儠?huì)遇到廠商的修改過(guò)權(quán)限系統(tǒng)的ROM焕盟,也有可能自己忘記在xml里加上權(quán)限清單。當(dāng)然這里面也會(huì)有坑宏粤,因?yàn)橛袝r(shí)在不同廠商手機(jī)上直接調(diào)用checkCallingOrSelfPermission方法得到的結(jié)果并不準(zhǔn)確脚翘。
很顯然绍哎,如果不target到23来农,短期內(nèi)還可以不寫(xiě)權(quán)限適配的代碼。但是3缪摺N钟凇!前面提到了海诲,用戶(hù)仍然可以在6.0的手機(jī)上取消安裝時(shí)默認(rèn)賦予的dangerous權(quán)限揽涮。那么這時(shí)候會(huì)發(fā)生什么饿肺??雪标?村刨?如果這個(gè)API原本應(yīng)該返回的是對(duì)象撰茎,那么這時(shí)將返回null;如果這個(gè)API原本應(yīng)該返回的是數(shù)字募疮,這時(shí)就是0僻弹。可想而知芭毙,如果你只是對(duì)返回的null或者0做了一些不恰當(dāng)?shù)奶幚硇对牛珹pp還是可能會(huì)crash的。所以這不是長(zhǎng)久之計(jì)侈百,盡快地處理好權(quán)限申請(qǐng)才是王道,這也是一種對(duì)App唱捣、對(duì)用戶(hù)更負(fù)責(zé)的做法。
如何在運(yùn)行時(shí)申請(qǐng)權(quán)限 & 官方的權(quán)限分級(jí)列表
關(guān)于如何適配到6.0的權(quán)限系統(tǒng)赂毯,網(wǎng)上有非常多的例子拣宰,我覺(jué)得看了這篇文章基本上就OK了巡社,因?yàn)榫W(wǎng)上很多貌似都翻譯自這篇文章,強(qiáng)力推薦一下:things-you-need-to-know-about-android-m-permission
Google官方的RuntimePermissions介紹:runtime-permissions
Google官方的dangerous權(quán)限及分組:permissions: normal-dangerous
開(kāi)源社區(qū)-權(quán)限適配組件:偉大的開(kāi)源社區(qū)已經(jīng)有輪子了肥荔,可以學(xué)習(xí)一下朝群!
TedPermission:不用自己調(diào)用checkSelfPermission(), requestPermissions(),然后再處理回調(diào)onRequestPermissionsResult(), onActivityResult()姜胖。只要一行代碼,設(shè)置一個(gè)listener就可以監(jiān)聽(tīng)授權(quán)的結(jié)果蚜锨,使用起來(lái)非常簡(jiǎn)單。內(nèi)部實(shí)現(xiàn)采用的是類(lèi)似event bus的otto實(shí)現(xiàn)的阀捅。