一、自定义

1.在项目的BaseActivity添加代码

/**
 * 动态获权
 * */
/**
 * 动态获权请求值
 */
private var REQUEST_CODE_PERMISSION = 0x00099
protected val TAG = this.javaClass.simpleName

/**
 * 请求权限
 * 动态获权
 * @param permissions 请求的权限
 * @param requestCode 请求权限的请求码
 */
open fun requestPermission(
    permissions: Array<String>,
    requestCode: Int
) {
    REQUEST_CODE_PERMISSION = requestCode
    if (checkPermissions(permissions)) {
        permissionSuccess(REQUEST_CODE_PERMISSION)
    } else {
        try {
            val needPermissions =
                getDeniedPermissions(permissions)
            ActivityCompat.requestPermissions(
                this,
                needPermissions.toTypedArray(),
                REQUEST_CODE_PERMISSION
            )
        } catch (e: Exception) {
            Log.e("BaseActivity", "获取权限失败 Exception = $e")
        }
    }
}

/**
 * 检测所有的权限是否都已授权
 */
fun checkPermissions(permissions: Array<String>): Boolean {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        return true
    }
    for (permission in permissions) {
        if (ContextCompat.checkSelfPermission(
                this,
                permission
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            return false
        }
    }
    return true
}

/**
 * 获取权限集中需要申请权限的列表
 */
fun getDeniedPermissions(permissions: Array<String>): List<String> {
    val needRequestPermissionList: MutableList<String> =
        ArrayList()
    for (permission in permissions) {
        if (ContextCompat.checkSelfPermission(this, permission) !=
            PackageManager.PERMISSION_GRANTED ||
            ActivityCompat.shouldShowRequestPermissionRationale(this, permission)
        ) {
            needRequestPermissionList.add(permission)
        }
    }
    return needRequestPermissionList
}

/**
 * 系统请求权限回调
 */
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<String?>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == REQUEST_CODE_PERMISSION) {
        if (verifyPermissions(grantResults)) {
            permissionSuccess(REQUEST_CODE_PERMISSION)
        } else {
            permissionFail(REQUEST_CODE_PERMISSION)
        }
    }
}

/**
 * 确认所有的权限是否都已授权
 */
fun verifyPermissions(grantResults: IntArray): Boolean {
    for (grantResult in grantResults) {
        if (grantResult != PackageManager.PERMISSION_GRANTED) {
            return false
        }
    }
    return true
}

/**
 * 获取权限成功
 */
open fun permissionSuccess(requestCode: Int) {
    Log.e(TAG, "获取权限成功=$requestCode")
}

/**
 * 权限获取失败
 */
open fun permissionFail(requestCode: Int) {
    Log.e(TAG, "获取权限失败=$requestCode")
}

2.在Activity中调用方法

val REQUEST_PHOTO_CODE = 3002 //获取权限

btnPerssion.setOnClickListener {

val permission = arrayOf(
    Manifest.permission.READ_EXTERNAL_STORAGE,
    Manifest.permission.WRITE_EXTERNAL_STORAGE
)
requestPermission(permission, REQUEST_PHOTO_CODE)

}

  /**
     * 获取头像相关
     * */
    override fun permissionSuccess(requestCode: Int) {
        super.permissionSuccess(requestCode)
        if (requestCode == REQUEST_PHOTO_CODE) { 
           showToast("获取权限成功!")
        }
    }

    override fun permissionFail(requestCode: Int) {
        super.permissionFail(requestCode)
        showToast("您把数据访问禁止了,你将不能享受服务。修改权限可以去设置中修改!")
    }

二、引用框架(OkPermission)

1.在工程下的build中添加

allprojects {
    repositories {
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

2.在module的build中添加 

dependencies {
   .
   .
   .
   .
    //添加OkPermission框架依赖
    implementation 'com.github.kelinZhou:OkPermission:3.1.3'
}

3.AndroidManifest.xml中添加权限

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>

4.在Activity中调用

package com.ruidde.animationtimesdeclinedemo

import android.Manifest
import android.app.AlertDialog
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.kelin.okpermission.OkPermission
import kotlinx.android.synthetic.main.activity_main.*

/**
 * 动画形式的时间递减
 * */
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnPerssion.setOnClickListener {

            /**
             * 可以
             * */
//            OkPermission.with(this)
//                .addDefaultPermissions(
//                    Manifest.permission.CALL_PHONE,
//                    Manifest.permission.CAMERA
//                ).checkAndApply { granted, permissions ->
//                    if (granted) {
//                        Toast.makeText(this, "权限已全部获取", Toast.LENGTH_SHORT).show()
//                    } else {
//                        Toast.makeText(this, "未获取全部权限", Toast.LENGTH_SHORT).show()
//                    }
//                }

            /**
             * 当用户拒绝权限且不再提醒后会引导用户前往设置页面。引导时会有弹窗,而这个弹窗是可以自定义的。
             * */
            OkPermission.with(this)
                .addDefaultPermissions(
                    Manifest.permission.CALL_PHONE,
                    Manifest.permission.CAMERA
                )
                .interceptMissingPermissionDialog {
                    AlertDialog.Builder(this)
                        .setCancelable(false)
                        .setTitle("帮助")
                        .setMessage("缺少拨打电话和拍照权限,请前往设置。")
                        .setNegativeButton("退出") { _, _ ->
                            it.continueWorking(false)
                        }
                        .setPositiveButton("设置") { _, _ ->
                            it.continueWorking(true)
                        }.show()
                }.checkAndApply { granted, permissions ->
                    if (permissions.isEmpty()) {
                        Toast.makeText(this, "权限已全部获取", Toast.LENGTH_SHORT).show()
                    } else {
                        Toast.makeText(this, "未获取全部权限", Toast.LENGTH_SHORT).show()
                    }
                }
        }
    }

}

5.整体的XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/btnPerssion"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="40dp"
        android:background="@color/colorAccent"
        android:textColor="#FFFFFF"
        android:layout_marginTop="20dp"
        android:textSize="20sp"
        android:gravity="center"
        android:text="动态获权"/>

</RelativeLayout>