android6.0运行时权限完美封装方法

为了在Android 6.0及以上版本上获得一些敏感权限,如读取设备存储器、拍照、录音等,需要使用运行时权限。本文将介绍如何完美封装运行时权限,使其在应用中更加方便快捷。

1. 权限获取流程

首先,我们需要确定权限获取的流程:

  1. 先判断权限是否已经被授予:
    • 如果有授予了,直接执行后续操作。
    • 如果没有授予,执行下一步。
  2. 弹出权限请求框,请求用户授权。
  3. 用户授权或拒绝后,系统回调我们预定义的处理函数,然后我们在该函数中处理相关逻辑。

现在,我们开始具体实现这个流程。

2. 权限申请流程封装

我们创建一个PermissionUtil类来封装该过程。

public class PermissionUtil {

    /**
     * 判断是否已经授权该权限
     * @param context 应用上下文
     * @param permission 权限字符串
     * @return true 已经授权,false 未授权
     */
    public static boolean hasPermission(Context context, String permission) {
        return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 请求权限
     * @param activity 当前Activity实例
     * @param permission 权限字符串
     * @param requestCode 请求码
     */
    public static void requestPermission(Activity activity, String permission, int requestCode) {
        ActivityCompat.requestPermissions(activity, new String[]{permission}, requestCode);
    }

    /**
     * 判断是否需要向用户解释此权限作用
     * @param activity 当前Activity实例
     * @param permission 权限字符串
     * @return true 需要解释,false 不需要解释
     */
    public static boolean shouldShowRequestPermissionRationale(Activity activity, String permission) {
        return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
    }

}

这个类封装了三个静态方法,分别用于判断权限是否已经被授予、请求权限和判断是否需要向用户解释权限。

这样实现的目的是使我们的代码能够更加清晰和易于维护。

3. 处理权限请求和结果

ActivityFragment的代码中,我们需要处理权限请求和结果。我们创建一个新的类PermissionActivity,用于处理权限请求。

public class PermissionActivity extends AppCompatActivity {

    private static final String EXTRA_PERMISSION_LIST = "extra_permission_list";
    private static final int PERMISSION_REQUEST_CODE = 1;

    private String[] mPermissionList;

    /**
     * 启动 PermissionActivity 的静态方法
     * @param context 应用上下文
     * @param permissionList 权限列表
     * @param callback 处理权限结果的回调
     */
    public static void launch(Context context, String[] permissionList, PermissionCallback callback) {
        Intent intent = new Intent(context, PermissionActivity.class);
        intent.putExtra(EXTRA_PERMISSION_LIST, permissionList);
        PermissionCallbackHolder.getInstance().setPermissionCallback(callback);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mPermissionList = getIntent().getStringArrayExtra(EXTRA_PERMISSION_LIST);

        if (mPermissionList == null || mPermissionList.length == 0) {
            // 权限列表为空
            finish();
            return;
        }

        requestPermissions();
    }

    /**
     * 请求权限
     */
    private void requestPermissions() {
        ActivityCompat.requestPermissions(this, mPermissionList, PERMISSION_REQUEST_CODE);
    }

    /**
     * 处理权限结果
     * @param requestCode 请求码
     * @param permissions 权限列表
     * @param grantResults 请求结果列表
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        PermissionCallback callback = PermissionCallbackHolder.getInstance().getPermissionCallback();

        if (requestCode == PERMISSION_REQUEST_CODE) {
            List<String> granted = new ArrayList<>();
            List<String> denied = new ArrayList<>();

            for (int i = 0; i < grantResults.length; i++) {
                String permission = permissions[i];
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    granted.add(permission);
                } else {
                    denied.add(permission);
                }
            }

            if (denied.isEmpty()) {
                // 全部权限都已授权
                callback.onPermissionGranted();
            } else {
                // 有权限被拒绝
                callback.onPermissionDenied(denied, shouldShowPermissionRationale());
            }
        }

        finish();
    }

    /**
     * 判断是否需要向用户解释权限作用
     * @return true 需要解释,false 不需要解释
     */
    private boolean shouldShowPermissionRationale() {
        for (String permission : mPermissionList) {
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
                return true;
            }
        }
        return false;
    }

}

PermissionActivity中,我们启动权限请求框、处理请求结果,并在回调中处理相关逻辑.

这个类未涉及到UI操作,只是进行了数据操作,可以便捷地被其他ActivityFragment调用。

4. 处理权限结果回调

最后,我们需要处理权限结果回调。为了将回调处理与要求权限的ActivityFragment解耦,我们将回调处理统一调用。

public class PermissionCallbackHolder {
    private static final PermissionCallbackHolder INSTANCE = new PermissionCallbackHolder();

    private PermissionCallbackHolder() {}

    @Nullable
    private PermissionCallback mPermissionCallback;

    public static PermissionCallbackHolder getInstance() {
        return INSTANCE;
    }

    @Nullable
    public PermissionCallback getPermissionCallback() {
        return mPermissionCallback;
    }

    public void setPermissionCallback(@Nullable PermissionCallback permissionCallback) {
        mPermissionCallback = permissionCallback;
    }

}

PermissionCallbackHolder类创建一个全局静态实例,负责保存处理权限结果的回调PermissionCallback

public interface PermissionCallback {
    void onPermissionGranted();
    void onPermissionDenied(List<String> denied, boolean alwaysDenied);
}

PermissionCallback中定义了两个函数:onPermissionGranted()onPermissionDenied(denied, alwaysDenied)。前者会在所有权限被授予时调用,后者会在有权限被拒绝时调用。如果alwaysDenied参数为true,表示用户总是拒绝了该权限,并勾选了“不再询问”选项。

5. 在Activity或Fragment中调用PermissionUtil

现在我们已经完成了所有需要的组件,可以开始在ActivityFragment中调用权限请求。

public class MainActivity extends AppCompatActivity implements PermissionCallback {

    private static final String PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO;
    private static final String PERMISSION_CAMERA = Manifest.permission.CAMERA;

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

    @Override
    protected void onResume() {
        super.onResume();

        // 检查录音权限
        String[] permissions = {PERMISSION_RECORD_AUDIO};
        if (PermissionUtil.hasPermission(this, PERMISSION_RECORD_AUDIO)) {
            onPermissionGranted();
        } else {
            if (!PermissionUtil.shouldShowRequestPermissionRationale(this, PERMISSION_RECORD_AUDIO)) {
                Toast.makeText(this, R.string.permission_no_granted, Toast.LENGTH_SHORT).show();
            }
            PermissionUtil.requestPermission(this, PERMISSION_RECORD_AUDIO, PERMISSION_RECORD_AUDIO.hashCode());
        }

        // 检查相机权限
        permissions[0] = PERMISSION_CAMERA;
        if (PermissionUtil.hasPermission(this, PERMISSION_CAMERA)) {
            onPermissionGranted();
        } else {
            if (!PermissionUtil.shouldShowRequestPermissionRationale(this, PERMISSION_CAMERA)) {
                Toast.makeText(this, R.string.permission_no_granted, Toast.LENGTH_SHORT).show();
            }
            PermissionUtil.requestPermission(this, PERMISSION_CAMERA, PERMISSION_CAMERA.hashCode());
        }
    }

    @Override
    public void onPermissionGranted() {
        // 权限请求成功操作
        Toast.makeText(this, R.string.permission_granted, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onPermissionDenied(List<String> denied, boolean alwaysDenied) {
        // 权限请求失败操作
        if (alwaysDenied && !denied.isEmpty()) {
            String message = getString(R.string.permission_denied_always_message, TextUtils.join(", ", denied));
            new AlertDialog.Builder(this)
                    .setTitle(R.string.permission_denied_always_title)
                    .setMessage(message)
                    .setPositiveButton(R.string.permission_setting, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            PermissionUtil.showAppSettings(MainActivity.this);
                        }
                    })
                    .setNegativeButton(R.string.permission_not_now, null)
                    .create().show();
        } else {
            Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_SHORT).show();
        }
    }

}

onResume()方法中,我们检查申请RECORD_AUDIOCAMERA权限。如果已经授予权限,则调用onPermissionGranted()方法,否则调用requestPermission()方法请求权限。当权限请求完成后,onRequestPermissionsResult方法会被调用。这个方法中判断所有权限是否授权,并根据情况调用onPermissionGranted()onPermissionDenied()方法。

这样,我们就完成了一整个完美封装流程,并在实际开发中得到了应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:android6.0运行时权限完美封装方法 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • Windows系统环境变量大全(XP/Win7/Win8)

    Windows系统环境变量大全(XP/Win7/Win8)攻略 什么是环境变量? 在Windows操作系统中,环境变量是一种存储系统配置信息的机制。它们是一些键值对,用于指定系统和应用程序的行为。环境变量可以在系统范围内或用户范围内设置,并且可以在命令提示符、批处理文件和应用程序中使用。 如何访问环境变量设置? 要访问环境变量设置,可以按照以下步骤进行操作:…

    other 2023年8月9日
    00
  • mac系统如何配置adb

    Mac系统如何配置ADB ADB是Android Debug Bridge的缩写,是Android开发工具中一个非常核心的部分。ADB可以用来连接和控制Android设备,进行文件传输和调试等操作。本文将简单介绍如何在Mac系统中配置并使用ADB。 1. 安装Android SDK 在使用ADB之前,我们需要安装Android SDK。Android SDK…

    其他 2023年3月29日
    00
  • Android学习之基础知识四-Activity活动8讲(活动的灵活运用)

    Android学习之基础知识四-Activity活动8讲(活动的灵活运用) 在Android开发中,Activity是非常重要的一个组件,它负责用户界面的呈现和事件响应。在之前的文章中,我们已经学习了Activity的基础知识,本篇文章将为大家介绍Activity的灵活运用技巧,帮助大家更好地开发应用程序。 1. 启动Activity Activity的启动…

    其他 2023年3月28日
    00
  • C#使用ToUpper()与ToLower()方法将字符串进行大小写转换的方法

    C#使用ToUpper()与ToLower()方法将字符串进行大小写转换的方法 在C#中,我们可以使用ToUpper()和ToLower()方法来将字符串转换为大写或小写。这两个方法都是字符串类型的扩展方法,可以直接应用于字符串对象。 使用ToUpper()方法将字符串转换为大写 ToUpper()方法将字符串中的所有字符转换为大写形式,并返回转换后的新字符…

    other 2023年8月17日
    00
  • java时间 java.util.Calendar深入分析

    Java时间:java.util.Calendar深入分析 java.util.Calendar是Java日期和时间处理的核心类之一。它能够处理Java程序中与日期和时间相关的操作。本文将深入介绍Calendar类,让开发者更加全面地了解它的使用。 1. Calendar类的概述 Calendar类是一个抽象类,用于将日期和时间抽象成一个可以操作的对象,使得…

    other 2023年6月27日
    00
  • 浅析Java内存模型与垃圾回收

    浅析Java内存模型与垃圾回收 1. Java内存模型 Java内存模型(Java Memory Model,JMM)定义了Java程序中线程如何与内存交互的规范。它确保了多线程环境下的可见性、有序性和原子性。 1.1 主内存与工作内存 Java内存模型中有两个重要的概念:主内存和工作内存。 主内存是所有线程共享的内存区域,包含了所有的变量。 每个线程都有自…

    other 2023年8月1日
    00
  • 关于同时使用swiper和echarts遇到的问题及解决方法

    针对同时使用swiper和echarts遇到的问题及解决方法,以下是完整攻略: 问题描述 在同时使用Swiper和Echarts时,可能会出现以下问题: Echarts在swiper中无法完全显示或者显示错位; Swiper在使用Echarts时滑动不流畅,卡顿等问题。 解决方法 针对以上问题,我们可以采用以下方法解决: 1. Echarts无法完全显示或者…

    other 2023年6月27日
    00
  • Window系统的批处理变量大全

    Window系统的批处理变量大全攻略 介绍 在Windows系统的批处理脚本中,变量是一种非常有用的工具,可以存储和操作数据。本攻略将详细介绍Window系统的批处理变量,并提供一些示例说明。 系统变量 Windows系统提供了一些默认的系统变量,可以在批处理脚本中直接使用。以下是一些常用的系统变量: %DATE%:当前日期。 %TIME%:当前时间。 %U…

    other 2023年8月16日
    00
合作推广
合作推广
分享本页
返回顶部