本文為菜鳥(niǎo)窩作者蔣志碧的連載乳幸∨缕罚“從 0 開(kāi)始開(kāi)發(fā)一款直播 APP ”系列來(lái)聊聊時(shí)下最火的直播 APP治笨,如何完整的實(shí)現(xiàn)一個(gè)類(lèi)"騰訊直播"的商業(yè)化項(xiàng)目
一考婴、前言
Android 6.0 版本(Api 23) 及其以上系統(tǒng)引入運(yùn)行時(shí)權(quán)限 — 默認(rèn)所有涉及用戶(hù)隱私的權(quán)限都被關(guān)閉,我們?cè)?AndroidManifest.xml 中申請(qǐng)權(quán)限之后杆麸,依然還需要?jiǎng)討B(tài)申請(qǐng)權(quán)限搁进,不然每次安裝完APP后,就需要在「設(shè)置 -> 應(yīng)用 -> APP」中打開(kāi)所需權(quán)限昔头。
Android 系統(tǒng)包含默認(rèn)的授權(quán)提示框饼问,但是仍需要我們?cè)O(shè)置自己的頁(yè)面,原因的系統(tǒng)提供的授權(quán)框會(huì)有不再提示選項(xiàng)揭斧。如果用戶(hù)選擇莱革,則無(wú)法觸發(fā)授權(quán)提示峻堰,使用自定義的提示頁(yè)面,可以給予用戶(hù)手動(dòng)修改授權(quán)的指導(dǎo)盅视。
統(tǒng)一授權(quán)
如果設(shè)備運(yùn)行的是 Android 5.1(API 級(jí)別 22)或更低版本捐名,并且應(yīng)用的 targetSdkVersion 是 22 或更低版本,則系統(tǒng)會(huì)在用戶(hù)安裝應(yīng)用時(shí)要求用戶(hù)授予權(quán)限闹击。如果將新權(quán)限添加到更新的應(yīng)用版本镶蹋,系統(tǒng)會(huì)在用戶(hù)更新應(yīng)用時(shí)要求授予該權(quán)限。用戶(hù)一旦安裝應(yīng)用赏半,他們撤銷(xiāo)權(quán)限的唯一方式是卸載應(yīng)用贺归。
運(yùn)行時(shí)權(quán)限
如果設(shè)備運(yùn)行的是 Android 6.0(API 級(jí)別 23)或更高版本,并且應(yīng)用的 targetSdkVersion 是 23 或更高版本断箫,則應(yīng)用在運(yùn)行時(shí)向用戶(hù)請(qǐng)求權(quán)限拂酣。用戶(hù)可隨時(shí)調(diào)用權(quán)限,因此應(yīng)用在每次運(yùn)行時(shí)均需檢查自身是否具備所需的權(quán)限仲义。
二婶熬、權(quán)限分組
Android 6.0 引入運(yùn)行時(shí)權(quán)限,所有權(quán)限仍然需要在 AndroidManifest 中聲明光坝,但是當(dāng)訪問(wèn)需要的權(quán)限時(shí),活動(dòng)或片段必須驗(yàn)證權(quán)限已被授予或使用支持庫(kù)的調(diào)用請(qǐng)求缺少的權(quán)限甥材。
權(quán)限分為三類(lèi):
正常(Normal Protection)權(quán)限
危險(xiǎn)(Dangerous)權(quán)限
特殊(Particular)權(quán)限
其它權(quán)限(一般很少用到)
正常權(quán)限
「正常權(quán)限」涵蓋應(yīng)用需要訪問(wèn)其沙盒外部數(shù)據(jù)或資源盯另,但對(duì)用戶(hù)隱私或其他應(yīng)用操作風(fēng)險(xiǎn)很小的區(qū)域。例如洲赵,設(shè)置時(shí)區(qū)的權(quán)限就是正常權(quán)限鸳惯。如果應(yīng)用聲明其需要正常權(quán)限,系統(tǒng)會(huì)自動(dòng)向應(yīng)用授予該權(quán)限叠萍。
正常權(quán)限具有如下特點(diǎn)
1芝发、對(duì)用戶(hù)隱私?jīng)]用較大影響或者不會(huì)帶來(lái)安全問(wèn)題
2、安裝之后就被賦予這些權(quán)限苛谷,不需要顯示提醒用戶(hù)辅鲸,用戶(hù)也不能取消這些權(quán)限
危險(xiǎn)權(quán)限
危險(xiǎn)權(quán)限涵蓋應(yīng)用需要涉及用戶(hù)隱私信息的數(shù)據(jù)或資源,或者可能對(duì)用戶(hù)存儲(chǔ)的數(shù)據(jù)或其他應(yīng)用的操作產(chǎn)生影響的區(qū)域腹殿。例如独悴,能夠讀取用戶(hù)的聯(lián)系人屬于危險(xiǎn)權(quán)限。如果應(yīng)用聲明其需要危險(xiǎn)權(quán)限锣尉,則用戶(hù)必須明確向應(yīng)用授予該權(quán)限刻炒。
權(quán)限組
所有危險(xiǎn)的 Android 系統(tǒng)權(quán)限都屬于權(quán)限組。如果設(shè)備運(yùn)行的是 Android 6.0(API 級(jí)別 23)自沧,并且應(yīng)用的 targetSdkVersion是 23 或更高版本坟奥,則當(dāng)用戶(hù)請(qǐng)求危險(xiǎn)權(quán)限時(shí)系統(tǒng)會(huì)發(fā)生以下行為:
如果應(yīng)用請(qǐng)求其清單中列出的危險(xiǎn)權(quán)限,而應(yīng)用目前在權(quán)限組中沒(méi)有任何權(quán)限,則系統(tǒng)會(huì)向用戶(hù)顯示一個(gè)對(duì)話框爱谁,描述應(yīng)用要訪問(wèn)的權(quán)限組晒喷。對(duì)話框不描述該組內(nèi)的具體權(quán)限。例如管行,如果應(yīng)用請(qǐng)求 READ_CONTACTS 權(quán)限厨埋,系統(tǒng)對(duì)話框只說(shuō)明該應(yīng)用需要訪問(wèn)設(shè)備的聯(lián)系信息。如果用戶(hù)批準(zhǔn)捐顷,系統(tǒng)將向應(yīng)用授予其請(qǐng)求的權(quán)限荡陷。
如果應(yīng)用請(qǐng)求其清單中列出的危險(xiǎn)權(quán)限,而應(yīng)用在同一權(quán)限組中已有另一項(xiàng)危險(xiǎn)權(quán)限迅涮,則系統(tǒng)會(huì)立即授予該權(quán)限废赞,而無(wú)需與用戶(hù)進(jìn)行任何交互。例如叮姑,如果某應(yīng)用已經(jīng)請(qǐng)求并且被授予了 READ_CONTACTS 權(quán)限唉地,然后它又請(qǐng)求 WRITE_CONTACTS,系統(tǒng)將立即授予該權(quán)限传透。
任何權(quán)限都可屬于一個(gè)權(quán)限組,包括正常權(quán)限和應(yīng)用定義的權(quán)限朱盐。但權(quán)限組僅當(dāng)權(quán)限危險(xiǎn)時(shí)才影響用戶(hù)體驗(yàn)群嗤。可以忽略正常權(quán)限的權(quán)限組兵琳。
如果設(shè)備運(yùn)行的是 Android 5.1(API 級(jí)別 22)或更低版本狂秘,并且應(yīng)用的 targetSdkVersion 是 22 或更低版本,則系統(tǒng)會(huì)在安裝時(shí)要求用戶(hù)授予權(quán)限躯肌。再次強(qiáng)調(diào)者春,系統(tǒng)只告訴用戶(hù)應(yīng)用需要的權(quán)限組,而不告知具體權(quán)限清女。
特殊權(quán)限
有許多權(quán)限其行為方式與正常權(quán)限及危險(xiǎn)權(quán)限都不同钱烟。SYSTEM_ALERT_WINDOW 和 WRITE_SETTINGS 特別敏感,因此大多數(shù)應(yīng)用不應(yīng)該使用它們嫡丙。如果某應(yīng)用需要其中一種權(quán)限忠售,必須在清單中聲明該權(quán)限,并且發(fā)送請(qǐng)求用戶(hù)授權(quán)的 intent迄沫。系統(tǒng)將向用戶(hù)顯示詳細(xì)管理屏幕稻扬,以響應(yīng)該 intent。
SYSTEM_ALERT_WINDOW 設(shè)置懸浮窗
WRITE_SETTINGS 修改系統(tǒng)設(shè)置
SYSTEM_ALERT_WINDOW
允許應(yīng)用使用類(lèi)型 TYPE_APPLICATION_OVERLAY 創(chuàng)建窗口羊瘩,該窗口顯示在所有其他應(yīng)用程序的頂端泰佳。極少的應(yīng)用程序應(yīng)該使用這個(gè)權(quán)限盼砍,這些窗口用于與用戶(hù)的系統(tǒng)級(jí)交互。
Note:如果是 API 23 及其以上版本逝她,用戶(hù)必須通過(guò)權(quán)限管理向應(yīng)用程顯示權(quán)限浇坐。 應(yīng)用程序通過(guò)發(fā)送 ACTION_MANAGE_OVERLAY_PERMISSION action 的隱式 intent 請(qǐng)求用戶(hù)的批準(zhǔn)。 該應(yīng)用程序可以通過(guò)調(diào)用 Settings.canDrawOverlays() 來(lái)檢查是否具有此授權(quán)黔宛。
請(qǐng)求 SYSTEM_ALERT_WINDOW 權(quán)限
private static final int REQUEST_CODE_SYSTEM_ALERT_WINDOW = 1;
private void requestAlertWindowPermission() {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_SYSTEM_ALERT_WINDOW);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_SYSTEM_ALERT_WINDOW) {
if (Settings.canDrawOverlays(this)) {
Log.i(TAG, "ACTION_MANAGE_OVERLAY_PERMISSION granted");
}
}
}
注意:
使用 Action 的 Settings.ACTION_MANAGE_OVERLAY_PERMISSION 啟動(dòng)隱式 Intent近刘。
使用 "package:" + getPackageName() 攜帶 APP 包名信息
使用 Settings.canDrawOverlays(this) 判斷授權(quán)結(jié)果
WRITE_SETTINGS
允許應(yīng)用程序讀取或?qū)懭胂到y(tǒng)設(shè)置。
Note:如果是 API 23 及其以上版本臀晃,則用戶(hù)必須通過(guò)權(quán)限管理向應(yīng)用程序顯式授予該權(quán)限觉渴。 應(yīng)用程序通過(guò)發(fā)送 ACTION_MANAGE_WRITE_SETTINGS 的 action 的隱式 Intent 來(lái)請(qǐng)求用戶(hù)的批準(zhǔn)。 該應(yīng)用程序可以通過(guò)調(diào)用 Settings.System.canWrite() 來(lái)檢查是否具有此授權(quán)徽惋。
請(qǐng)求 WRITE_SETTINGS 權(quán)限
private static final int REQUEST_CODE_WRITE_SETTINGS = 2;
private void requestWriteSettings() {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS );
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_WRITE_SETTINGS) {
if (Settings.System.canWrite(this)) {
Log.i(LOGTAG, "WRITE_SETTINGS granted" );
}
}
}
注意:
使用 Action 的 Settings.ACTION_MANAGE_WRITE_SETTINGS 啟動(dòng)隱式 Intent案淋。
使用 "package:" + getPackageName() 攜帶 APP 包名信息
使用 Settings.canDrawOverlays(this) 判斷授權(quán)結(jié)果
關(guān)于這兩個(gè)特殊權(quán)限,一般不建議應(yīng)用申請(qǐng)险绘。
三踢京、申請(qǐng)權(quán)限的主要方法
Android 6.0 運(yùn)行時(shí)權(quán)限申請(qǐng)位于 package android.support.v4.app 包中。主要方法有三個(gè):
**1宦棺、權(quán)限通過(guò) ActivityCompat 類(lèi)的 checkSelfPermission() 方法判斷是否有所需權(quán)限瓣距。
**
**2、權(quán)限請(qǐng)求是通過(guò) ActivityCompat 類(lèi)中的 requestPermissions() 方法代咸,在OnRequestPermissionsResultCallback # onRequestPermissionsResult() 方法中回調(diào)蹈丸。
**
3、應(yīng)用程序可以提供一個(gè)額外的合理的使用權(quán)限調(diào)用 Activitycompat # shouldShowRequestPermissionRationale() 方法侣背。Android 原生系統(tǒng)中白华,如果第二次彈出權(quán)限申請(qǐng)的對(duì)話框慨默,會(huì)出現(xiàn)「以后不再?gòu)棾觥沟奶崾究蚍纺停绻脩?hù)勾選了,你再申請(qǐng)權(quán)限厦取,則 shouldShowRequestPermissionRationale() 返回 true潮太,意思是說(shuō)要給用戶(hù)一個(gè)解釋?zhuān)嬖V用戶(hù)為什么要這個(gè)權(quán)限。
四虾攻、運(yùn)行時(shí)權(quán)限示例
以照相機(jī)權(quán)限為例铡买。
1、在 AndroidManifest.xml 文件中申請(qǐng)所需要的權(quán)限霎箍。
<uses-permission android:name="android.permission.CAMERA"/>
2奇钞、在 gradle 中修改 targetSdkVersion 大于或等于 23。
3漂坏、開(kāi)始申請(qǐng)權(quán)限景埃。
權(quán)限檢查
PublishPresenter.java # checkPublishPermission()
@Override
public boolean checkPublishPermission(Activity activity) {
//1媒至、ActivityCompat.checkSelfPermission() 判斷權(quán)限
if (Build.VERSION.SDK_INT >= 23) {
List<String> permissions = new ArrayList<>();
if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA)) {
permissions.add(Manifest.permission.CAMERA);
}
//2、ActivityCompat.requestPermissions() 申請(qǐng)權(quán)限
if (permissions.size() != 0) {
ActivityCompat.requestPermissions(activity
, permissions.toArray(new String[0]),
Constants.WRITE_PERMISSION_REQ_CODE);
return false;
}
}
return true;
}
方法回調(diào)
PublishActivity.java # onRequestPermissionsResult()
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case Constants.WRITE_PERMISSION_REQ_CODE:
for (int ret:grantResults){
if (ret != PackageManager.PERMISSION_GRANTED){
return;
}
}
mPermission = true;
break;
default:
break;
}
}
五谷徙、運(yùn)行效果
當(dāng)進(jìn)入該界面拒啰,系統(tǒng)就會(huì)判斷是否具有照相機(jī)權(quán)限,沒(méi)有則會(huì)彈出對(duì)話框提示用戶(hù)添加權(quán)限完慧。
詳情請(qǐng)轉(zhuǎn)至 GitHub
參考:
http://www.what21.com/article/a_3_1483187432030.html
http://droidyue.com/blog/2016/01/17/understanding-marshmallow-runtime-permission/
https://developer.android.com/guide/topics/security/permissions.html?hl=zh-cn#normal-dangerous
擼這個(gè)項(xiàng)目的一半谋旦,你就是大神 , 戳http://mp.weixin.qq.com/s/ZagocTlDfxZpC2IjUSFhHg