Android 6.0系統(tǒng)中權(quán)限問題調(diào)用 - Permission in Android M

安卓平臺權(quán)限一直有被流氓應(yīng)用隨便利用詬病, android M的發(fā)布徹底解決了這一問題,取而代之的是,app不得不在運行時一個一個詢問用戶授予權(quán)限侣颂。

Android 6.0(api23)系統(tǒng)中,做了一些限制, 開發(fā)者在使用到每條權(quán)限時必須自己調(diào)用相關(guān)代碼請求.

如果沒有獲得某項權(quán)限,直接使用相關(guān)功能,則會導(dǎo)致自己程序crash.

見log

可見6.0以后的系統(tǒng)開發(fā)者必須對權(quán)限適配,否則軟件隨時都可能奔潰,那么問題來了~

已經(jīng)發(fā)出去的版本或是targetSdkVersion小與23的apk怎么辦?

廢話,當(dāng)然會崩了!!!

只要在滿足在Android M上直接使用為授權(quán)的功能每庆,程序必須Crash. targetSdkVersion<23的應(yīng)用在安裝時系統(tǒng)會默認(rèn)全部授權(quán)應(yīng)用在manifest中申請的權(quán)限哪痰,

不要應(yīng)用這樣你的應(yīng)用就完事大全了.用戶可以在以下頁面或是其他應(yīng)用關(guān)閉相關(guān)權(quán)限泽论,然后…你的應(yīng)用就沒有然后了~

關(guān)閉權(quán)限頁


Android M 權(quán)限分類

安卓系統(tǒng)把權(quán)限分為了三類:

Normal Permissions

Dangerous Permissions

Special Permissions

Normal Permissions-一般權(quán)限

一般權(quán)限都是一些系統(tǒng)認(rèn)為比較權(quán)限的權(quán)限夺蛇,流氓應(yīng)用就是擁有這些權(quán)限也干不出多大壞事步做,Normal 權(quán)限會在應(yīng)用安裝是直接授權(quán)副渴,

官網(wǎng)解釋:權(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

FLASHLIGHT

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

Dangerous Permissions-危險權(quán)限

這些權(quán)限都是一些敏感性權(quán)限,一些廣告平臺或是流氓應(yīng)用會用這些權(quán)限干一些壞壞的事情全度,因此系統(tǒng)將這類權(quán)限分了幾個類別煮剧,

應(yīng)用每次都要檢測下是否有權(quán)限,沒有的化必須彈出對話框申請讼载,只要一個組別中的一個權(quán)限得到了授權(quán)轿秧,整個組的權(quán)限都會的到授權(quán).

這部分權(quán)限也是我們重點在M系統(tǒng)上關(guān)注和適配的部分.

官網(wǎng)權(quán)威說明, 具體相關(guān)權(quán)限見圖:

Dangerous Permission


Special Permissions- 特殊權(quán)限

SYSTEM_ALERT_WINDOW and WRITE_SETTINGS, 這兩個權(quán)限比較特殊,不能通過代碼申請方式獲取咨堤,必須得用戶打開軟件設(shè)置頁手動打開菇篡,才能授權(quán).

There are a couple of permissions that don’t behave like normal and dangerous permissions. SYSTEM_ALERT_WINDOW and WRITE_SETTINGS are particularly sensitive, so most apps should not use them. If an app needs one of these permissions, it must declare the permission in the manifest, and send an intent requesting the user’s authorization. The system responds to the intent by showing a detailed management screen to the user.

特殊權(quán)限官網(wǎng)推薦用法

實戰(zhàn)Android m權(quán)限申請用法

我們對相關(guān)申請方法封裝成了工具類,方便m系統(tǒng)適配隨時調(diào)用.

相關(guān)配置

compileSdkVersion and targetSdkVersion 設(shè)置為 23開始

調(diào)用相關(guān)權(quán)限

private void testAlertPermission() {

WindowManager mWindowManager = (WindowManager) getSystemService(

Context.WINDOW_SERVICE);

WindowManager.LayoutParams params = new WindowManager.LayoutParams();

params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;

mWindowManager.addView(new TextView(this), params);

}

權(quán)限申請相關(guān)代碼

// Here, thisActivity is the current activity

if (ContextCompat.checkSelfPermission(thisActivity,

Manifest.permission.READ_CONTACTS)

!= PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?

if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,

Manifest.permission.READ_CONTACTS)) {

// Show an expanation to the user *asynchronously* -- don't block

// this thread waiting for the user's response! After the user

// sees the explanation, try again to request the permission.

} else {

// No explanation needed, we can request the permission.

ActivityCompat.requestPermissions(thisActivity,

new String[]{Manifest.permission.READ_CONTACTS},

MY_PERMISSIONS_REQUEST_READ_CONTACTS);

// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an

// app-defined int constant. The callback method gets the

// result of the request.

}

}

requestPermissions方法調(diào)用時會彈出以下對話框.當(dāng)用戶點擊拒絕并且勾選了不再彈出后這個對話框?qū)⒉粫購棾鲆淮瑫苯泳芙^掉該權(quán)限:

requestPermissions


shouldShowRequestPermissionRationale方法說明

用戶拒絕驱还,或是不在彈出,這個方法會返回false.

返回說明


Activity activity = (Activity) cxt;

return ActivityCompat.checkSelfPermission(activity,

permission) == PackageManager.PERMISSION_GRANTED;

} else if (cxt instanceof Fragment) {

Fragment fragment = (Fragment) cxt;

return fragment.getActivity().checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;

} else {

throw new RuntimeException("cxt is net a activity or fragment");

}

}

private static String[] checkSelfPermissionArray(Object cxt, String[] permission) {

ArrayList permiList = new ArrayList<>();

for (String p : permission) {

if (!checkSelfPermissionWrapper(cxt, p)) {

permiList.add(p);

}

}

return permiList.toArray(new String[permiList.size()]);

Activity和Fragment的申請方法不一樣凸克,所以我們對方法做了包裝如下:

@TargetApi(Build.VERSION_CODES.M)

public static boolean checkPermission(Object cxt, String permission, int requestCode) {

if (!checkSelfPermissionWrapper(cxt, permission)) {

if (!shouldShowRequestPermissionRationaleWrapper(cxt, permission)) {

requestPermissionsWrapper(cxt, new String[]{permission}, requestCode);

} else {

Log.d(TAG, "should show rational");

}

return false;

}

return true;

}

private static void requestPermissionsWrapper(Object cxt, String[] permission, int requestCode) {

if (cxt instanceof Activity) {

Activity activity = (Activity) cxt;

ActivityCompat.requestPermissions(activity, permission, requestCode);

} else if (cxt instanceof Fragment) {

Fragment fragment = (Fragment) cxt;

fragment.requestPermissions(permission, requestCode);

} else {

throw new RuntimeException("cxt is net a activity or fragment");

}

}

權(quán)限可以一次申請多個

如圖一次可以申請多個權(quán)限议蟆,但是用戶還是一個一個授權(quán).我們對該請求也做了封裝:

multimulti




@TargetApi(23)

private static boolean checkSelfPermissionWrapper(Object cxt, String permission) {

if (cxt instanceof Activity) {

Activity activity = (Activity) cxt;

return ActivityCompat.checkSelfPermission(activity,

permission) == PackageManager.PERMISSION_GRANTED;

} else if (cxt instanceof Fragment) {

Fragment fragment = (Fragment) cxt;

return fragment.getActivity().checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;

} else {

throw new RuntimeException("cxt is net a activity or fragment");

}

}

private static String[] checkSelfPermissionArray(Object cxt, String[] permission) {

ArrayList permiList = new ArrayList<>();

for (String p : permission) {

if (!checkSelfPermissionWrapper(cxt, p)) {

permiList.add(p);

}

}

return permiList.toArray(new String[permiList.size()]);

}


權(quán)限返回處理

在activity或fragment 中重寫onRequestPermissionsResult,用戶處理相關(guān)權(quán)限后會回調(diào)該方法萎战,當(dāng)活取到相關(guān)應(yīng)用后可以繼續(xù)原來的邏輯.

@Override

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

switch (requestCode) {

case PermissionUtils.PERMISSION_REQUEST_CODE:

if (PermissionUtils.verifyPermissions(grantResults)) {

// Permission Granted

// do you action

} else {

// Permission Denied

Toast.makeText(this, "WRITE_CONTACTS Denied", Toast.LENGTH_SHORT)

.show();

}

break;

default:

super.onRequestPermissionsResult(requestCode, permissions, grantResults);

}

}

public static boolean verifyPermissions(int[] grantResults) {

// At least one result must be checked.

if (grantResults.length < 1) {

return false;

}

// Verify that each required permission has been granted, otherwise return false.

for (int result : grantResults) {

if (result != PackageManager.PERMISSION_GRANTED) {

return false;

}

}

return true;

}

特殊權(quán)限的申請

以前特殊權(quán)限說明地方已經(jīng)支出咐容,該類權(quán)限需求intent到具體的設(shè)置頁面,讓用戶手動打開蚂维,才能授權(quán).

同樣重寫onActivityResult方法戳粒,返回該頁面時做回調(diào)處理.

sp

系統(tǒng)彈出權(quán)限,相關(guān)代碼實例:

/**

* 檢測系統(tǒng)彈出權(quán)限

* @param cxt

* @param req

* @return

*/

@TargetApi(23)

public static boolean checkSettingAlertPermission(Object cxt, int req) {

if (cxt instanceof Activity) {

Activity activity = (Activity) cxt;

if (!Settings.canDrawOverlays(activity.getBaseContext())) {

Log.i(TAG, "Setting not permission");

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,

Uri.parse("package:" + activity.getPackageName()));

activity.startActivityForResult(intent, req);

return false;

}

} else if (cxt instanceof Fragment) {

Fragment fragment = (Fragment) cxt;

if (!Settings.canDrawOverlays(fragment.getActivity())) {

Log.i(TAG, "Setting not permission");

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,

Uri.parse("package:" + fragment.getActivity().getPackageName()));

fragment.startActivityForResult(intent, req);

return false;

}

} else {

throw new RuntimeException("cxt is net a activity or fragment");

}

return true;

}

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if (requestCode == PermissionUtils.PERMISSION_SETTING_REQ_CODE) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

if (Settings.canDrawOverlays(this)) {

// do something

} else {

Toast.makeText(this, "not has setting permission", Toast.LENGTH_LONG).show();

finish();

}

}

}

}

結(jié)語

Android 6.0系統(tǒng)權(quán)限管理是安卓系統(tǒng)的一大進(jìn)步虫啥,為安卓手機(jī)用戶提供了一個安全干凈系統(tǒng)前提蔚约,鑒于google對未授權(quán)應(yīng)用的奔潰方式處理,

安卓開發(fā)者應(yīng)當(dāng)盡早適配6.0系統(tǒng)涂籽,提示軟件體驗.

實戰(zhàn)整體代碼已提交到GitHub(https://github.com/CankingApp/PermissionDemo),歡迎下載交流學(xué)習(xí)~


博客:http://cankingapp.github.io/2016/03/18/android-permission/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苹祟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌树枫,老刑警劉巖直焙,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異砂轻,居然都是意外死亡箕般,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門舔清,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人曲初,你說我怎么就攤上這事体谒。” “怎么了臼婆?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵抒痒,是天一觀的道長。 經(jīng)常有香客問我颁褂,道長故响,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任颁独,我火速辦了婚禮彩届,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘誓酒。我一直安慰自己樟蠕,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布靠柑。 她就那樣靜靜地躺著寨辩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪歼冰。 梳的紋絲不亂的頭發(fā)上靡狞,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機(jī)與錄音隔嫡,去河邊找鬼甸怕。 笑死,一個胖子當(dāng)著我的面吹牛畔勤,可吹牛的內(nèi)容都是我干的蕾各。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼庆揪,長吁一口氣:“原來是場噩夢啊……” “哼式曲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤吝羞,失蹤者是張志新(化名)和其女友劉穎兰伤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钧排,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡敦腔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了恨溜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片符衔。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖糟袁,靈堂內(nèi)的尸體忽然破棺而出判族,到底是詐尸還是另有隱情,我是刑警寧澤项戴,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布形帮,位于F島的核電站,受9級特大地震影響周叮,放射性物質(zhì)發(fā)生泄漏辩撑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一仿耽、第九天 我趴在偏房一處隱蔽的房頂上張望合冀。 院中可真熱鬧,春花似錦氓仲、人聲如沸水慨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晰洒。三九已至,卻和暖如春啥箭,著一層夾襖步出監(jiān)牢的瞬間谍珊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工急侥, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留砌滞,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓坏怪,卻偏偏與公主長得像贝润,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铝宵,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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