Android-6.0 棉花糖權(quán)限的那點(diǎn)事

Android6.0引入了全新的權(quán)限管理方式,也就是運(yùn)行時權(quán)限围段,至于什么是運(yùn)行時權(quán)限顾翼,我們先看一下6.0以前的權(quán)限處理。

6.0以前的權(quán)限

6.0以前的系統(tǒng)奈泪,我們在安裝一個應(yīng)用的時候會默認(rèn)賦予所有權(quán)限适贸。

pre-marshmallow-permission.jpg

安裝的時候會提示應(yīng)用需要獲取的所有權(quán)限难菌,選擇安裝則會全部獲取刽锤,如果要拒絕獲取權(quán)限,只能放棄安裝應(yīng)用贴汪。用戶無法選擇獲取或者放棄某些權(quán)限冯遂。

6.0的運(yùn)行時權(quán)限

什么是運(yùn)行時權(quán)限蕊肥?舉個栗子,以某個需要拍照的應(yīng)用為例蛤肌,當(dāng)運(yùn)行時權(quán)限生效時壁却,其Camera權(quán)限不是在安裝后賦予批狱,而是在應(yīng)用運(yùn)行的時候進(jìn)行請求權(quán)限(比如當(dāng)用戶按下”相機(jī)拍照“按鈕后)看到的效果則是這樣的,提示用戶需要權(quán)限展东,用戶選擇允許赔硫,才能獲取到該權(quán)限。

marshmallow-permission.png

一個問題:我們必須要支持運(yùn)行時權(quán)限嗎盐肃?

如果我們不想啟用運(yùn)行時權(quán)限其實很簡單爪膊,我們只要,把targetSdkVersion設(shè)置為設(shè)置低于23就可以了恼蓬,系統(tǒng)會認(rèn)為我們的應(yīng)用還不支持新特性惊完,會按照棉花糖以前的版本進(jìn)行處理。這樣的處理不會有任何的問題处硬,但有一點(diǎn)小槐,棉花糖對每一個應(yīng)用都有一個權(quán)限管理界面,是這樣

6a195423jw1ezwqnmjhcdj20u01hc40k.jpg

如果用戶手動關(guān)閉了我們應(yīng)用的某些權(quán)限荷辕,問題就出現(xiàn)了凿跳,運(yùn)行應(yīng)用時可能會出現(xiàn)崩潰。下面這個例子

TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String deviceId = telephonyManager.getDeviceId();
if (deviceId.equals(mLastDeviceId)) {//This may cause NPE
//do something
}

如果用戶撤消了獲取DeviceId的權(quán)限疮方,那么再次運(yùn)行時,deviceId就是null控嗜,如果程序后續(xù)處理不當(dāng),就會出現(xiàn)崩潰骡显。所以說該來的還是要來的疆栏,我們需要處理好運(yùn)行時權(quán)限問題。

權(quán)限分類

android系統(tǒng)的權(quán)限很多但不是所有的權(quán)限都是敏感權(quán)限惫谤,棉花糖將android系統(tǒng)權(quán)限分為四類壁顶。

1.正常權(quán)限(Normal Protection)

2.危險權(quán)限(Dangerous)

3.特殊權(quán)限(Particular)

4.其他權(quán)限(幾乎使用不到)

1.正常權(quán)限

這一類權(quán)限是對用戶隱私影響較小,沒有什么安全問題溜歪,這類權(quán)限會像6.0以前的系統(tǒng)一樣若专,安裝就獲取到這些權(quán)限,沒有用戶提醒蝴猪,也不能被取消调衰。下面是正常權(quán)限列表。

ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_INSTALL_PACKAGES
SET_TIME_ZONE
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
SET_ALARM
INSTALL_SHORTCUT
UNINSTALL_SHORTCUT

對于這些權(quán)限自阱,我們只需要在Manifest中指定嚎莉,應(yīng)用安裝就會獲取。

2.危險權(quán)限

危險權(quán)限才是運(yùn)行時權(quán)限的主要處理對象沛豌,這些權(quán)限可能會有隱私問題萝喘,或者影響其他應(yīng)用的運(yùn)行,危險權(quán)限可以分為以下幾組:

  • CALENDAR
  • CAMERA
  • CONTACTS
  • LOCATION
  • MICROPHONE
  • PHONE
  • SENSORS
  • SMS
  • STORAGE

對于各組權(quán)限對應(yīng)的具體權(quán)限如下:

6a195423jw1ezwpc11cs0j20hr0majwm.jpg

關(guān)于權(quán)限我們需要下面幾個API

  • int checkSelfPermission(String permission) 用來檢測應(yīng)用是否已經(jīng)具有權(quán)限
  • void requestPermissions(String[] permissions, int requestCode) 進(jìn)行請求單個或多個權(quán)限
  • void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)

請求Camera的權(quán)限

private static final int REQUEST_PERMISSION_CAMERA_CODE = 1;
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!(checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
Toast.makeText(this, "Please grant the permission this time", Toast.LENGTH_LONG).show();
}
requestCameraPermission();
}
}
}
private void requestCameraPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_PERMISSION_CAMERA_CODE);
}
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CAMERA_CODE) {
int grantResult = grantResults[0];
boolean granted = grantResult == PackageManager.PERMISSION_GRANTED;
Log.i(LOGTAG, "onRequestPermissionsResult granted=" + granted);
}
}

通常情況下,我們會得到這樣的一個對話框

marshmallow-permission.png

我們可以在onRequestPermissionsResult中獲取用戶的選擇情況進(jìn)行相應(yīng)的處理阁簸。但如果用戶選擇了否爬早,我們再次申請的時候就會多一個checkbox

6a195423jw1ezwtz1ljjgj20u01hcad8.jpg

如果用戶選擇了不在詢問,然后拒絕启妹,我們的應(yīng)用基本上就獲取不到這個權(quán)限了筛严,shouldShowRequestPermissionRationale這個API可以幫我們判斷接下來的對話框是否包含”不再詢問“選擇框,我們可以這樣使用饶米。這樣如果我們第一次申請權(quán)限失敗后桨啃,在申請權(quán)限的時候就會彈出提示Toast,這個使用一定要向用戶說明我們?yōu)槭裁匆暾堖@個權(quán)限檬输,來做什么照瘾。

if (!(checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED)) {
if (shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) {
Toast.makeText(this, "Please grant the permission this time", Toast.LENGTH_LONG).show();
}
requestReadContactsPermission();
} else {
Log.i(LOGTAG, "onClick granted");
}

對于同時申請多個權(quán)限我們可以

String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE};
requestPermissions(permissions, REQUEST_CODE);

效果是這樣,同時申請多個權(quán)限可以避免彈出多個對話框造成不好的視覺影響丧慈。

6a195423jw1ezxulzbeu2j20iq0ggt9y.jpg

3.特殊權(quán)限

特殊權(quán)限是指特別敏感的權(quán)限析命,這里主要是指兩個。

SYSTEM_ALERT_WINDOW逃默,設(shè)置懸浮窗

WRITE_SETTINGS 修改系統(tǒng)設(shè)置

關(guān)于上面兩個特殊權(quán)限的授權(quán)鹃愤,做法是使用startActivityForResult啟動授權(quán)界面來完成,下面是請求SYSTEM_ALERT_WINDOW權(quán)限完域。

private static final int REQUEST_CODE = 1;
private void requestAlertWindowPermission() {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
Log.i("AlertWindowPermission", "onActivityResult granted");
}
}
}
}

需要注意:

  • 使用Action Settings.ACTION_MANAGE_OVERLAY_PERMISSION啟動隱式Intent
  • 使用"package:" + getPackageName()攜帶App的包名信息
  • 使用Settings.canDrawOverlays方法判斷授權(quán)結(jié)果

WRITE_SETTINGS 使用的則是 Action Settings.ACTION_MANAGE_WRITE_SETTINGS软吐,使用Settings.System.canWrite方法檢測授權(quán)結(jié)果

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市吟税,隨后出現(xiàn)的幾起案子凹耙,更是在濱河造成了極大的恐慌,老刑警劉巖肠仪,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件使兔,死亡現(xiàn)場離奇詭異,居然都是意外死亡藤韵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門熊经,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泽艘,“玉大人,你說我怎么就攤上這事镐依∑ヤ蹋” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵槐壳,是天一觀的道長然低。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么雳攘? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任带兜,我火速辦了婚禮,結(jié)果婚禮上吨灭,老公的妹妹穿的比我還像新娘刚照。我一直安慰自己,他們只是感情好喧兄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布无畔。 她就那樣靜靜地躺著,像睡著了一般吠冤。 火紅的嫁衣襯著肌膚如雪浑彰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天拯辙,我揣著相機(jī)與錄音郭变,去河邊找鬼。 笑死薄风,一個胖子當(dāng)著我的面吹牛饵较,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播遭赂,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼循诉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了撇他?” 一聲冷哼從身側(cè)響起茄猫,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎困肩,沒想到半個月后划纽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锌畸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年勇劣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潭枣。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡比默,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盆犁,到底是詐尸還是另有隱情命咐,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布谐岁,位于F島的核電站醋奠,受9級特大地震影響榛臼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜窜司,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一沛善、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧例证,春花似錦路呜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至笙蒙,卻和暖如春抵屿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捅位。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工轧葛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人艇搀。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓尿扯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親焰雕。 傳聞我的和親對象是個殘疾皇子衷笋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

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