安卓動態獲取許可權看這一篇就夠了
安卓動態獲取許可權看這一篇就夠了(想看具體流程的進)
為大家帶來一篇安卓6.0動態獲取許可權的內容。看完後,你就能夠掌握安卓動態獲取許可權的相關知識。而不是在面試官面前說我會用 RxPermission 等一些類庫實現。為什麼這樣說,因為在之前我也是網上找找類庫用用就行了。而如今工作中碰到發現還是需要自己去原生層處理。
為何需要主動獲取許可權
Google在 Android 6.0 開始將所有許可權分成了正常許可權和危險許可權。所以如果應用的 targetSdkVersion >= 23 並且 申請了危險許可權 但是僅僅在AndroidManifest 註冊是不夠的,相關執行時會出錯,會提示沒有相應的許可權。如果不想申請,設定targetSdkVersion = 22或者更低,然後 return;
哪些是危險許可權
危險許可權有哪些,涉及到使用者一些隱私的大體都屬於。具體有以下
- group:android.permission-group.CONTACTS
- permission:android.permission.WRITE_CONTACTS
- permission:android.permission.GET_ACCOUNTS
- permission:android.permission.READ_CONTACTS
- group:android.permission-group.PHONE
- permission:android.permission.READ_CALL_LOG
- permission:android.permission.READ_PHONE_STATE
- permission:android.permission.CALL_PHONE
- permission:android.permission.WRITE_CALL_LOG
- permission:android.permission.USE_SIP
- permission:android.permission.PROCESS_OUTGOING_CALLS
- permission:com.android.voicemail.permission.ADD_VOICEMAIL
- group:android.permission-group.CALENDAR
- permission:android.permission.READ_CALENDAR
- permission:android.permission.WRITE_CALENDAR
- group:android.permission-group.CAMERA
- permission:android.permission.CAMERA
- group:android.permission-group.SENSORS
- permission:android.permission.BODY_SENSORS
- group:android.permission-group.LOCATION
- permission:android.permission.ACCESS_FINE_LOCATION
- permission:android.permission.ACCESS_COARSE_LOCATION
- group:android.permission-group.STORAGE
- permission:android.permission.READ_EXTERNAL_STORAGE
- permission:android.permission.WRITE_EXTERNAL_STORAGE
- group:android.permission-group.MICROPHONE
- permission:android.permission.RECORD_AUDIO
- group:android.permission-group.SMS
- permission:android.permission.READ_SMS
- permission:android.permission.RECEIVE_WAP_PUSH
- permission:android.permission.RECEIVE_MMS
- permission:android.permission.RECEIVE_SMS
- permission:android.permission.SEND_SMS
- permission:android.permission.READ_CELL_BROADCASTS
申請許可權的幾個步驟
- AndroidManifest.xml 中宣告需要的許可權
- 判斷許可權狀態
- 判斷使用者是否上一次拒絕了許可權並且勾選了 不再提示
- 申請許可權 (使用者執行 繼續操作,使用者拒絕 根據個人情景對應操作)
AndroidManifest.xml 中宣告需要的許可權
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
判斷許可權狀態
/**
* 判斷是否有許可權
*
* @param permission
* @return
*/
protected boolean isHasPermission(String permission) {
return ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED;
}
判斷使用者是否上一次拒絕了許可權並且勾選了 不再提示
使用者拒絕的時候,本地記錄下,以方便下一次申請,判斷上一次使用者是否選擇了不再提示。
requestRunTimePermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, new SimplePermissionListener() {
@Override
public void onGranted() {
Log.i(TAG, "儲存許可權 已經授權");
}
@Override
public void onDenied() {
super.onDenied();Log.i(TAG, "使用者拒絕授予 儲存 許可權");
HelperUtils.setValues(MainActivity.this, SharePerfenceUtils.KEY_STORAGE_NOTIP);
}
});
shouldShowRequestPermissionRationale 返回false,並且上一次是拒絕了許可權,所以給出提示,或者彈出對話方塊(使用者自定義)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
SharePerfenceUtils.clear(this, SharePerfenceUtils.KEY_STORAGE_NOTIP);
} else if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE) && HelperUtils.getValues(MainActivity.this, SharePerfenceUtils.KEY_STORAGE_NOTIP).equals("1")) {
//使用者拒絕許可權 並勾選了 不再提示 (這裡 可以自定義 Dialog 讓使用者跳轉 系統設定 去選擇許可權 跳轉的方法在 HelperUtils 類中)
if(HelperUtils.getValues(MainActivity.this, SharePerfenceUtils.KEY_STORAGE_NOTIP_SHOWED).equals("1")){
// 使用者拒絕許可權 並勾選了 不再提示 後 已經提示過一次
return;
}
// 使用者拒絕許可權 並勾選了 不再提示 下一次獲取許可權 彈土司提示
Toast.makeText(this, "未取得儲存許可權,請在應用設定中開啟許可權", Toast.LENGTH_SHORT).show();
HelperUtils.setValues(MainActivity.this, SharePerfenceUtils.KEY_STORAGE_NOTIP_SHOWED);
return;
} else {
}
}
申請許可權(這是我寫在BaseActivity裡的,介面回撥方式回傳,看不明白的,文章結束處可以去github上看)
/**
* 許可權申請
*
* @param permissions 待申請的許可權集合
* @param listener 申請結果監聽事件
*/
protected void requestRunTimePermission(String[] permissions, PermissionListener listener) {
this.mlistener = listener;
// 用於存放未授權的許可權
List<String> permissionList = new ArrayList<>();
// 遍歷傳遞過來的許可權集合
for (String permission : permissions) {
// 判斷是否已經授權
if (isHasPermission(permission)) {
// 未授權,則加入待授權的許可權集合中
permissionList.add(permission);
}
}
// 判斷集合
if (!permissionList.isEmpty()) {
// 如果集合不為空,則需要去授權
ActivityCompat.requestPermissions(this, permissionList.toArray(new String[permissionList.size()]), 1);
} else {
// 為空,則已經全部授權
if (listener != null) {
listener.onGranted();
}
}
}
/**
* 許可權申請結果
*
* @param requestCode 請求碼
* @param permissions 所有的許可權集合
* @param grantResults 授權結果集合
*/
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults.length > 0) {
// 被使用者拒絕的許可權集合
List<String> deniedPermissions = new ArrayList<>();
// 使用者通過的許可權集合
List<String> grantedPermissions = new ArrayList<>();
for (int i = 0; i < grantResults.length; i++) {
// 獲取授權結果,這是一個int型別的值
int grantResult = grantResults[i];
if (grantResult != PackageManager.PERMISSION_GRANTED) {
// 使用者拒絕授權的許可權
String permission = permissions[i];
deniedPermissions.add(permission);
} else {
// 使用者同意的許可權
String permission = permissions[i];
grantedPermissions.add(permission);
}
}
if (deniedPermissions.isEmpty()) {
// 使用者拒絕許可權為空
if (mlistener != null) {
mlistener.onGranted();
}
} else {
// 不為空
if (mlistener != null) {
// 回撥授權成功的介面
mlistener.onGranted(grantedPermissions);
// 回撥授權失敗的介面
mlistener.onDenied(deniedPermissions);
mlistener.onDenied();
}
}
}
break;
default:
break;
}
}
public interface PermissionListener {
// 授權成功
void onGranted();
// 授權部分
void onGranted(List<String> grantedPermission);
// 拒絕授權
void onDenied(List<String> deniedPermission);
// 授權失敗
void onDenied();
}
下面說兩種特殊情況
- 危險許可權 呼叫許可權方法沒反應 沒系統彈窗
- 危險許可權 安裝時就已經賦予了許可權,但是 是 空白通行證
沒系統彈窗
在申請許可權之前,先調下對應需要許可權的方法並且 try catch。
try{
TelephonyManager TelephonyMgr = (TelephonyManager)this.getSystemService(this.TELEPHONY_SERVICE);
String ime = TelephonyMgr.getDeviceId();
}catch (SecurityException e){
e.printStackTrace();
}finally {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
if(isHasPermission(Manifest.permission.READ_PHONE_STATE)){
requestRunTimePermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, new SimplePermissionListener() {
@Override
public void onGranted() {
}
@Override
public void onDenied() {
HelperUtils.setValues(MainActivity.this, SharePerfenceUtils.KEY_STORAGE_NOTIP);
}
});
}
}
}
空白通行證
開發中遇到,紅米10 機型,安卓10 系統,獲取 Phone_State 許可權時。得到已經獲取了許可權,但是並沒有拿到對應的內容。暫時沒解決
最後附上github地址,歡迎一起學習(因為回撥經常寫了,所以看不慣的大佬們還請擔待 安卓6.0動態獲取許可權)
相關文章
- Linux特殊許可權,這一篇就夠了Linux
- delphi安卓動態許可權申請安卓
- Git 看這一篇就夠了Git
- 索引?看這一篇就夠了!索引
- Transformer 看這一篇就夠了ORM
- Java 動態代理,看這篇就夠了Java
- Flutter DataTable 看這一篇就夠了Flutter
- Java 集合看這一篇就夠了Java
- 代理模式看這一篇就夠了模式
- OAuth授權|看這篇就夠了OAuth
- Elasticsearch入門,看這一篇就夠了Elasticsearch
- 關於SwiftUI,看這一篇就夠了SwiftUI
- 瞭解 MongoDB 看這一篇就夠了MongoDB
- flex佈局看這一篇就夠了Flex
- ActiveMq 之JMS 看這一篇就夠了MQ
- MySQL入門看這一篇就夠了MySql
- jQuery入門看這一篇就夠了jQuery
- 入門Hbase,看這一篇就夠了
- Spring入門看這一篇就夠了Spring
- Mybatis入門看這一篇就夠了MyBatis
- Python操作MongoDB看這一篇就夠了PythonMongoDB
- Python快速入門,看這一篇就夠了!Python
- Android Architecture Components 只看這一篇就夠了Android
- 【Nginx】如何獲取客戶端真實IP、域名、協議、埠?看這一篇就夠了!Nginx客戶端協議
- MySQL,你只需看這一篇文章就夠了!MySql
- 瞭解SSL證書,看這一篇就夠了!!
- Nginx 配置常用引數,看這一篇就夠了Nginx
- SpringBoot寫後端介面,看這一篇就夠了!Spring Boot後端
- 什麼是事件管理?看這一篇就夠了!事件
- IDEA中的Git操作,看這一篇就夠了!IdeaGit
- 約束佈局ConstraintLayout看這一篇就夠了AI
- 分散式事務,只看這一篇就夠了分散式
- 虛擬機器安裝及使用Linux,看這一篇就夠了!虛擬機Linux
- 谷歌披露安卓嚴重安全問題,惡意軟體能夠獲取系統級許可權谷歌安卓
- Redis快取雪崩、快取穿透、快取擊穿對比看這一篇就夠了Redis快取穿透
- MAUI之安卓許可權UI安卓
- Java安全第一篇 | 反射看這一篇就夠了Java反射
- macOS 安裝 Nebula Graph 看這篇就夠了Mac