權(quán)限請求可以保護設(shè)備中的敏感信息谱轨,并且僅當應(yīng)用正常工作需要訪問相關(guān)信息時才能使用這些信息。利用本文檔提供的技巧庸毫,您無需請求訪問此類信息即可實現(xiàn)相同(或更好的)功能爹凹;但本文不會詳細討論權(quán)限在 Android 操作系統(tǒng)中的工作方式。
要更籠統(tǒng)地了解 Android 權(quán)限身诺,請參閱權(quán)限概述蜜托。要詳細了解如何在代碼中使用權(quán)限,請參閱請求應(yīng)用權(quán)限霉赡。
使用 Android 權(quán)限的原則
使用 Android 權(quán)限時橄务,我們建議遵循以下原則:
#1:僅使用應(yīng)用正常工作所需的權(quán)限。根據(jù)您使用權(quán)限的方式穴亏,您可以通過其他方式執(zhí)行所需的操作(系統(tǒng) intent仪糖、標識符、電話的后臺處理)迫肖,而無需依賴于訪問敏感信息锅劝。
#2:注意庫所需的權(quán)限。 添加某個庫時蟆湖,您也會繼承它的權(quán)限要求故爵。您應(yīng)了解正在添加的庫、它們需要的權(quán)限以及這些權(quán)限的用途隅津。
#3:公開透明诬垂。 請求權(quán)限時,請清晰說明您要訪問的內(nèi)容以及訪問原因伦仍,以便用戶可以做出明智的決策结窘。在請求權(quán)限時(包括安裝、運行時或更新權(quán)限對話框)列出這些信息充蓝。
#4:讓系統(tǒng)以顯式方式訪問隧枫。 在訪問敏感功能(例如,攝像頭或麥克風)時提供連續(xù)指示谓苟,讓用戶知道您在收集數(shù)據(jù)官脓,避免讓他們認為您在偷偷地收集數(shù)據(jù)。
本指南剩下的部分將以開發(fā) Android 應(yīng)用為背景詳細介紹這些規(guī)則涝焙。
Android 6.0+ 中的權(quán)限
Android 6.0 Marshmallow 引入了一個新的權(quán)限模式卑笨,讓應(yīng)用可以在運行時而不是在安裝之前向用戶請求權(quán)限。支持這個新模式的應(yīng)用會在應(yīng)用確實需要相關(guān)服務(wù)或這些服務(wù)保護的數(shù)據(jù)時請求權(quán)限仑撞。盡管這不會(不一定會)改變整體應(yīng)用行為赤兴,但會給敏感用戶數(shù)據(jù)的處理方式帶來一些變化:
增加了情境上下文:系統(tǒng)會在運行時在應(yīng)用的上下文中提示用戶提供訪問相關(guān)權(quán)限組涵蓋的功能所需的權(quán)限妖滔。用戶對請求權(quán)限的上下文更加敏感,如果您請求的權(quán)限與應(yīng)用的用途不匹配桶良,則一定要向用戶詳細解釋您為什么請求此權(quán)限座舍;您應(yīng)盡可能在請求時以及后續(xù)對話框中(如果用戶拒絕請求)解釋您的請求。
在授予權(quán)限時更加靈活:用戶可以在收到請求時以及在設(shè)置中拒絕訪問各個權(quán)限艺普,但是當功能因此而中斷時簸州,他們可能仍會感到驚訝鉴竭。最好監(jiān)控有多少用戶拒絕權(quán)限請求(例如歧譬,使用 Google Analytics(分析)),以便重構(gòu)應(yīng)用以避免依賴該權(quán)限搏存,或更好地解釋應(yīng)用需要此權(quán)限才能正常工作的原因瑰步。還應(yīng)確保應(yīng)用可以處理當用戶拒絕權(quán)限請求或在設(shè)置中關(guān)閉權(quán)限時產(chǎn)生的異常。
增加了事務(wù)負擔:系統(tǒng)將要求用戶單獨授予權(quán)限組的訪問權(quán)限璧眠,而不是以集合的形式授予缩焦。這樣一來,最大程度降低請求的權(quán)限數(shù)量就變得非常重要责静,因為數(shù)量多會增加用戶授予權(quán)限的負擔袁滥,并且會增大至少有一個請求被拒絕的概率。
避免請求不必要的權(quán)限
每次您請求某個權(quán)限時灾螃,都是在強迫用戶做出決定题翻。應(yīng)盡量減少提出這些請求的次數(shù)。如果用戶運行的是 Android 6.0(API 級別 23)或更高版本腰鬼,則每次用戶嘗試一些請求權(quán)限的新應(yīng)用功能時嵌赠,應(yīng)用都必須中斷用戶的操作而發(fā)起權(quán)限請求。如果用戶運行的是較低版本的 Android熄赡,則在安裝應(yīng)用時必須授予應(yīng)用每一種權(quán)限姜挺;如果列表過長或看起來不合適,用戶可能會決定根本不安裝應(yīng)用彼硫。因此炊豪,應(yīng)盡量減少應(yīng)用需要的權(quán)限數(shù)量。
本部分提供了常見用例的替代方法拧篮,有助于限制您提出權(quán)限請求的次數(shù)溜在。由于向用戶請求的權(quán)限數(shù)量和類型會影響下載量(與其他請求較少權(quán)限的類似應(yīng)用相比),因此最好避免為不必要的功能請求權(quán)限他托。
改用 intent
在許多情況下掖肋,要讓應(yīng)用執(zhí)行某項任務(wù),有兩種方法供您選擇赏参。應(yīng)用可以要求提供權(quán)限來自行執(zhí)行該任務(wù)志笼,也可以使用 intent 讓其他應(yīng)用執(zhí)行該任務(wù)沿盅。
例如,假設(shè)應(yīng)用需要使用設(shè)備攝像頭才能夠拍攝照片纫溃。應(yīng)用可以請求 CAMERA 權(quán)限腰涧,以便允許應(yīng)用直接訪問攝像頭。然后紊浩,應(yīng)用將使用攝像頭 API 控制攝像頭并拍攝照片窖铡。此方法使應(yīng)用能夠完全控制拍攝過程,并且您可以將攝像頭界面整合到應(yīng)用中坊谁。
不過费彼,如果您很少需要訪問用戶數(shù)據(jù),換句話說口芍,每次您需要訪問數(shù)據(jù)時都向用戶顯示運行時對話框箍铲,這種中斷操作并非不可接受,那么您可以使用基于 intent 的請求鬓椭。Android 提供了一些系統(tǒng) intent颠猴,借助這些 intent,應(yīng)用無需請求權(quán)限小染,因為在發(fā)出基于 intent 的請求時用戶會選擇與應(yīng)用共享的內(nèi)容(如果有)翘瓮。
例如,您可以使用 intent 操作類型 MediaStore.ACTION_IMAGE_CAPTURE 或 MediaStore.ACTION_VIDEO_CAPTURE 來拍攝圖像或視頻裤翩,而無需直接使用 Camera 對象(或請求權(quán)限)资盅。在這種情況下,每次拍攝圖像時岛都,系統(tǒng) intent 都會代表您請求用戶提供權(quán)限律姨。
同樣,如果您需要撥打電話臼疫、訪問用戶的聯(lián)系人或執(zhí)行其他操作择份,您可以通過創(chuàng)建適當?shù)?intent 來完成,也可以直接請求權(quán)限并訪問相應(yīng)的對象烫堤。每種方法各有優(yōu)缺點荣赶。
如果使用權(quán)限:
- 當您執(zhí)行操作時,您的應(yīng)用可以完全控制用戶體驗鸽斟。不過拔创,如此廣泛的控制會增加代碼的復雜性,因為您需要設(shè)計適當?shù)慕缑妗?/li>
- 系統(tǒng)會在運行時或安裝時(具體取決于用戶的 Android 版本)提示用戶授予權(quán)限一次富蓄。之后剩燥,應(yīng)用即可執(zhí)行操作,不再需要用戶進行其他互動。不過灭红,如果用戶未授予權(quán)限(或之后撤消權(quán)限)侣滩,則應(yīng)用將根本無法執(zhí)行操作。
如果使用 intent:
- 您不必為操作設(shè)計界面变擒。處理 intent 的應(yīng)用將提供界面君珠。
- 用戶可以使用他們首選的應(yīng)用執(zhí)行任務(wù)。例如娇斑,用戶可以選擇用他們喜愛的照片應(yīng)用拍照策添。
- 如果用戶沒有適用于操作的默認應(yīng)用,則系統(tǒng)會提示用戶選擇一款應(yīng)用毫缆。如果用戶未指定默認處理程序唯竹,則他們每次執(zhí)行此操作時都可能必須處理一個額外的對話框。
不要讓用戶感到無所適從
如果用戶運行的是 Android 6.0(API 級別 23)或更高版本悔醋,則用戶必須在運行應(yīng)用時為其授予權(quán)限摩窃。如果您讓用戶一次面對大量的權(quán)限請求兽叮,可能會讓用戶感到無所適從芬骄,導致他們退出您的應(yīng)用。您應(yīng)根據(jù)需要請求權(quán)限鹦聪。
在某些情況下账阻,一項或多項權(quán)限可能對您的應(yīng)用來說必不可少。在這種情況下泽本,合理的做法是淘太,在應(yīng)用啟動之后立即請求提供所有這些權(quán)限。例如规丽,如果您創(chuàng)建的是攝影應(yīng)用蒲牧,則該應(yīng)用將需要訪問設(shè)備的攝像頭。當用戶首次啟動該應(yīng)用時赌莺,系統(tǒng)會要求他們提供攝像頭使用權(quán)限冰抢,他們不會對此感到驚訝。但是艘狭,如果同一應(yīng)用還具備與用戶的聯(lián)系人分享照片的功能挎扰,那么您或許不應(yīng)在應(yīng)用首次啟動時請求用戶提供 READ_CONTACTS 權(quán)限,而應(yīng)等到用戶嘗試使用“分享”功能之后再請求該權(quán)限巢音。
如果應(yīng)用提供教程遵倦,則合理的做法是,在教程結(jié)束時請求提供應(yīng)用的必要權(quán)限官撼。
失去音頻焦點后暫停媒體
在這種情況下梧躺,當用戶接電話時,您的應(yīng)用需要轉(zhuǎn)入后臺傲绣,只有在通話停止后才會重新獲得焦點掠哥。
出現(xiàn)此類情況(例如棘脐,媒體播放器在通話期間靜音或暫停)時,通常采用的方法是使用 PhoneStateListener
或監(jiān)聽 android.intent.action.PHONE_STATE
的廣播龙致,以監(jiān)聽通話狀態(tài)有無變化蛀缝。這種解決方法的問題是它需要 READ_PHONE_STATE
權(quán)限,這將強制用戶授予對廣泛的敏感數(shù)據(jù)(如用戶的設(shè)備和 SIM 硬件 ID 以及來電的電話號碼)的訪問權(quán)限目代。
您可以通過為應(yīng)用請求 AudioFocus
屈梁,在沒有 READ_PHONE_STATE
或 MODIFY_PHONE_STATE
權(quán)限的情況下檢測用戶是否在通話中,這么做不需要顯式權(quán)限榛了,因為它不訪問敏感信息在讶。只需將對音頻放入后臺所需的代碼放入onAudioFocusChange() 事件處理程序,當操作系統(tǒng)轉(zhuǎn)換其音頻焦點時霜大,它將自動運行构哺。要詳細了解如何執(zhí)行此操作,請參閱此文檔战坤。
確定正在運行實例的設(shè)備
在這種情況下曙强,您需要一個唯一標識符來確定您的應(yīng)用實例正在哪個設(shè)備上運行。
應(yīng)用可能具有設(shè)備特定的偏好設(shè)置或消息(例如途茫,在云端為用戶保存設(shè)備特定的播放列表碟嘴,以便他們在車上和家里可以有不同的播放列表)。常見的解決方案是利用設(shè)備標識符(如 Device IMEI
)囊卜,但這需要 Device ID and call information
權(quán)限組(M+ 中為 PHONE
)娜扇。它還使用一個無法重置且在所有應(yīng)用之間共享的標識符。
下面兩種方法可以替代這些類型的標識符:
- 使用
com.google.android.gms.iid
InstanceID API栅组。getInstance(Context context).getID()
將為您的應(yīng)用實例返回一個唯一設(shè)備標識符雀瓢。結(jié)果是一個應(yīng)用實例作用域標識符,在存儲有關(guān)應(yīng)用的信息時玉掸,該標識符可用作鍵刃麸,如果用戶重新安裝應(yīng)用,該標識符會重置排截。 - 使用
randomUUID()
之類的基本系統(tǒng)函數(shù)創(chuàng)建您自己的標識符嫌蚤,其作用域限定為應(yīng)用的存儲空間。
為廣告或用戶分析創(chuàng)建唯一標識符
在這種情況下断傲,您需要一個唯一標識符來為沒有登錄您應(yīng)用的用戶構(gòu)建配置文件(例如脱吱,用于廣告定位或衡量轉(zhuǎn)化率)。
為廣告和用戶分析構(gòu)建配置文件有時需要一個在其他應(yīng)用之間共享的標識符认罩。此問題的常見解決方案需要利用設(shè)備標識符(如 Device IMEI
)箱蝠,這需要 Device ID
and call information
權(quán)限組(API 級別 23+ 中為 PHONE
),并且無法由用戶重置。無論是上述哪種情況宦搬,除了使用不可重置的標識符并請求用戶可能認為不尋常的權(quán)限外牙瓢,還會違反 Play 開發(fā)者計劃政策。
遺憾的是间校,在這些情況下矾克,使用 com.google.android.gms.iid
InstanceID API 或系統(tǒng)函數(shù)創(chuàng)建應(yīng)用作用域 ID 并不是適當?shù)慕鉀Q方案,因為可能需要在應(yīng)用之間共享該 ID憔足。一種替代解決方案是使用通過 getId()
方法從AdvertisingIdClient.Info 類中獲取的 Advertising Identifier
胁附。您可以使用 getAdvertisingIdInfo(Context)
方法創(chuàng)建一個 AdvertisingIdClient.Info
對象,并調(diào)用 getId()
方法來使用該標識符滓彰。請注意控妻,此方法會產(chǎn)生阻塞,因此揭绑,您不應(yīng)從主線程調(diào)用它弓候;有關(guān)此方法的詳細說明,請點擊此處他匪。
了解您正在使用的庫
有時菇存,您在應(yīng)用中使用的庫需要一些權(quán)限。例如诚纸,廣告和分析庫可能需要訪問 Location
或 Identity
權(quán)限組以實現(xiàn)必需的功能撰筷。但從用戶的角度來看陈惰,權(quán)限請求來自于您的應(yīng)用畦徘,而不是庫。
就像用戶會選擇使用較少權(quán)限即可實現(xiàn)相同功能的應(yīng)用一樣抬闯,開發(fā)者也應(yīng)檢查他們的庫井辆,并選擇不會使用非必要權(quán)限的第三方 SDK。例如溶握,設(shè)法避免使用需要 Identity
權(quán)限組的庫杯缺,除非可以清楚地向用戶解釋應(yīng)用為什么需要這些權(quán)限。尤其是對于提供位置功能的庫睡榆,請確保您不需要請求 FINE_LOCATION
權(quán)限萍肆,除非您正在使用基于位置的定位功能。
解釋為何需要權(quán)限
系統(tǒng)在您調(diào)用 requestPermissions()
時顯示的權(quán)限對話框?qū)⒄f明應(yīng)用需要哪些權(quán)限胀屿,但不會解釋為何需要這些權(quán)限塘揣。在某些情況下,用戶可能會感到困惑宿崭。最好在調(diào)用 requestPermissions()
之前向用戶解釋應(yīng)用需要相應(yīng)權(quán)限的原因亲铡。
研究表明舌狗,如果用戶知道應(yīng)用需要相應(yīng)權(quán)限的原因,他們會更容易接受權(quán)限請求缨历。用戶研究表明:
…用戶是否愿意為某個移動應(yīng)用授予給定權(quán)限揪罕,在很大程度上受此類權(quán)限關(guān)聯(lián)用途的影響。例如吆鹤,用戶是否愿意授予訪問其位置的權(quán)限取決于該權(quán)限請求是否為支持應(yīng)用的核心功能所必需厨疙,或者應(yīng)用是否將與廣告網(wǎng)絡(luò)或分析公司分享此信息。1
卡內(nèi)基梅隆大學 (CMU) 的 Jason Hong 教授根據(jù)他所帶領(lǐng)的小組的研究成果得出一個一般結(jié)論:
…與只是告訴用戶應(yīng)用正在使用其位置相比疑务,如果用戶知道應(yīng)用為什么使用像他們的位置這樣敏感的信息(例如轰异,用于定向廣告),那么用戶會更容易接受暑始。1
因此搭独,如果您僅使用歸入權(quán)限組的一小部分 API 調(diào)用,明確列出您使用哪些權(quán)限以及使用原因會非常有用廊镜。例如:
- 如果您僅使用粗略位置牙肝,請在應(yīng)用說明或應(yīng)用的幫助文檔中告知用戶。
- 如果您需要訪問短信以接收身份驗證碼嗤朴,從而防止用戶被欺詐配椭,請在應(yīng)用說明和/或首次訪問數(shù)據(jù)時告知用戶。
注意:如果應(yīng)用面向 Android 8.0(API 級別 26)或更高版本雹姊,請不要在驗證用戶憑據(jù)過程中請求 READ_SMS 權(quán)限股缸,而應(yīng)使用
createAppSpecificSmsToken()
生成應(yīng)用特定的令牌,然后將此令牌傳遞給可以發(fā)送驗證短信的其他應(yīng)用或服務(wù)吱雏。
在特定條件下敦姻,讓用戶實時了解應(yīng)用在訪問敏感數(shù)據(jù)也是非常有益的。例如歧杏,如果應(yīng)用在訪問攝像頭或麥克風镰惦,通常最好在應(yīng)用中的某個位置或在通知托盤中(如果應(yīng)用正在后臺運行)使用通知圖標告知用戶,這樣不會讓您看起來像是在偷偷地收集數(shù)據(jù)犬绒。
最后旺入,如果您需要請求權(quán)限以便在應(yīng)用中運行某項功能,但用戶不清楚原因凯力,則需要找到一種方法讓用戶知道您為什么需要最敏感的權(quán)限茵瘾。
測試兩種權(quán)限模式
自 Android 6.0(API 級別 23)起,用戶是在運行時(而不是在安裝應(yīng)用時)授予和撤消應(yīng)用權(quán)限咐鹤。因此拗秘,您必須在多種不同條件下測試應(yīng)用。在低于 Android 6.0 的版本中慷暂,您可以合理地認為聘殖,如果應(yīng)用能運行晨雳,它就已經(jīng)獲得在應(yīng)用清單中聲明的全部權(quán)限。自 Android 6.0 起奸腺,用戶可以開啟或關(guān)閉任何應(yīng)用的權(quán)限餐禁,即使面向 API 級別 22 或更低級別的應(yīng)用也是如此。您應(yīng)測試以確保您的應(yīng)用能正常運行突照,無論它是否具有任何權(quán)限帮非。
以下提示可幫助您在運行 API 級別 23 或更高級別的設(shè)備上找出與權(quán)限有關(guān)的代碼問題:
- 確定應(yīng)用的當前權(quán)限和相關(guān)的代碼路徑。
- 在各種受權(quán)限保護的服務(wù)和數(shù)據(jù)中測試用戶流讹蘑。
- 使用授予或撤消權(quán)限的各種組合進行測試末盔。例如,相機應(yīng)用可能會在其清單中列出 CAMERA座慰、READ_CONTACTS和 ACCESS_FINE_LOCATION陨舱。您應(yīng)在測試應(yīng)用時逐一開啟和關(guān)閉這些權(quán)限,確保應(yīng)用可以妥善處理所有權(quán)限配置版仔。
- 使用 adb 工具從命令行管理權(quán)限:
- 按組列出權(quán)限和狀態(tài):
$ adb shell pm list permissions -d -g
- 授予或撤消一項或多項權(quán)限:
$ adb shell pm [grant|revoke] <permission-name> ...
- 針對使用權(quán)限的服務(wù)對應(yīng)用進行分析游盲。
其他資源
- Android 權(quán)限的 Material Design 準則
- Android Marshmallow 6.0:請求權(quán)限 - 此視頻介紹了 Android 運行時權(quán)限模式以及請求用戶提供權(quán)限的正確方法。
- 解釋應(yīng)用為什么需要權(quán)限
- 唯一標識符最佳做法