(1)Android動態權限申請

原文鏈接:https://www.jianshu.com/p/2324a2bdb3d4

Android權限的申請有兩種方式,靜態獲取和動態獲取。

靜態獲取:是在APP安裝的時候一次性獲取App所需要的所有權限,用戶不清楚在什麼情況下需要哪些權限

動態獲取:只有在使用的使用纔去獲取權限,由用戶決定是否授予,用戶能夠清楚的知道app在哪些場景下申請的了什麼權限

Android權限的申請由靜態方法變到動態方式,體現了Google在手機安全機制上的努力。

androd中有各種各樣的權限,和用戶數據相關的權限叫做危險權限,因爲應用如果獲得了這些權限,就有可能對用戶數據安全造成威脅,所以稱爲危險權限,危險權限的申請必須要用戶同意,同時危險權限又分爲9組,只要申請了每一組 內的任何一個權限,其餘權限也 自動獲得。

 

 

權限的申請在App中應該算是一個 通用的功能,既然是通用的功能就可以抽象成一個單獨的代碼模塊,進行處理,想要申請什麼權限就通過相應的方法傳遞權限即可。在每一次 需要權限的代碼執行之前都應該先判斷是否 擁有相應的權限。

下面的例子是一個 權限申請的通用代碼:

1.首先定義UI界面,在MainActivity中通過button觸發申請權限的操作,同時還要在Mainfest文件中聲明要申請的權限

AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS"/>


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="點擊獲儲權限" />
</LinearLayout>

2.在申請權限的時候需要調用requestPermission方法傳遞我們要申請的權限的信息,方法的簽名如下

    public final void requestPermissions(@NonNull String[] permissions, int requestCode) 

permissions表示是所要申請的權限,以字符串數組表示,requestCode可以理解爲一個標識符吧,和對應的權限一一對應

3. 在Activity的requestPermissions中會調用另外一個方法onRequestPermissionsResult,這個方法就是我們需要實現

對應的邏輯的地方,在Activity.java中這是一個空的實現。

Activity.java 
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
        if (requestCode < 0) {
            throw new IllegalArgumentException("requestCode should be >= 0");
        }
        if (mHasCurrentPermissionsRequest) {
            Log.w(TAG, "Can request only one set of permissions at a time");
            // Dispatch the callback with empty arrays which means a cancellation.
            onRequestPermissionsResult(requestCode, new String[0], new int[0]);
            return;
        }
        Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
        startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);
        mHasCurrentPermissionsRequest = true;
    }



    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        /* callback - no nothing */
    }

  下面是我們自己的實現,我們實現了onRequestPermissionsResult方法,同時又自定義了另外了一個重載的方法進一步的去處理我們的邏輯。因爲權限的申請是一個可以抽象成單獨模塊的動作,所以可以通過代碼抽象,將權限申請做成一個可以複用的邏輯,在需要權限的地方調用相應的方法傳遞參數就可以。

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode != RC_REQUEST_PERMISSION){
            return ;
        }
        boolean[] shouldShowRequestPermissionRationale = new boolean[permissions.length];
        for(int i = 0;i < permissions.length;i++){
            shouldShowRequestPermissionRationale[i] = shouldShowRequestPermissionRationale(permissions[i]);
        }
        this.onRequestPermissionsResult(permissions,grantResults,shouldShowRequestPermissionRationale);

    }


    void onRequestPermissionsResult(String[] permissions,int[] grantResults,boolean[] shouldShowRequestPermissionRationale ){

        Log.d("niuhaoshi","onRequestPermissionsResult");
        int length = permissions.length;
        int granted = 0;
        for(int i = 0;i < length;i++){
            if(grantResults[i] != PackageManager.PERMISSION_GRANTED){
                if(shouldShowRequestPermissionRationale[i] == true){
                    CALLBACK.shouldShowRational(permissions[i]);
                }else{
                    CALLBACK.onPermissionReject(permissions[i]);
                }
            }else{
                granted++;
            }
        }
        if(granted == length){
            CALLBACK.onPermissionGranted();
        }

    }

在onRequestPermissionsResult方法內部,我們通過for循環針對每一個權限都調用了一次shouldShowRequestPermissionRationale方法,從功能上理解就是說,它的返回值如果爲true就表示我們需要提供一個提示用戶爲什麼申請這個權限的原因,如果false的話表示不需要提供原因,當我們申請權限的時候彈出了對應的權限授予框,如果用戶拒絕,並且沒有選擇不再提示,此時返回false,如果用戶選擇了不再提示該函數就會返回true,我們就 可以根據這個返回值來做相應的處理。

 public boolean shouldShowRequestPermissionRationale(@NonNull String permission) {
        return getPackageManager().shouldShowRequestPermissionRationale(permission);
    }

所以在onRequestPermissionsResult中我們獲取到了,用戶針對我們申請的每一個權限所做的操作,然後繼續調用我們自定義的

onRequestPermissionsResult處理進一步的動作,根據用戶是否授權,是否點擊不在提示,來處理相應的邏輯。

 

在權限申請的過程中會彈出選擇是否授予權限的對話框,懷疑這個對話框的彈出和requestPermissions方法中的mHasCurrentPermissionsRequest 變量有關係,第一次調用requestPermissions,mHasCurrentPermissionsRequest爲false所以不走onRequestPermissionsResult這個過程,直接啓動一個對話框,這個應該直接調到系統測了,然後,從系統測回調回來的時候,調用了onRequestPermissionsResult這個方法,下次再調用的時候由於mHasCurrentPermissionsRequest爲true就不往系統側調用了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章