android 6.0許可權機制的簡單封裝(支援批量申請許可權)

納蘭寒明發表於2019-01-22

本文章是對android 6.0許可權機制的簡單封裝,如果對許可權機制不太瞭解可以移步android 6.0許可權申請機制(簡單案例),有助於你對許可權機制的整體瞭解。

在封裝的過程中出現了一個問題,給大家分享下: 在官方文件中許可權的回撥是這樣的:

@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;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}
複製程式碼

在本方法中,官方使用的是switch..case...的方法去實現的,然而在封裝過程中無法將MY_PERMISSIONS_REQUEST常量資訊傳遞給PermissionUtils的callback(...)方法,傳遞後就會變成int型別,無法使用switch...case...方法,在查閱相關資料後,將回撥的方法改成這樣:

 public void callback(int requestCode, String permissions[], int[] grantResults){
        if(requestCode == key){
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            } else {
                Toast.makeText(context, "申請失敗", Toast.LENGTH_SHORT).show();
            }
            return;
        }
    }
複製程式碼

去判斷requestCode和key的值是否相等代替掉switch...case...,這個時switch...case...的基本原理,原諒我一時忘記!

接下來直接上全部整體原始碼: ####1.AndroidManifest的許可權新增

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.SEND_SMS" />
複製程式碼

####2.PermissionUtils的封裝

package com.example.mypremission;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by 納蘭寒明 on 2017/7/31.
 * 歡迎大家關注我的主頁
 * 簡書--http://www.jianshu.com/u/d9b6614545ce
 */

class PermissionUtils {
    private Context context;
    private List<String> p = new ArrayList<>();
    public  static int key = 1;

    //構造器
    PermissionUtils(Context context,int key) {
        this.context = context;
        this.key = key;
    }

    //新增許可權資訊
    public void add(String permission) {
        p.add(permission);
    }
    //將list轉化為String
    private String[] getPermissionString(){
        String strings[] = new String[p.size()];
        for (int k = 0, j = p.size(); k < j; k++) {
            strings[k] = p.get(k);
        }
        return strings;
    }

    
    //實現許可權的申請
    public void setPermission() {
        Log.e("kang",p+toString());
        for (int i = 0; i < p.size(); i++) {
            requestPermission(i);
            String strings[] = getPermissionString();
            ActivityCompat.requestPermissions((Activity) context, strings,key);
        }
    }
    //回撥方法
    public void callback(int requestCode, String permissions[], int[] grantResults){
        if(requestCode == key){
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            } else {
                Toast.makeText(context, "申請失敗", Toast.LENGTH_SHORT).show();
            }
            return;
        }
    }
    //驗證許可權的資訊
    private void requestPermission(int i) {
        if (ContextCompat.checkSelfPermission(context,
                p.get(i))
                != PackageManager.PERMISSION_GRANTED) {
            //檢查到該許可權未被授權
            if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context,
                    p.get(i))) {
                //上一次使用者拒絕了開啟此許可權
//                p.remove(i);
                Toast.makeText(context, "上次使用者拒絕開啟了"+p.get(i).toString()+"許可權!", Toast.LENGTH_SHORT).show();
            }
        } else {
            p.remove(i);
        }

    }
}
複製程式碼

####3.Activity中的配置

package com.example.mypremission;

import android.Manifest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private PermissionUtils p;
    private static final int MY_PERMISSIONS_EXTERNAL= 1;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //宣告PermissionUtils的物件
        p = new PermissionUtils(this,MY_PERMISSIONS_EXTERNAL);
        //新增許可權資訊
        p.add(Manifest.permission.CAMERA);
        p.add(Manifest.permission.SEND_SMS);
        p.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        //啟動許可權申請
        p.setPermission();
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        //許可權回撥處理
        p.callback(requestCode,permissions,grantResults);
    }
}
複製程式碼

目前在程式中,不太理解MY_PERMISSIONS_EXTERNAL的功能,他的必要性是什麼,檢視文件與回撥方法onRequesrPermissionResult(...)方法有關,但具體不太理解,希望大神可以幫我指出來它的功能。接下來我會檢視資料,解決問題!

修改版本:感謝@pianoboyfans 對本章的支援!通過交流,確實發現程式碼中存在的一些問題,現在問題已經解決。如果還有什麼bug還請反饋,及時修改,完善這個封裝類。

更新程式碼中修改PermissionUtils封裝類,其他未動,所以只更新PermissionUtils類:

/**
 * Created by 納蘭寒明 on 2017/7/31.
 * 歡迎大家關注我的主頁
 * 掘金--https://juejin.im/user/57e79759d20309006940dab7
 */
class PermissionUtils {
    private Context context;
    private List<String> p = new ArrayList<>();
    public  static int key = 1;
    public int temp = 0;

    //構造器
    PermissionUtils(Context context,int key) {
        this.context = context;
        this.key = key;
    }

    //新增許可權資訊
    public void add(String permission) {
        p.add(permission);
    }
    //將list轉化為String
    private String[] getPermissionString(){
        String strings[] = new String[p.size()];
        for (int k = 0, j = p.size(); k < j; k++) {
            strings[k] = p.get(k);
        }
        return strings;
    }

    
    //實現許可權的申請
    public void setPermission() {
       while(p.size()>temp){
           requestPermission(temp);
           temp++;
       }
        String strings[] = getPermissionString();
        if(strings.length != 0)
        ActivityCompat.requestPermissions((Activity) context, strings,key);
    }
    //回撥方法
    public void callback(int requestCode, String permissions[], int[] grantResults){
        if(requestCode == key){
            if (grantResults.length > 0){
                //每個許可權的返回資訊都可以判斷其是否授權成功
                for(int i = 0;i<grantResults.length;i++){
                    if(grantResults[i] == PackageManager.PERMISSION_GRANTED){
                        //成功授權
                        Toast.makeText(context, "授權成功", Toast.LENGTH_SHORT).show();
                    }else{
                        //授權失敗
                        Toast.makeText(context, "授權失敗", Toast.LENGTH_SHORT).show();
                    }
                }
            }
            return;
        }
    }
    //驗證許可權的資訊
    private void requestPermission(int i) {
        //檢查到該許可權未被授權
        if (ContextCompat.checkSelfPermission(context,
                p.get(i))
                != PackageManager.PERMISSION_GRANTED) {
            //判斷上一次使用者是否開啟了此許可權(原生系統)
            if (ActivityCompat.shouldShowRequestPermissionRationale((Activity) context,
                    p.get(i))) {
                //上一次使用者拒絕了開啟此許可權
                Toast.makeText(context, "上次使用者拒絕開啟了"+p.get(i).toString()+"許可權!", Toast.LENGTH_SHORT).show();
            }
        } else {
            //檢查許可權被授權就移除許可權
            p.remove(i);
            temp--;
        }
    }
}
複製程式碼

原生系統在使用者拒絕後第二次開啟程式還是會讓使用者選擇的,而本人親測小米5手機上shouldShowRequestPermissionRationale()這個方法返回的是false(),那麼就不會在第二次開啟程式後彈出被拒絕的許可權了,直接就會拒絕授權。

該封裝類許可權控制較為重要,避免多次使用,只允許擁有一個例項,所以可以使用單例模式進行封裝!

相關文章