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

Android 6.0 運行時權限封裝框架

編輯:關於Android編程

1.概述


  視頻講解都已經錄了好幾天,但是最近實在抽不開身一直在忙Unity3D,就連光棍節都在寫,上次我們只是寫了Android 6.0 運行時權限處理解析,但是並未對其做代碼封裝,這一次我們做一個徹底的處理。
  附視頻講解地址:http://pan.baidu.com/s/1bpqqkGn
  
這裡寫圖片描述

2.框架封裝 


  2.1. 簡單例子

public class MainActivity extends AppCompatActivity {
    // 打電話權限申請的請求碼
    private static final int CALL_PHONE_REQUEST_CODE = 0x0011;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void phoneClick(View view){
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE)
                != PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this, "申請權限", Toast.LENGTH_SHORT).show();
            ActivityCompat.requestPermissions(this,
                    new String[]{"Manifest.permission.CALL_PHONE"}, CALL_PHONE_REQUEST_CODE);
        }else {
            callPhone();
        }
    }

    /**
    * 撥打電話
    **/
    private void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:147****2514");
        intent.setData(data);
        startActivity(intent);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(requestCode == CALL_PHONE_REQUEST_CODE){
            if (grantResults !=null&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission Granted
                callPhone();
            } else {
                // Permission Denied
                Toast.makeText(this,"權限被拒絕了",Toast.LENGTH_SHORT).show();
            }
        }
    }
}

  這是從上一篇中復制過來的,並沒有做過任何處理,如果每次申請權限的地方都需要這麼做,那就比較麻煩了,那麼我們肯定要對phoneClick()和onRequestPermissionsResult()裡面的代碼進行處理,那麼要處理成什麼樣子?當然是所有的代碼都可以優化成一行,別人都這麼說的。

  2.1. 確定方式
  到底采用什麼方式去封裝,這個github上面有很多,中國人,日本人,韓國人各國人民都有,這個不是開完笑的真的都有,這裡我才用反射+注解的方式去實現。
  
  2.2. 參數傳遞和傳遞方式
  我們肯定要新建類,至於傳什麼參數? 第一個參數反射的類this,第二個參數請求碼用於監聽反饋處理,第三個參數傳請求權限的數組
  利用什麼方式傳遞過去那麼?可以在工具類裡面寫一個靜態的方法一把塞過去。但是在這裡我們可以使用鏈式調用這種方式我們也經常使用,比如Okhttp,Gilde,甚至是Android的AlertDialog都是使用的這個方式,可以裝裝B

public class PermissionHelper {
    // 1. 傳什麼參數
    // 1.1. Object Fragment or Activity  1.2. int 請求碼   1.3.需要請求的權限  string[]
    private Object mObject;
    private int mRequestCode;
    private String[] mRequestPermission;

    private PermissionHelper(Object object){
        this.mObject = object;
    }

    // 2.已什麼的方式傳參數
    // 2.1 直接傳參數
    public static void  requestPermission(Activity activity,int requestCode,String[] permissions){
            PermissionHelper.with(activity).requestCode(requestCode).
                    requestPermission(permissions).request();
    }

    public static void  requestPermission(Fragment fragment,int requestCode,String[] permissions){
        PermissionHelper.with(fragment).requestCode(requestCode).
                requestPermission(permissions).request();
    }

    // 2.2 鏈式的方式傳
    // 傳Activity
    public static PermissionHelper with(Activity activity){
        return new PermissionHelper(activity);
    }

    // 傳Fragment
    public static PermissionHelper with(Fragment fragment){
        return new PermissionHelper(fragment);
    }

    // 添加一個請求碼
    public PermissionHelper requestCode(int requestCode){
        this.mRequestCode = requestCode;
        return this;
    }

    // 添加請求的權限數組
    public PermissionHelper requestPermission(String... permissions){
        this.mRequestPermission = permissions;
        return this;
    }

    /**
     * 3.1 真正判斷和發起請求權限
     */
    public void request() {
        // 3.2 首先判斷當前的版本是不是6.0 及以上
        if(!PermissionUtils.isOverMarshmallow()){
            // 3.3 如果不是6.0以上  那麼直接執行方法   反射獲取執行方法
            // 執行什麼方法並不確定 那麼我們只能采用注解的方式給方法打一個標記,
            // 然後通過反射去執行。  注解 + 反射  執行Activity裡面的callPhone
            PermissionUtils.executeSucceedMethod(mObject,mRequestCode);
            return;
        }
    }
}

2.2. 處理6.0以下的版本
  對於6.0以下的版本,我們可以直接反射調用執行成功的方法,如果反射不太理解可以看一下這個視頻講解:http://pan.baidu.com/s/1bpqqkGn

    /**
     * 執行成功的方法
     */
    public static void executeSucceedMethod(Object reflectObject, int requestCode) {
        // 獲取class中多有的方法
        Method[] methods = reflectObject.getClass().getDeclaredMethods();

        // 遍歷找我們打了標記的方法
        for (Method method:methods){
            Log.e("TAG",method+"");
            // 獲取該方法上面有沒有打這個成功的標記
            PermissionSucceed succeedMethod =  method.getAnnotation(PermissionSucceed.class);
            if(succeedMethod != null){
                // 代表該方法打了標記
                // 並且我們的請求碼必須 requestCode 一樣
                int methodCode = succeedMethod.requestCode();
                if(methodCode == requestCode){
                    // 這個就是我們要找的成功方法
                    // 反射執行該方法
                    Log.e("TAG","找到了該方法 :"+method);
                    executeMethod(reflectObject,method);
                }
            }
        }
    }

    /**
     * 反射執行該方法
     */
    private static void executeMethod(Object reflectObject,Method method) {
        // 反射執行方法  第一個是傳該方法是屬於哪個類   第二個參數是反射方法的參數
        try {
            method.setAccessible(true); // 允許執行私有方法
            method.invoke(reflectObject,new Object[]{});
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

2.3. 處理6.0以上的版本

    /**
     * 3.1 真正判斷和發起請求權限
     */
    public void request() {
        // 3.2 首先判斷當前的版本是不是6.0 及以上
        if(!PermissionUtils.isOverMarshmallow()){
            // 3.3 如果不是6.0以上  那麼直接執行方法   反射獲取執行方法
            // 執行什麼方法並不確定 那麼我們只能采用注解的方式給方法打一個標記,
            // 然後通過反射去執行。  注解 + 反射  執行Activity裡面的callPhone
            PermissionUtils.executeSucceedMethod(mObject,mRequestCode);
            return;
        }

        // 3.3 如果是6.0以上  那麼首先需要判斷權限是否授予
        // 需要申請的權限中 獲取沒有授予過得權限
        List deniedPermissions = PermissionUtils.getDeniedPermissions(mObject,mRequestPermission);

        // 3.3.1 如果授予了 那麼我們直接執行方法   反射獲取執行方法
        if(deniedPermissions.size() == 0){
            // 全部都是授予過的
            PermissionUtils.executeSucceedMethod(mObject,mRequestCode);
        }else {
            // 3.3.2 如果沒有授予 那麼我們就申請權限  申請權限
            ActivityCompat.requestPermissions(PermissionUtils.getActivity(mObject),
                    deniedPermissions.toArray(new String[deniedPermissions.size()]),
                    mRequestCode);
        }
    }

  
2.4. 處理回調
  如果用戶同意或是拒絕那麼會回調onRequestPermissionsResult(),我們肯定也需要對它做處理,這個方法就很簡單了:

    /**
     * 處理申請權限的回調
     */
    public static void requestPermissionsResult(Object object,int requestCode,
                                                String[] permissions) {
        // 再次獲取沒有授予的權限
        List deniedPermissions = PermissionUtils.getDeniedPermissions(object,permissions);

        if(deniedPermissions.size() == 0){
            // 權限用戶都同意授予了
            PermissionUtils.executeSucceedMethod(object,requestCode);
        }else{
            // 你申請的權限中 有用戶不同意的
            PermissionUtils.executeFailMethod(object,requestCode);
        }
    }

2.5. 最後的事例

public class MainActivity extends AppCompatActivity {
    // 打電話權限申請的請求碼
    private static final int CALL_PHONE_REQUEST_CODE = 0x0011;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

   public void phoneClick(View view){
        PermissionHelper.with(this).requestCode(CALL_PHONE_REQUEST_CODE)
                .requestPermission(Manifest.permission.CALL_PHONE).request();
    }

    @PermissionSucceed(requestCode =  CALL_PHONE_REQUEST_CODE)
    private void callPhone() {
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:147****2514");
        intent.setData(data);
        startActivity(intent);
    }

    @PermissionFail(requestCode = CALL_PHONE_REQUEST_CODE)
    private void callPhoneFail(){
        Toast.makeText(this,"您拒絕了撥打電話",
            Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    PermissionHelper.requestPermissionsResult(this,
        CALL_PHONE_REQUEST_CODE,permissions);
    }
}

  到最後再處理權限請求的時候會輕松很多,一行代碼解決問題,反正別人都這麼說,我們甚至可以把onRequestPermissionsResult()的處理寫到BaseActivity中,因為權限封裝我沒有把它寫入到基礎架構部分,這裡我就不處理了。

這裡寫圖片描述
  
  項目的代碼不能夠發給大家,裡面涉及到後台接口以及數據加密,如果大家感興趣可以看一下我錄的視頻:http://pan.baidu.com/s/1bpqqkGn 。
  

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