Android 6.0 許可權使用 以及小米手機許可權的適配
阿新 • • 發佈:2019-01-31
Android Runtime Permission
1,執行時許可權說明:
Android執行時許可權,是Android6.0新加的功能點。當我們想要把我們的app適配到6.0 以及以上的時候,我們需要對執行時許可權做些操作,否則很容易會造成程式崩潰,當我們執行在6.0系統的時候。
2,常見許可權:
// 6.0許可權的基本知識,以下是需要單獨申請的許可權,
// 共分為9組,每組只要有一個許可權申請成功了,就預設整組許可權都可以使用了。
// 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 //第七組 允許程式寫入外部儲存,如SD卡上寫檔案
// 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
3,google 官方的介紹:
官方執行時demo:https://github.com/bonaparteI/android-RuntimePermissions-master
1,官方demo中 :
先看效果圖 (以下為我翻譯後的介面):
google官方的demo 還是比較不錯的。但對於許可權的處理。我感覺還是不夠完善。當我們碰到適配問題時就暴露無疑。
比如小米對於 shouldShowRequestPermissionRationale方法 的處理。
若按照google的處理方式:處理顯然不夠完善。
4,於是乎 我寫了一個 許可權請求處理的demo。供大家參考。
先看效果圖:左邊是直接請求許可權的處理方式,右邊是對許可權先做檢查後做處理的方式。
5 邏輯說明:
1,首先我們要知道我們申請許可權是需要在 Mainfest.xml 中註冊的。預設不註冊的許可權是不被准許的。直接申請許可權存在App崩潰的潛在風險:
// 直接申請 不做許可權檢查:執行流程:請求許可權---彈出Dialog(要允許App申請許可權嗎?)---拒絕||允許
// 拒絕情況:再次點選:請求許可權----彈出Dialog(帶有不再詢問對話方塊checkBox)---拒絕||允許
// 拒絕情況:再次點選:之前未勾選不再詢問的checkBox: 此時效果同上。
// 拒絕情況:再次點選:之前勾選了不再詢問的checkBox: 此時不再提示對話方塊,但會回撥onRequestPermissionsResult列印6許可權被拒絕。
directRequestPermisssion(Manifest.permission.READ_CONTACTS,REQUEST_CONTACTS_CODE);
//.....
/**
* 直接 請求 許可權
* @param permission 許可權
* @param resultCode 結果碼
*/
protected void directRequestPermisssion(String permission,int resultCode){
ActivityCompat.requestPermissions(this, new String[]{permission}, resultCode);
}
2,幾個重要方法:
/**
* Determine whether <em>you</em> have been granted a particular permission.
*
* @param permission The name of the permission being checked.
*
* @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if you have the
* permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} if not.
*
* @see android.content.pm.PackageManager#checkPermission(String, String)
*/
public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
}
return context.checkPermission(permission, android.os.Process.myPid(), Process.myUid());
}
//=============================================================
/**
* Requests permissions to be granted to this application. These permissions
* must be requested in your manifest, they should not be granted to your app,
* and they should have protection level {@link android.content.pm.PermissionInfo
* #PROTECTION_DANGEROUS dangerous}, regardless whether they are declared by
* the platform or a third-party app.
* <p>
* Normal permissions {@link android.content.pm.PermissionInfo#PROTECTION_NORMAL}
* are granted at install time if requested in the manifest. Signature permissions
* {@link android.content.pm.PermissionInfo#PROTECTION_SIGNATURE} are granted at
* install time if requested in the manifest and the signature of your app matches
* the signature of the app declaring the permissions.
* </p>
* <p>
* If your app does not have the requested permissions the user will be presented
* with UI for accepting them. After the user has accepted or rejected the
* requested permissions you will receive a callback reporting whether the
* permissions were granted or not. Your activity has to implement {@link
* android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback}
* and the results of permission requests will be delivered to its {@link
* android.support.v4.app.ActivityCompat.OnRequestPermissionsResultCallback#onRequestPermissionsResult(
* int, String[], int[])} method.
* </p>
* <p>
* Note that requesting a permission does not guarantee it will be granted and
* your app should be able to run without having this permission.
* </p>
* <p>
* This method may start an activity allowing the user to choose which permissions
* to grant and which to reject. Hence, you should be prepared that your activity
* may be paused and resumed. Further, granting some permissions may require
* a restart of you application. In such a case, the system will recreate the
* activity stack before delivering the result to your
* {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
* </p>
* <p>
* When checking whether you have a permission you should use {@link
* #checkSelfPermission(android.content.Context, String)}.
* </p>
* <p>
* Calling this API for permissions already granted to your app would show UI
* to the user to decided whether the app can still hold these permissions. This
* can be useful if the way your app uses the data guarded by the permissions
* changes significantly.
* </p>
* <p>
* You cannot request a permission if your activity sets {@link
* android.R.attr#noHistory noHistory} to <code>true</code> in the manifest
* because in this case the activity would not receive result callbacks including
* {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
* </p>
* <p>
* The <a href="http://developer.android.com/samples/RuntimePermissions/index.html">
* RuntimePermissions</a> sample app demonstrates how to use this method to
* request permissions at run time.
* </p>
*
* @param activity The target activity.
* @param permissions The requested permissions. Must me non-null and not empty.
* @param requestCode Application specific request code to match with a result
* reported to {@link OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])}.
* Should be >= 0.
*
* @see OnRequestPermissionsResultCallback#onRequestPermissionsResult(int, String[], int[])
* @see #checkSelfPermission(android.content.Context, String)
* @see #shouldShowRequestPermissionRationale(android.app.Activity, String)
*/
public static void requestPermissions(final @NonNull Activity activity,
final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode) {
if (Build.VERSION.SDK_INT >= 23) {
ActivityCompatApi23.requestPermissions(activity, permissions, requestCode);
} else if (activity instanceof OnRequestPermissionsResultCallback) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
final int[] grantResults = new int[permissions.length];
PackageManager packageManager = activity.getPackageManager();
String packageName = activity.getPackageName();
final int permissionCount = permissions.length;
for (int i = 0; i < permissionCount; i++) {
grantResults[i] = packageManager.checkPermission(
permissions[i], packageName);
}
((OnRequestPermissionsResultCallback) activity).onRequestPermissionsResult(
requestCode, permissions, grantResults);
}
});
}
}
//==========================================================================
/**
* Gets whether you should show UI with rationale for requesting a permission.
* You should do this only if you do not have the permission and the context in
* which the permission is requested does not clearly communicate to the user
* what would be the benefit from granting this permission.
* <p>
* For example, if you write a camera app, requesting the camera permission
* would be expected by the user and no rationale for why it is requested is
* needed. If however, the app needs location for tagging photos then a non-tech
* savvy user may wonder how location is related to taking photos. In this case
* you may choose to show UI with rationale of requesting this permission.
* </p>
*
* @param activity The target activity.
* @param permission A permission your app wants to request.
* @return Whether you can show permission rationale UI.
*
* @see #checkSelfPermission(android.content.Context, String)
* @see #requestPermissions(android.app.Activity, String[], int)
*/
public static boolean shouldShowRequestPermissionRationale(@NonNull Activity activity,
@NonNull String permission) {
if (Build.VERSION.SDK_INT >= 23) {
return ActivityCompatApi23.shouldShowRequestPermissionRationale(activity, permission);
}
return false;
}
樓主也基本看不懂但大致意思是:
checkPermission():檢查許可權。requestPermissions()請求許可權。shouldShowRequestPermissionRationale():是否應該請求許可權(注意該方法,小米對於該方法一直返回false)。
經樓主反覆測試:
第一個主要是用於檢查許可權是否被使用者准許過。
第二個方法主要是用來請求許可權。
第三個怎麼解釋呢?我直接說返回結果吧:當用戶第一次拒絕過之後該方法會一直返回false。其他返回true。(該方法在小米手機中會一直返回false。開發者需注意適配問題。)
上面說的適配問題怎麼解決呢?
樓主是在許可權請求結果中添加了一次判斷:當用戶拒絕許可權後,再次彈出dialog提醒許可權的重要性。使用者可以選擇取消或者開啟設定介面進行設定。
//TODO 解釋為什麼 需要該許可權的 對話方塊
showMissingPermissionDialog();
小米手機返回圖片截圖:
over。
樓主對activity進行了許可權請求的封裝,需要請求許可權的可以直接拿走,修改需要請求的許可權即可。。
如果對你有幫助 歡迎fork 和star
參考: