Android動態請求許可權的工具類(轉載、非原創)

小小9575發表於2018-09-18

 

Android動態請求許可權的工具類

Android 6.0(SDK 23)以上才需要用到動態許可權。

之前已經寫過好多次關於Android動態許可權的文章,但是後期發現每次都要進行復制貼上,還要修改,

還不如寫一個自己的工具類,那就方便多了!

網上也有很多關於動態許可權的工具類,還有一些框架, 
但是我發現有些使用還是挺麻煩,我感覺還是自己這個動態許可權的工具類是非常好的。

一.我的動態許可權工具類PermissionsUtils使用方法:

1.定義許可權陣列

 //比如:兩個日曆許可權和一個資料讀寫許可權
 String[] permissions = new String[]{Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_EXTERNAL_STORAGE};

一個或者多個許可權都是可以的。

2.建立監聽許可權的介面物件

  //建立監聽許可權的介面物件
    PermissionsUtils.IPermissionsResult permissionsResult = new PermissionsUtils.IPermissionsResult() {
        @Override
        public void passPermissons() {
            Toast.makeText(MainActivity.this, "許可權通過,可以做其他事情!", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void forbitPermissons() {
//            finish();
            Toast.makeText(MainActivity.this, "許可權不通過!", Toast.LENGTH_SHORT).show();
        }
    };

這裡許可權禁止,也可以自己寫得詳細一些,比如還有什麼許可權沒有通過,但是我感覺沒有必要。

3.在Activity重寫onRequestPermissionsResult方法

在重寫的方法中需要呼叫工具類的onRequestPermissionsResult方法,這個方法需要傳入Activity物件

   @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //就多一個引數this
        PermissionsUtils.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }

4.呼叫checkPermissions方法

這個方法一般在onCreate使用,或者在執行某個事件前使用,在回撥方法中覺得是否執行後續的動作!

 //這裡的this不是上下文,是Activity物件!
 PermissionsUtils.getInstance().chekPermissions(this, permissions, permissionsResult);

5.屬性showSystemSetting

showSystemSetting是一個靜態屬性,可以設定true和false,表示是否可以跳轉到系統設定許可權的視窗。

這個屬性的作用是如果使用者在勾選不再提示許可權的情況下,可以幫助使用者跳轉到系統許可權的視窗去設定這個屬性。 
防止這個許可權可能一直沒有得到允許的情況。

這個屬性預設是true,在許可權沒有通過的情況,提示使用者是否跳轉到系統設定許可權的視窗。

二.PermissionsUtils工具類的程式碼

package com.huawei.calendar.myapplication;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;

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

/**
 * 許可權工具類
 */

public class PermissionsUtils {


    private final int mRequestCode = 100;//許可權請求碼
    public static boolean showSystemSetting = true;

    private PermissionsUtils() {
    }

    private static PermissionsUtils permissionsUtils;
    private IPermissionsResult mPermissionsResult;

    public static PermissionsUtils getInstance() {
        if (permissionsUtils == null) {
            permissionsUtils = new PermissionsUtils();
        }
        return permissionsUtils;
    }

    public void chekPermissions(Activity context, String[] permissions, @NonNull IPermissionsResult permissionsResult) {
        mPermissionsResult = permissionsResult;

        if (Build.VERSION.SDK_INT < 23) {//6.0才用動態許可權
            permissionsResult.passPermissons();
            return;
        }

        //建立一個mPermissionList,逐個判斷哪些許可權未授予,未授予的許可權儲存到mPerrrmissionList中
        List<String> mPermissionList = new ArrayList<>();
        //逐個判斷你要的許可權是否已經通過
        for (int i = 0; i < permissions.length; i++) {
            if (ContextCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
                mPermissionList.add(permissions[i]);//新增還未授予的許可權
            }
        }

        //申請許可權
        if (mPermissionList.size() > 0) {//有許可權沒有通過,需要申請
            ActivityCompat.requestPermissions(context, permissions, mRequestCode);
        } else {
            //說明許可權都已經通過,可以做你想做的事情去
            permissionsResult.passPermissons();
            return;
        }


    }

    //請求許可權後回撥的方法
    //引數: requestCode  是我們自己定義的許可權請求碼
    //引數: permissions  是我們請求的許可權名稱陣列
    //引數: grantResults 是我們在彈出頁面後是否允許許可權的標識陣列,陣列的長度對應的是許可權名稱陣列的長度,陣列的資料0表示允許許可權,-1表示我們點選了禁止許可權

    public void onRequestPermissionsResult(Activity context, int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        boolean hasPermissionDismiss = false;//有許可權沒有通過
        if (mRequestCode == requestCode) {
            for (int i = 0; i < grantResults.length; i++) {
                if (grantResults[i] == -1) {
                    hasPermissionDismiss = true;
                }
            }
            //如果有許可權沒有被允許
            if (hasPermissionDismiss) {
                if (showSystemSetting) {
                    showSystemPermissionsSettingDialog(context);//跳轉到系統設定許可權頁面,或者直接關閉頁面,不讓他繼續訪問
                } else {
                    mPermissionsResult.forbitPermissons();
                }
            } else {
                //全部許可權通過,可以進行下一步操作。。。
                mPermissionsResult.passPermissons();
            }
        }

    }


    /**
     * 不再提示許可權時的展示對話方塊
     */
    AlertDialog mPermissionDialog;

    private void showSystemPermissionsSettingDialog(final Activity context) {
        final String mPackName = context.getPackageName();
        if (mPermissionDialog == null) {
            mPermissionDialog = new AlertDialog.Builder(context)
                    .setMessage("已禁用許可權,請手動授予")
                    .setPositiveButton("設定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            cancelPermissionDialog();

                            Uri packageURI = Uri.parse("package:" + mPackName);
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                            context.startActivity(intent);
                            context.finish();
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            //關閉頁面或者做其他操作
                            cancelPermissionDialog();
                            //mContext.finish();
                            mPermissionsResult.forbitPermissons();
                        }
                    })
                    .create();
        }
        mPermissionDialog.show();
    }

    //關閉對話方塊
    private void cancelPermissionDialog() {
        if (mPermissionDialog != null) {
            mPermissionDialog.cancel();
            mPermissionDialog = null;
        }

    }


    public interface IPermissionsResult {
        void passPermissons();

        void forbitPermissons();
    }


}

三.呼叫工具類的示例程式碼


package com.huawei.calendar.myapplication;

import android.Manifest;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import java.security.Permission;

public class MainActivity extends AppCompatActivity {

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

        //兩個日曆許可權和一個資料讀寫許可權
        String[] permissions = new String[]{Manifest.permission.WRITE_CALENDAR, Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_EXTERNAL_STORAGE};
//        PermissionsUtils.showSystemSetting = false;//是否支援顯示系統設定許可權設定視窗跳轉
        //這裡的this不是上下文,是Activity物件!
        PermissionsUtils.getInstance().chekPermissions(this, permissions, permissionsResult);
    }

    //建立監聽許可權的介面物件
    PermissionsUtils.IPermissionsResult permissionsResult = new PermissionsUtils.IPermissionsResult() {
        @Override
        public void passPermissons() {
            Toast.makeText(MainActivity.this, "許可權通過,可以做其他事情!", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void forbitPermissons() {
//            finish();
            Toast.makeText(MainActivity.this, "許可權不通過!", Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //就多一個引數this
        PermissionsUtils.getInstance().onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }
}

記得在AndroidManifest中新增許可權

    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

使用效果圖

1.申請許可權的時候

1

2.有許可權沒有通過的情況

1

3.點選跳轉到系統許可權設定頁面的時候

3 
showSystemSetting屬性為true的情況才會提示這個對話方塊! 
我看了其他人動態許可權的寫法,都沒有跳轉到設定系統許可權的對話方塊的,但是我感覺這個在需要的時候還是比較管用的。

四.其他的

這個工具類還是比較完善的了,如果需要修改一些字串或者邏輯可以自己修改,工具類的邏輯應該也是比較清晰的。

android6.0後,僅在manifest.xml清單中配置相關許可權時,如果將targetSdkVersion設定為23及以上,部分敏感許可權需要動態申請後才能使用; 
如果不想處理6.0以上的適配,請將targetSdkVersion設定為22或以下;但是低版本的SDK可能沒有高版本的一些屬性或者類。

但是注意一點,無論版本高低,需要的許可權一定要寫在AndroidManifest中,如果在動態許可權中申請的許可權在Manife中沒有寫,你會發現他不會詢問你這個許可權。 
所有你不可能獲取到這個許可權。

如果你在AndroidManifest中寫了多個需要動態申請的許可權,在動態許可權申請的時候可以只申請一個或者一部分。沒有問題的。 
如果你跳轉到這個程式的系統設定許可權介面,你會發現AndroidManifest中所有申明的許可權都顯示在這裡,可以對任何一個許可權進行禁止或者允許。

1.敏感許可權也是危險許可權Dangerous-Permisson,能夠獲取到使用者的隱私;

共9類/組

許可權組 名稱
CALENDAR 日曆
CAMERA 相機
CONTACTS 聯絡人
LOCATION 定位
MICROPHONE 麥克相關,比如錄音
PHONE 手機狀態
SENSORS 感測器
SMS 簡訊
STORAGE 儲存許可權

2.詳細敏感權

1 group:android.permission-group.CONTACTS
    permission:android.permission.WRITE_CONTACTS
    permission:android.permission.GET_ACCOUNTS    
    permission:android.permission.READ_CONTACTS

2  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

3  group:android.permission-group.CALENDAR
    permission:android.permission.READ_CALENDAR
    permission:android.permission.WRITE_CALENDAR

4  group:android.permission-group.CAMERA
    permission:android.permission.CAMERA

5  group:android.permission-group.SENSORS
    permission:android.permission.BODY_SENSORS

6  group:android.permission-group.LOCATION
    permission:android.permission.ACCESS_FINE_LOCATION
    permission:android.permission.ACCESS_COARSE_LOCATION

7  group:android.permission-group.STORAGE
    permission:android.permission.READ_EXTERNAL_STORAGE
    permission:android.permission.WRITE_EXTERNAL_STORAGE

8  group:android.permission-group.MICROPHONE
    permission:android.permission.RECORD_AUDIO

9  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 

原創作地址https://blog.csdn.net/wenzhi20102321/article/details/80616197 

相關文章