1. 程式人生 > >Android 6.0 許可權使用 以及小米手機許可權的適配

Android 6.0 許可權使用 以及小米手機許可權的適配

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

參考: