日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

聊一聊Android 6.0的运行时权限

發布時間:2025/3/15 Android 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 聊一聊Android 6.0的运行时权限 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android 6.0,代號棉花糖,自發布伊始,其主要的特征運行時權限就很受關注。因為這一特征不僅改善了用戶對于應用的使用體驗,還使得應用開發者在實踐開發中需要做出改變。

沒有深入了解運行時權限的開發者通常會有很多疑問,比如什么是運行時權限,哪些是運行時的權限,我的應用是不是會在6.0系統上各種崩潰呢,如何才能支持運行時權限機制呢。本文講嘗試回答這一些問題,希望讀者閱讀完成之后,都能找到較為完美的答案。

權限一刀切

在6.0以前的系統,都是權限一刀切的處理方式,只要用戶安裝,Manifest申請的權限都會被賦予,并且安裝后權限也撤銷不了
這種情況下,當我們從Google Play安裝一個應用,在安裝之前會得到這樣的權限提示信息。

當上述對話框彈出后,用戶只有兩種選擇:

  • 我信任你,即使有敏感權限
  • 你一個**應用,要這個權限干嘛,我還是不安裝了。

所以,這種一刀切的處理方式還是有弊端的,我們沒有辦法只允許某些權限或者拒絕某些權限。

棉花糖運行時權限

從棉花糖開始,Android系統引入了新的權限機制,即本文要講的運行時權限。

何為運行時權限呢?舉個栗子,以某個需要拍照的應用為例,當運行時權限生效時,其Camera權限不是在安裝后賦予,而是在應用運行的時候進行請求權限(比如當用戶按下”相機拍照“按鈕后)看到的效果則是這樣的

接下來,對于Camera權限的處理完全權交給用戶。是不是有點像蘋果系統的處理呢,不要說這是抄襲,暫且稱為師夷長技以制夷。

權限的分組

Android中有很多權限,但并非所有的權限都是敏感權限,于是6.0系統就對權限進行了分類,一般為下述幾類

  • 正常(Normal Protection)權限
  • 危險(Dangerous)權限
  • 特殊(Particular)權限
  • 其他權限(一般很少用到)

正常權限

正常權限具有如下的幾個特點

  • 對用戶隱私沒有較大影響或者不會打來安全問題。
  • 安裝后就賦予這些權限,不需要顯示提醒用戶,用戶也不能取消這些權限

正常權限列表

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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

上述的權限基本設計的是關于網絡,藍牙,時區,快捷方式等方面,只要在Manifest指定了這些權限,就會被授予,并且不能撤銷。

特殊權限

這里講特殊權限提前講一下,因為這個相對來說簡單一些。

特殊權限,顧名思義,就是一些特別敏感的權限,在Android系統中,主要由兩個

  • SYSTEM_ALERT_WINDOW,設置懸浮窗,進行一些黑科技
  • WRITE_SETTINGS 修改系統設置

關于上面兩個特殊權限的授權,做法是使用startActivityForResult啟動授權界面來完成。

請求SYSTEM_ALERT_WINDOW

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 (Settings.canDrawOverlays(this)) { Log.i(LOGTAG, "onActivityResult granted"); } } }

上述代碼需要注意的是

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

請求WRITE_SETTINGS

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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, "onActivityResult write settings granted" ); } } }

上述代碼需要注意的是

  • 使用Action Settings.ACTION_MANAGE_WRITE_SETTINGS 啟動隱式Intent
  • 使用"package:" + getPackageName()攜帶App的包名信息
  • 使用Settings.System.canWrite方法檢測授權結果

注意:關于這兩個特殊權限,一般不建議應用申請。

危險權限

危險權限實際上才是運行時權限主要處理的對象,這些權限可能引起隱私問題或者影響其他程序運行。Android中的危險權限可以歸為以下幾個分組:

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

各個權限分組與其具體的權限,可以參考下圖:

必須要支持運行時權限么

目前應用實際上是可以不需要支持運行時權限的,但是最終肯定還是需要支持的,只是時間問題而已。

想要不支持運行時權限機制很簡單,只需要將targetSdkVersion設置低于23就可以了,意思是告訴系統,我還沒有完全在API 23(6.0)上完全搞定,不要給我啟動新的特性。

不支持運行時權限會崩潰么

可能會,但不是那種一上來就噼里啪啦崩潰不斷的那種。

如果你的應用將targetSdkVersion設置低于23,那么在6.0的系統上不會為這個應用開啟運行時權限機制,即按照以前的一刀切方式處理。

然而有點糟糕的是

6.0系統提供了一個應用權限管理界面,界面長得是這樣的

既然是可以管理,用戶就能取消權限,當一個不支持運行時權限的應用某項權限被取消時

系統會彈出一個對話框提醒撤銷的危害,如果用戶執意撤銷,會帶來如下的反應

  • 如果你的程序正在運行,則會被殺掉。
  • 當你的應用再次運行時,可能出現崩潰

為什么會可能崩潰的,比如下面這段代碼

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

如果用戶撤消了獲取DeviceId的權限,那么再次運行時,deviceId就是null,如果程序后續處理不當,就會出現崩潰。

該來的還得來

6.0的運行時權限,我們最終都是要支持的,通常我們需要使用如下的API

  • int checkSelfPermission(String permission) 用來檢測應用是否已經具有權限
  • void requestPermissions(String[] permissions, int requestCode) 進行請求單個或多個權限
  • void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 用戶對請求作出響應后的回調

以一個請求Camera權限為例

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Override public void onClick(View v) { if (!(checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)) { requestCameraPermission(); } } private static final int REQUEST_PERMISSION_CAMERA_CODE = 1; private void requestCameraPermission() { 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); } }

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

當用戶選擇允許,我們就可以在onRequestPermissionsResult方法中進行響應的處理,比如打開攝像頭
當用戶拒絕,你的應用可能就開始危險了

當我們再次嘗試申請權限時,彈出的對話框和之前有點不一樣了,主要表現為多了一個checkbox。如下圖

當用戶勾選了”不再詢問“拒絕后,你的程序基本這個權限就Game Over了。

不過,你還有一絲希望,那就是再出現上述的對話框之前做一些說明信息,比如你使用這個權限的目的(一定要坦白)。

shouldShowRequestPermissionRationale這個API可以幫我們判斷接下來的對話框是否包含”不再詢問“選擇框。

一個標準的流程

1 2 3 4 5 6 7 8 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"); }

如何批量申請

批量申請權限很簡單,只需要字符串數組放置多個權限即可。如請求代碼

1 2 3 4 5 private static final int REQUEST_CODE = 1; private void requestMultiplePermissions() { String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE}; requestPermissions(permissions, REQUEST_CODE); }

對應的界面效果是

注意:間隔較短的多個權限申請建議設置成單次多個權限申請形式,避免彈出多個對話框,造成不太好的視覺效果。

申請這么多權限豈不是很累

其實你不需要每個權限都去顯式申請,舉一個例子,如果你的應用授權了讀取聯系人的權限,那么你的應用也是被賦予了寫入聯系人的權限。因為讀取聯系人和寫入聯系人這兩個權限都屬于聯系人權限分組,所以一旦組內某個權限被允許,該組的其他權限也是被允許的。

注意事項

API問題

由于checkSelfPermission和requestPermissions從API 23才加入,低于23版本,需要在運行時判斷 或者使用Support Library v4中提供的方法

  • ContextCompat.checkSelfPermission
  • ActivityCompat.requestPermissions
  • ActivityCompat.shouldShowRequestPermissionRationale

多系統問題

當我們支持了6.0必須也要支持4.4,5.0這些系統,所以需要在很多情況下,需要有兩套處理。比如Camera權限

1 2 3 4 5 if (isMarshmallow()) { requestPermission();//然后在回調中處理 } else { useCamera();//低于6.0直接使用Camera }

兩個權限

運行時權限對于應用影響比較大的權限有兩個,他們分別是

  • READ_PHONE_STATE
  • WRITE_EXTERNAL_STORAGE/READ_EXTERNAL_STORAGE

其中READ_PHONE_STATE用來獲取deviceID,即IMEI號碼。這是很多統計依賴計算設備唯一ID的參考。如果新的權限導致讀取不到,避免導致統計的異常。建議在完全支持運行時權限之前,將對應的值寫入到App本地數據中,對于新安裝的,可以采取其他策略減少對統計的影響。

WRITE_EXTERNAL_STORAGE/READ_EXTERNAL_STORAGE這兩個權限和外置存儲(即sdcard)有關,對于下載相關的應用這一點還是比較重要的,我們應該盡可能的說明和引導用戶授予該權限。

些許建議

  • 不要使用多余的權限,新增權限時要慎重
  • 使用Intent來替代某些權限,如撥打電話(和你的產品經理PK去吧)
  • 對于使用權限獲取的某些值,比如deviceId,盡量本地存儲,下次訪問直接使用本地的數據值
  • 注意,由于用戶可以撤銷某些權限,所以不要使用應用本地的標志位來記錄是否獲取到某權限。

注意

即使支持了運行時權限,也要在Manifest聲明,因為市場應用會根據這個信息和硬件設備進行匹配,決定你的應用是否在該設備上顯示。

是否支持運行時權限

個人覺得Marshmallow的運行時權限對于用戶來說絕對是一個好東西,但是目前想要支持需要做的事情還是比較多的。

對于一個有很多依賴的宿主應用,想要做到支持還是有一些工作量的,因為你的權限申請受制于依賴。

建議在短期內暫時可以不考慮支持該運行時權限機制,等時機成熟或者簡單易用的第三方庫完善之后再支持也未嘗不可。


原文地址: http://droidyue.com/blog/2016/01/17/understanding-marshmallow-runtime-permission/index.html

總結

以上是生活随笔為你收集整理的聊一聊Android 6.0的运行时权限的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。