Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 6.0 運行時權限框架

android 6.0 運行時權限框架

編輯:關於Android編程

android 6.0 有些危險權限需要運行時手動獲取才能繼續執行應用,否則將出來很多崩潰問題 如果sdk設置22是可以在啟動時避免這個問題,先獲取到全部的權限,但是一旦用戶關閉了你需要的權限,呢完了。你的程序還是奔潰了。用戶如果不知道是因為自己關閉了權限導致應用奔潰的。呢就陷入死循環的奔潰中,所以還是先加上這個控制比較好。   以下是通過android系統提供的在運行時獲取權限的辦法,這裡我就不寫了網上也有不少我就復制來給大家看看。大家看過了解後我會給大家推薦一個我現在正在使用並且感覺比較好的一款權限管理框架。   當你的這個activity某個功能需要調用到權限的時候(比如,相機,文件讀寫) 你需要在調用功能前先去檢查下權限  
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {
}else{
    //這是已經獲得到權限 可以寫你的邏輯了
}
這裡涉及到一個API,ContextCompat.checkSelfPermission,主要用於檢測某個權限是否已經被授予,方法返回值為PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。當返回DENIED就需要進行申請授權了。   這是運行時去獲得授權的方法
ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);
該方法是異步的,第一個參數是Context;第二個參數是需要申請的權限的字符串數組;第三個參數為requestCode,主要用於回調的時候檢測。可以從方法名requestPermissions以及第二個參數看出,是支持一次性申請多個權限的,系統會通過對話框逐一詢問用戶是否授權。   處理權限申請回調
@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }
    }
}
如果用戶拒絕了你的請求,但是沒有選擇不再提示
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
        Manifest.permission.READ_CONTACTS)) 
這個API可以讓你在次請求的時候,判斷是不是已經拒絕過一次了,如果已經拒絕了這是你可以在這裡給用戶一些提示,為什麼需要這個權限
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // 寫上你的提示。然後再去請求權限,比如一個提示框,然後告訴用戶為什麼需要這個權限,用戶點擊確定後再去調用ActivityCompat請求一遍權限

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}
系統的方法就講到這裡。系統的權限請求 activity和fragment略有不同。
    //activity
    ActivityCompat.requestPermissions(conent, perms, requestCode);
    //fragment
    fragment.requestPermissions(perms, requestCode);
  以上的代碼 鴻神的博客寫的比較詳細大家可以去鴻神呢裡看看 傳送門 http://blog.csdn.net/lmj623565791/article/details/50709663 鴻神也在後邊詳解了兩個框架 PermissionGen 和 MPermissions 第一個是用反射實現的,但是這兩個框架的代碼稍稍多了一點,對我來說不宜學習。所以我推薦一個更簡潔的框架,這個只需要一個類,一個注解就決絕了以上的問題。   這個框架就是 EasyPermission 大家也可以去網上找找這個框架的使用,我在這裡就簡單的介紹一下使用   activity或者fragment需要實現這個接口
EasyPermissions.PermissionCallbacks

    @Override
    public void onPermissionsGranted(int requestCode, List perms) {
        //這是回掉成功的方法,成功的需要判斷請求成功幾條權限,可以用list的條數進行判斷 請求的條數等於成功數這樣就是全部請求成功了
    }

    @Override
    public void onPermissionsDenied(int requestCode, List perms) {
        //這是失敗的
    }
}
  這是請求時的代碼
    @AfterPermissionGranted(REQUECT_CODE_SDCARD) //請求時的請求碼
    private void getPermiss(){
        if (EasyPermissions.hasPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE})) {

        } else {
            EasyPermissions.requestPermissions(this,"沒有權限將無法繼續執行,請為應用授權!", REQUECT_CODE_SDCARD, permission);
        }
    }
然後就是系統的回掉方法,你需要調用框架的回掉方法,把系統的回掉方法的值傳給它
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
  
  這樣一個權限請求就寫完了。當你的應用需要用到這些權限的時候。調用getPermiss方法就可以。   後面我會復上這個框架的類。   現在框架都講完了。其實會遇到一個問題,呢就是如果用戶點了拒絕,然後也選擇了不再提醒,但是我們的應用有必須需要這個權限,呢怎麼辦呢,其實可以在框架中稍稍修改下就可以解決這個問題,當不能再彈出來提示框的時候,我們可以給一個提示框,然後讓用戶到系統設置我們應用的界面裡,去手動的打開這個權限:
    private static int count;//定義一個記錄請求次數的值
    public static void requestPermissions(final Object object, String rationale,
                                          @StringRes int positiveButton,
                                          @StringRes int negativeButton,
                                          final int requestCode, final String... perms) {

        checkCallingObjectSuitability(object);
        final PermissionCallbacks callbacks = (PermissionCallbacks) object;

        boolean shouldShowRationale = false;
        for (String perm : perms) {
            shouldShowRationale = shouldShowRationale || shouldShowRequestPermissionRationale(object, perm);
        }

        if (shouldShowRationale) { //用戶雖然點了拒絕,但是沒有選擇不再提示,這樣每次都會彈這個框框
            AlertDialog dialog = new AlertDialog.Builder(getActivity(object))
                    .setMessage(rationale)
                    .setPositiveButton(positiveButton, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            executePermissionsRequest(object, perms, requestCode);
                        }
                    })
                    .setNegativeButton(negativeButton, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            // act as if the permissions were denied
                            callbacks.onPermissionsDenied(requestCode, Arrays.asList(perms));
                        }
                    }).create();
            dialog.show();
        } else {
            if (count==0){//第一次請求
                executePermissionsRequest(object, perms, requestCode);
                count=1;
            }else {//如果選擇了不再提示,呢樣就會進入這裡,彈出提示框,讓他直接去系統設置中打開權限
                AlertDialog dialog = new AlertDialog.Builder(getActivity(object))
                        .setMessage(perminssions_content)
                        .setPositiveButton(positiveButton, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Uri packageURI = Uri.parse("package:" + getActivity(object).getPackageName().toString());
                                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                                getActivity(object).startActivity(intent);
                            }
                        })
                        .setNegativeButton(negativeButton, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                            }
                        }).create();
                dialog.show();
            }

        }
    }

要記得權限請求成功後,吧count還原成0,要不別的頁面就不能正常請求了。在這個方法裡邊還原
    public static void onRequestPermissionsResult(int requestCode, String[] permissions,
                                                  int[] grantResults, Object object) {

        checkCallingObjectSuitability(object);
        PermissionCallbacks callbacks = (PermissionCallbacks) object;

        // Make a collection of granted and denied permissions from the request.
        ArrayList granted = new ArrayList<>();
        ArrayList denied = new ArrayList<>();
        for (int i = 0; i < permissions.length; i++) {
            String perm = permissions[i];
            if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                granted.add(perm);
            } else {
                denied.add(perm);
            }
        }

        // Report granted permissions, if any.
        if (!granted.isEmpty()) {
            // Notify callbacks
            count=0;//請求成功,還原count
            callbacks.onPermissionsGranted(requestCode, granted);
        }

        // Report denied permissions, if any.
        if (!denied.isEmpty()) {
            callbacks.onPermissionsDenied(requestCode, denied);
        }

        // If 100% successful, call annotated methods
        if (!granted.isEmpty() && denied.isEmpty()) {
            runAnnotatedMethods(object, requestCode);
        }
    }
這個框架只有一個類,相對學習起來都比較容易,看完這個代碼,自己對權限這塊就會比較清晰了。   但是權限的這些API這不同的手機上的呈現都有不同。這個的兼容問題,就要靠大家的努力一起解決了。 比如我現在就遇到了,在小米上,同時請求手機及狀態和通訊錄通話記錄讀取的時候,用戶點擊了拒絕,但是權限檢查權限的方法卻返回了成功。 這個問題我還沒解決,大家如果有好的辦法,請在留言板回復。 這裡我為大家提供一些便利。我將需要運行檢查的呢些權限都寫成常量放在一起了。也方便以後找那些權限。
    /**
     * Dangerous Permissions
     * 坑爹的危險權限
     * */
    public static final String WRITE_CONTACTS= Manifest.permission.WRITE_CONTACTS;//寫入聯系人,但不可讀取
    public static final String GET_ACCOUNTS= Manifest.permission.GET_ACCOUNTS;//訪問一個帳戶列表在Accounts Service中
    public static final String READ_CONTACTS= Manifest.permission.READ_CONTACTS;//讀取聯系人,但不可寫入
    public static final String READ_CALL_LOG= Manifest.permission.READ_CALL_LOG;//讀取通話記錄
    public static final String READ_PHONE_STATE= Manifest.permission.READ_PHONE_STATE;//讀取手機狀態
    public static final String CALL_PHONE= Manifest.permission.CALL_PHONE;//讀取手機號碼
    public static final String WRITE_CALL_LOG= Manifest.permission.WRITE_CALL_LOG;//寫入通話記錄
    public static final String USE_SIP= Manifest.permission.USE_SIP;
    public static final String PROCESS_OUTGOING_CALLS= Manifest.permission.PROCESS_OUTGOING_CALLS;//允許程序監視、修改有關播出電話
    public static final String ADD_VOICEMAIL= Manifest.permission.ADD_VOICEMAIL;
    public static final String READ_CALENDAR= Manifest.permission.READ_CALENDAR;//允許程序讀取用戶日歷數據
    public static final String WRITE_CALENDAR= Manifest.permission.WRITE_CALENDAR;//允許一個程序寫入但不讀取用戶日歷數據
    public static final String CAMERA= Manifest.permission.CAMERA;//相機
    public static final String BODY_SENSORS= Manifest.permission.BODY_SENSORS;//人體傳感器;
    public static final String ACCESS_FINE_LOCATION= Manifest.permission.ACCESS_FINE_LOCATION;//這個權限用於訪問GPS定位
    public static final String ACCESS_COARSE_LOCATION= Manifest.permission.ACCESS_COARSE_LOCATION;//這個權限用於進行網絡定位
    public static final String READ_EXTERNAL_STORAGE= Manifest.permission.READ_EXTERNAL_STORAGE;//讀取外部存儲器
    public static final String WRITE_EXTERNAL_STORAGE= Manifest.permission.WRITE_EXTERNAL_STORAGE;//寫入外部存儲器
    public static final String RECORD_AUDIO= Manifest.permission.RECORD_AUDIO;//允許程序錄制音頻
    public static final String READ_SMS= Manifest.permission.READ_SMS;//讀取短信
    public static final String RECEIVE_WAP_PUSH= Manifest.permission.RECEIVE_WAP_PUSH;//允許程序監控將收到WAP PUSH信息
    public static final String RECEIVE_MMS= Manifest.permission.RECEIVE_MMS;//允許一個程序監控將收到MMS彩信,記錄或處理
    public static final String RECEIVE_SMS= Manifest.permission.RECEIVE_SMS;//允許程序監控一個將收到短信息,記錄或處理
    public static final String SEND_SMS= Manifest.permission.SEND_SMS;//允許程序發送SMS短信

EasyPermiss項目地址
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved