【Android 應用開發】動態許可權管理示例 ( 使用原生程式碼實現 | 申請許可權 | 判定許可權申請結果 | 判定 “ 不再詢問 “ 情況 )及程式碼示例
一、申請許可權
首先 , 判定許可權是否已經通過 , 如果沒有通過再進行申請 ;
如果下面函式返回值為 PackageManager.PERMISSION_GRANTED , 說明許可權申請通過 ;
如果返回值為 PackageManager.PERMISSION_DENIED , 說明許可權沒有被授予 ;
ContextCompat.checkSelfPermission(mActivity, mRequestPermissions[i]);
然後 , 申請沒有通過的許可權 ;
第2個引數是 String 陣列 , 內容是許可權字串 ;
/** * 需要申請的許可權*/ protected String[] mRequestPermissions = new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; ActivityCompat.requestPermissions(mActivity, mRequestPermissions, REQUEST_CODE);
完整過程 :
在 Build.VERSION_CODES.M , Android 6.0 ( API 23 ) 才啟用動態許可權申請 ;
只要有 任何1個許可權沒有通過 , 就需要許可權申請 ;
/** * 請求動態許可權 * * @return */ public boolean requestPermission() { // Android 6.0 ( API 23 ) 才啟用動態許可權申請 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 使用者是否不同意許可權, 只要有 1 個不同意, 則為 true, 預設 false boolean isDisagree = false;// 判定是否有許可權未獲取 for (int i = 0; i < mRequestPermissions.length; i++) { if (ContextCompat.checkSelfPermission( mActivity, mRequestPermissions[i]) != PackageManager.PERMISSION_GRANTED) { isDisagree = true; } } if (isDisagree) { // 存在許可權沒有通過,需要申請 ActivityCompat.requestPermissions(mActivity, mRequestPermissions, REQUEST_CODE); return false; } else { // 所有許可權都已同意 return true; } } else { // 6.0 以下預設有動態許可權 return true; } }
二、判定許可權申請結果
在 Activity 的 onRequestPermissionsResult 回撥方法中 , 可以獲取到許可權是否授予 ;
@Override public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { }
遍歷第 3個引數 grantResults 陣列 , 如果指定索引的元素值為− 1, 說明 permissions 陣列中指定的許可權沒有授予通過 , 被使用者拒絕了 ;
如果 grantResults 陣列中所有的值都為0, 說明所有許可權授予通過 , 可以繼續執行後續操作 ;
public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (REQUEST_CODE != requestCode) { return; } // 許可權是否賦予完畢, 如果有任意一個沒有同意, 則判定許可權申請失敗 boolean allAgree = true; // 遍歷 grantResults 陣列, 判定哪個許可權被拒絕了 for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == -1) { if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permissions[i])) { // 被使用者拒絕了, 但是還可以申請, 說明沒有設定 "不再詢問" 選項 } else { // 被使用者拒絕了, 不能彈出, 說明使用者設定了 "不再詢問" 選項 showDialog(); } allAgree = false; } } // 如果都同意, 則執行相關操作 if (allAgree) { Toast.makeText(mActivity, "許可權設定完畢, 執行相關操作", Toast.LENGTH_LONG).show(); } }
三、判定 " 不再詢問 " 情況
使用 ActivityCompat.shouldShowRequestPermissionRationale 方法判定使用者是否選擇了 " 不再詢問 " 選項 ;
ActivityCompat.shouldShowRequestPermissionRationale(mActivity, 許可權字串) ;
shouldShowRequestPermissionRationale 方法的含義是當前是否 提示使用者進行許可權申請 , 指的是顯示給使用者申請許可權的理由 ;
是否顯示申請許可權的原理 , 也就是 顯示給使用者 " 為什麼應用需要你授予這個許可權 " , 要想方設法勸使用者授予這個許可權 , 以及說明不授予許可權不能使用的哪些功能 ;
如果該方法 返回 true , 則顯示 ; 如果該方法返回 false , 則不顯示 ;
分為四種情況 :
① 首次申請 :由於是第1 11次申請許可權 , 直接申請即可 , 不需要給使用者顯示申請許可權的理由 , 返回 false ;
② 使用者拒絕了申請 :如果使用者拒絕了許可權的申請 , 開發者需要給使用者顯示 " 為什麼申請該許可權 , 要使用許可權做那些事 " , 因此需要給使用者提示 , 返回 true ;
③ 使用者拒絕申請並選擇 " 不再詢問 " :使用者已經明確拒絕 , 就不要再騷擾使用者了 , 不用給出進一步的提示資訊 , 返回 false ;
④ 使用者同意權限申請 :使用者已經同意了 , 也不用給使用者進行原理提示 , 返回 false ;
Google 的意思是如果使用者選擇了 " 不再詢問 " , 那開發者就不能在提及與該許可權相關的事了 ;
但是我們開發時總想把使用者引導到許可權設定介面 , 讓使用者自己設定 , 因此這裡就有了這個 " 不再詢問 " 判定問題 ;
有點反直覺 ;
判定 " 不再詢問 " 情況 :
在 Activity 的 onRequestPermissionsResult 方法中 ,
public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
在使用者拒絕許可權的前提下 , 如果
ActivityCompat.shouldShowRequestPermissionRationale(mActivity, 許可權字串)
方法返回 false , 此時就是使用者點選了 " 不再詢問 " 選項 ;
只能在上述情況下判定 , 其它情況都判定不了 ;
四、完整程式碼示例
1、許可權管理程式碼
許可權管理程式碼 :
package com.example.permission; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; public class PermissionManager { /** * 申請許可權的 Activity 介面 */ private Activity mActivity; /** * "不再詢問" 後的引導對話方塊 */ private AlertDialog mAlertDialog; /** * 申請許可權的請求碼, 要求必須 >0 */ public final int REQUEST_CODE = 100; /** * 需要申請的許可權 */ protected String[] mRequestPermissions = new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; public PermissionManager(Activity activity) { this.mActivity = activity; } /** * 請求動態許可權 * * @return */ public boolean requestPermission() { // Android 6.0 ( API 23 ) 才啟用動態許可權申請 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 使用者是否不同意許可權, 只要有 1 個不同意, 則為 true, 預設 false boolean isDisagree = false; // 判定是否有許可權未獲取 for (int i = 0; i < mRequestPermissions.length; i++) { if (ContextCompat.checkSelfPermission( mActivity, mRequestPermissions[i]) != PackageManager.PERMISSION_GRANTED) { isDisagree = true; } } if (isDisagree) { // 存在許可權沒有通過,需要申請 ActivityCompat.requestPermissions(mActivity, mRequestPermissions, REQUEST_CODE); return false; } else { // 所有許可權都已同意 return true; } } else { // 6.0 以下預設有動態許可權 return true; } } public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (REQUEST_CODE != requestCode) { return; } // 許可權是否賦予完畢, 如果有任意一個沒有同意, 則判定許可權申請失敗 boolean allAgree = true; // 遍歷 grantResults 陣列, 判定哪個許可權被拒絕了 for (int i = 0; i < grantResults.length; i++) { if (grantResults[i] == -1) { if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, permissions[i])) { // 被使用者拒絕了, 但是還可以申請, 說明沒有設定 "不再詢問" 選項 } else { // 被使用者拒絕了, 不能彈出, 說明使用者設定了 "不再詢問" 選項 showDialog(); } allAgree = false; } } // 如果都同意, 則執行相關操作 if (allAgree) { Toast.makeText(mActivity, "許可權設定完畢, 執行相關操作", Toast.LENGTH_LONG).show(); } } /** * 使用者選擇 "不再詢問" 後的提示方案 */ protected void showDialog() { // 不管同意/拒絕 , 只彈出一次 if (mAlertDialog != null){ return; } mAlertDialog = new AlertDialog.Builder(mActivity) .setMessage("手動設定許可權") .setPositiveButton("設定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 跳轉到設定介面 Intent intent = new Intent( Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:com.example.permission") ); mActivity.startActivity(intent); mAlertDialog.cancel(); } }) .setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { mAlertDialog.cancel(); } }) .create(); mAlertDialog.show(); } }
主介面程式碼
package com.example.permission; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import com.example.permission.databinding.ActivityMainBinding; public class MainActivity extends AppCompatActivity { /** * 許可權管理 */ private PermissionManager mPermissionManager; /** * 檢視繫結 */ private ActivityMainBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); binding.button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mPermissionManager = new PermissionManager(MainActivity.this); mPermissionManager.requestPermission(); } }); } @Override public void onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); mPermissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults); } }
五 部落格原始碼
GitHub :https://github.com/han1202012/PermissionManager
文章出處:感謝這篇文章很直接很清晰的反映了安卓6及以上的版本申請許可權的過程,過程非常清晰明瞭,特註明出處,如有侵權,請作者聯絡,第一時間刪除。感謝作者的好文分享
【【Android 應用開發】動態許可權管理示例 ( 使用原生程式碼實現 | 申請許可權 | 判定許可權申請結果 | 判定 “ 不再詢問 “ 情況 ) (136.la)】
半斤八兩開始寫BLOG了