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

yizhihongxing

为了在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日

相关文章

  • Android App中使用Glide加载图片的教程

    当今移动应用程序很少可以没有网络请求和图像加载。图像是一个通用的数据类型,作为应用程序重要的一部分,必须被优化以获得最好的用户体验。 Glide是一个基于Google Image Library(API)的Android开源图片加载库。它具有诸如模拟淡入淡出效果的高级功能。Glide处理图像,即使是大型的图像,也可以保持图像的清晰度和速度。 引入依赖 在项目…

    other 2023年6月25日
    00
  • python 类的基础详解与应用

    Python 类的基础详解与应用 什么是类? 类是Python中的一种基本数据结构,可以用来组织相关的变量和方法。类定义了一种数据类型,并且支持实例化一个或多个对象。每个对象都可以访问特定的变量和方法,这些变量和方法在类的定义中被定义。类中的变量称为属性,类中的函数称为方法。 创建类 创建一个类的语法如下所示: class ClassName: def __…

    other 2023年6月26日
    00
  • 从浅入深带你掌握Golang数据结构map

    从浅入深带你掌握Golang数据结构map 什么是map map是Golang中非常常用的一种数据结构,类似于其他语言中的哈希表。map是一种无序的键值对数据结构,通过key来快速定位和访问对应的value。map的key可以是任何可比较类型(如int,float等),value可以是任何类型。 map的基本操作 创建map 创建map的方式如下所示: va…

    other 2023年6月27日
    00
  • js打开新页面的几种方式

    js打开新页面的几种方式 在开发Web应用中,我们常常需要在当前页面打开一个链接,但又不希望离开当前页面。下面将介绍几种使用JS在新窗口或新标签页中打开链接的方式。 使用window.open方法 使用window.open方法可以打开一个指定URL的新窗口或新标签页,该方法接受三个参数:URL、窗口名称和参数字符串。 window.open(‘http:/…

    其他 2023年3月28日
    00
  • Win10怎么自定义设置文件资源管理器打开位置?

    当我们在 Windows 10 中打开文件资源管理器时,默认情况下会打开“快速访问”页面,也就是最近访问和收藏的文件和文件夹列表。然而,我们可能希望直接打开某个特定的文件夹,比如我们项目常用的文件夹,这时就需要对文件资源管理器的默认打开位置进行自定义设置。以下是详细的攻略: 1. 打开文件资源管理器 首先,我们需要在 Windows 10 中打开文件资源管理…

    other 2023年6月27日
    00
  • linux 断网 扫描基本命令

    当Linux系统出现网络问题时,可以使用一些基本命令来扫描和诊断问题。本文将为您提供Linux断网扫描基本命令的完整攻略,包括其原理、实现方法和示例。 原理 当Linux系统出现网络问题时,可以使用一些基本命令来扫描和诊断问题。这些命令可以帮助您确定网络连接是否正常,以及确定网络问题的根本原因。以下是一些常用的Linux网络扫描命令: ping:用于测试网络…

    other 2023年5月7日
    00
  • ios基础篇(二十七)——json解析

    以下是关于“iOS基础篇(二十七)——JSON解析”的完整攻略: 什么是JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式易于阅读和编,也易于机器解析和生成。JSON数据格式是一种键值对的数据结构,可以表示数字、字符串布尔值、数组和对象等数据类型。 JSON解析 在iOS中,可以使用NSJSONSeriali…

    other 2023年5月7日
    00
  • apk是什么文件格式?.apk文件怎么打开?

    APK是什么文件格式? APK是Android应用程序包(Android Package)的缩写,它是一种用于在Android操作系统上安装和分发应用程序的文件格式。APK文件实际上是一个压缩文件,其中包含了应用程序的所有组件和资源,如代码、图像、音频和视频等。 .APK文件怎么打开? 要打开APK文件,您可以按照以下步骤进行操作: 使用Android设备打…

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