【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 完整代码示例 | 申请权限 | 申请权限原理对话框 | 引导用户手动设置权限对话框 )(二)

简介: 【Android 应用开发】Google 官方 EasyPermissions 权限申请库 ( 完整代码示例 | 申请权限 | 申请权限原理对话框 | 引导用户手动设置权限对话框 )(二)

三、引导用户手动设置权限对话框


如果用户在 授权界面 选择了 “拒绝, 不要再询问” , 这事比上面的还要大 , 此时权限对话框根本就无法弹出 , 只能到设置界面取设置权限 ;

image.png


引导用户手动设置权限对话框 : 该对话框的作用就是 引导用户跳转到设置界面 , 设置需要的权限 ;


这个对话框需要自定义 , 但是 EasyPermission 库给提供了一个 AppSettingsDialog 对话框 , 其作用就是引导用户跳转到设置界面 , 设置对话框 ;


判定是否存在永久拒绝的权限 : 调用 EasyPermissions.somePermissionPermanentlyDenied 方法 , 判定是否存在被永久拒绝的权限 , 如果有 , 那么 创建 AppSettingsDialog 对话框 ,


弹出 引导用户手动设置权限对话框 代码示例 :


   

// 如果申请的权限中有任何一个权限存在 永久拒绝 的情况
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            // 设置 引导用户前往设置界面 自行设置权限的引导对话框
            AppSettingsDialog.Builder(this)
                .setTitle("需要手动设置权限")
                .setRationale("存在永久拒绝的权限 , 需要手动前往设置界面为应用进行授权")
                .setPositiveButton("前往设置界面")
                .setNegativeButton("不使用该功能")
                .build().show()
        }


弹出的对话框样式 :

image.png



如果点击 “前往设置界面” , 就会跳转到 应用信息 设置界面 :


image.png


操作完毕返回操作 : 从该对话框返回 , 不管是点击哪个按钮 , 都会进入该方法中 , 此时判定是否授权成功 , 如果没有授权成功 , 给用户进行提示 ; 如果有授权成功 , 那么进行后续操作 ;


 

/**
     * 从 AppSettingsDialog 界面中返回, 回调该方法
     */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE){
            // 判断五种权限是否申请成功
            var hasPermissions =
                EasyPermissions.hasPermissions(this, *PERMMISSIONS)
            // 界面中显示权限申请结果
            Toast.makeText(this, "设置界面用户手动申请权限结果 $hasPermissions",
                Toast.LENGTH_LONG).show()
        }
    }





四、在 AndroidManifest.xml 中配置权限


一定不要忘记在 AndroidManifest.xml 中配置权限 , 否则无法使用 ;


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kim.hsl.easypermissions">
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_SMS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>




五、完整代码示例


package kim.hsl.easypermissions
import android.Manifest
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import pub.devrel.easypermissions.AfterPermissionGranted
import pub.devrel.easypermissions.AppSettingsDialog
import pub.devrel.easypermissions.EasyPermissions
import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks
import pub.devrel.easypermissions.EasyPermissions.RationaleCallbacks
/**
 * 权限申请码, 作为权限申请的标识
 * 注意 : const val 常量才是 Java 中的 public static final 对等的常量值
 *        const val 常量只能定义在 Kotlin 文件中, 或 object 对象表达式中, 不能定义在类中
 */
const val PERMISSION_REQUEST_CODE : Int = 100;
class MainActivity : AppCompatActivity(), PermissionCallbacks, RationaleCallbacks{
    val TAG = "MainActivity"
    /**
     * 当做可变参数时 , 前面加上 * 符号 , 展开数组
     * *PERMMISSIONS 等同于可变参数
     */
    var PERMMISSIONS: Array<String> = arrayOf(Manifest.permission.CAMERA,
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.READ_CONTACTS,
        Manifest.permission.READ_SMS,
        Manifest.permission.WRITE_EXTERNAL_STORAGE)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
    /*
        一 、 用户点击按钮开始申请权限
     */
    fun onCLick(view : View){
        // 申请权限, 并在权限申请通过后 , 在执行一次该方法
        doSomethingWithPermissions();
    }
    /**
     * AfterPermissionGranted 注解的作用是 , 当 请求吗 666 对应的权限申请全部通过后
     * 再次回调一次该方法 . ( 相当于调用了两次该方法 )
     */
    @AfterPermissionGranted( PERMISSION_REQUEST_CODE )
    fun doSomethingWithPermissions(){
        Log.i(TAG, "doSomethingWithPermissions")
        // 数组前加上 * 符号 , 可以将数组展开 , 转为可变数组
        // 调用 EasyPermissions.hasPermissions 方法判定是否已经申请该权限
        if(EasyPermissions.hasPermissions(this,
                *PERMMISSIONS)){
            // 如果有上述权限, 执行该操作
            Toast.makeText(this, "权限申请通过", Toast.LENGTH_LONG).show()
        }else{
            // 如果没有上述权限 , 那么申请权限
            EasyPermissions.requestPermissions(
                this,
                "权限申请原理对话框 : 描述申请权限的原理",
                PERMISSION_REQUEST_CODE,
                // 数组前加上 * 符号 , 可以将数组展开 , 转为可变数组
                *PERMMISSIONS
            )
        }
    }
    /**
     * 二 、 重写 Activity 的 onRequestPermissionsResult 方法
     *    主要是在该方法中使用 EasyPermissions 进一步处理权限申请后续结果
     */
    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<out String>, grantResults: IntArray){
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        Log.i(TAG, "onRequestPermissionsResult")
        // 进一步使用 EasyPermissions 处理后续结果
        EasyPermissions.onRequestPermissionsResult(
            requestCode, permissions, grantResults, this);
    }
    /*
        三 、 实现 EasyPermissions.PermissionCallbacks 接口中的方法
     */
    /**
     * EasyPermissions.PermissionCallbacks 接口中实现的方法
     * 调用 EasyPermissions.requestPermissions() 方法申请权限 , 用户点击拒绝授权后会回调该方法
     */
    override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
        Log.i(TAG, "onPermissionsDenied 用户拒绝权限申请 , 请求码 $requestCode , 拒绝的权限 : $perms")
        // 如果申请的权限中有任何一个权限存在 永久拒绝 的情况
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            // 设置 引导用户前往设置界面 自行设置权限的引导对话框
            AppSettingsDialog.Builder(this)
                .setTitle("需要手动设置权限")
                .setRationale("存在永久拒绝的权限 , 需要手动前往设置界面为应用进行授权")
                .setPositiveButton("前往设置界面")
                .setNegativeButton("不使用该功能")
                .build().show()
        }
    }
    /**
     * EasyPermissions.PermissionCallbacks 接口中实现的方法
     * 调用 EasyPermissions.requestPermissions() 方法申请权限 , 用户点击同意授权后会回调该方法
     */
    override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
        Log.i(TAG, "onPermissionsGranted 用户同意权限申请 , 请求码 $requestCode , 拒绝的权限 : $perms")
    }
    /*
        四 、 实现 EasyPermissions.RationaleCallbacks 接口中的方法
     */
    /**
     * EasyPermissions.RationaleCallbacks 接口中的方法
     *
     */
    override fun onRationaleDenied(requestCode: Int) {
        Log.i(TAG, "权限申请原理对话框中选择 取消 , 请求码 $requestCode")
    }
    /**
     * EasyPermissions.RationaleCallbacks 接口中的方法
     *
     */
    override fun onRationaleAccepted(requestCode: Int) {
        Log.i(TAG, "权限申请原理对话框中选择 确定 , 请求码 $requestCode")
    }
    /*
        五 、实现从 AppSettingsDialog 对话框返回的逻辑
             主要是检查用户永久拒绝后, 查看引导用户设置权限的结果
     */
    /**
     * 从 AppSettingsDialog 界面中返回, 回调该方法
     */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == AppSettingsDialog.DEFAULT_SETTINGS_REQ_CODE){
            // 判断五种权限是否申请成功
            var hasPermissions =
                EasyPermissions.hasPermissions(this, *PERMMISSIONS)
            // 界面中显示权限申请结果
            Toast.makeText(this, "设置界面用户手动申请权限结果 $hasPermissions",
                Toast.LENGTH_LONG).show()
        }
    }
}







六、GitHub 地址


https://github.com/han1202012/EasyPermissions


目录
相关文章
|
10月前
|
Android开发 开发者
Android设置View是否可用
在Android开发中,有时需要将布局设置为不可点击状态(失去焦点)。常见的解决方法是使用`setOnClickListener(null)`,但本文介绍一种更通用的方式:通过封装`setViewEnabled`方法实现。该方法可递归设置View及其子View的启用状态,支持传入目标View和布尔值(`true`为可用,`false`为禁用)。例如,调用`setViewEnabled(edittext, false)`即可禁用EditText。文章附有源码及示例动图,帮助开发者快速理解与应用。
225 1
|
存储 XML 开发工具
探索安卓应用开发:从基础到进阶
在这篇文章中,我们将一起踏上安卓应用开发的旅程。不论你是编程新手还是希望提升技能的开发者,这里都有你需要的东西。我们会从最基础的概念开始,逐步深入到更复杂的主题。文章将涵盖开发环境设置、用户界面设计、数据处理以及性能优化等方面。通过理论与实践的结合,你将能够构建出既美观又高效的安卓应用。让我们一起开启这段技术之旅吧!
|
Android开发 Swift iOS开发
深入探索iOS与Android操作系统的架构差异及其对应用开发的影响
在当今数字化时代,移动设备已经成为我们日常生活和工作不可或缺的一部分。其中,iOS和Android作为全球最流行的两大移动操作系统,各自拥有独特的系统架构和设计理念。本文将深入探讨iOS与Android的系统架构差异,并分析这些差异如何影响应用开发者的开发策略和用户体验设计。通过对两者的比较,我们可以更好地理解它们各自的优势和局限性,从而为开发者提供有价值的见解,帮助他们在这两个平台上开发出更高效、更符合用户需求的应用。
|
10月前
|
Android开发 开发者
Android中Dialog位置+样式的设置
本文介绍了在Android开发中如何设置Dialog的位置和样式。通过自定义`MyDialog`类,可以灵活调整Dialog的显示位置,例如将其固定在屏幕底部,并设置宽度匹配父布局。同时,文章还展示了如何模仿Android原生Dialog样式,通过定义`MyDialogStyle`去除标题栏、设置背景透明度、添加阴影效果以及配置点击外部关闭等功能,从而实现更加美观和符合需求的Dialog效果。代码示例详细,便于开发者快速上手实现。
540 2
|
搜索推荐 Android开发 开发者
安卓应用开发中的自定义控件实践
在安卓应用开发的广阔天地中,自定义控件如同璀璨的星辰,点亮了用户界面设计的夜空。它们不仅丰富了交互体验,更赋予了应用独特的个性。本文将带你领略自定义控件的魅力,从基础概念到实际应用,一步步揭示其背后的原理与技术细节。我们将通过一个简单的例子——打造一个具有独特动画效果的按钮,来展现自定义控件的强大功能和灵活性。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇通往更高阶UI设计的大门。
204 2
|
缓存 监控 前端开发
探索Android应用开发之旅:从新手到专家
【10月更文挑战第42天】本文将带你踏上Android应用开发的旅程,无论你是初学者还是有经验的开发者。我们将一起探索如何从零开始创建你的第一个Android应用,并逐步深入到更高级的主题,如自定义视图、网络编程和性能优化。通过实际示例和清晰的解释,你将学会如何构建高效、吸引人的Android应用。让我们一起开启这段激动人心的旅程吧!
191 2
|
传感器 XML IDE
探索安卓应用开发:从基础到进阶
【10月更文挑战第23天】在数字化时代的浪潮中,移动应用已成为人们日常生活的延伸。本文以安卓平台为例,深入浅出地介绍了如何从零开始构建一个安卓应用,涵盖了开发环境搭建、基本组件使用、界面设计原则以及进阶技巧等关键步骤。通过实例演示和代码片段,引导读者逐步掌握安卓应用开发的核心技能,旨在激发更多开发者对安卓平台的探索热情,并为初学者提供一条清晰的学习路径。
|
开发框架 前端开发 Android开发
探索安卓和iOS应用开发中的跨平台解决方案
【10月更文挑战第42天】在移动应用开发的广阔天地中,安卓和iOS系统如同两座巍峨的山峰,分别占据着半壁江山。开发者们在这两座山峰之间穿梭,努力寻找一种既能节省资源又能提高效率的跨平台开发方案。本文将带你走进跨平台开发的世界,探讨各种解决方案的优势与局限,并分享一些实用的代码示例,助你在应用开发的道路上更加游刃有余。
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
199 4
|
Android开发 Swift iOS开发
探索iOS与安卓应用开发的差异性
探索iOS与安卓应用开发的差异性
262 2

推荐镜像

更多