比Rxpermission更简洁的权限申请封装

写这篇文章的原因主要是为了加深下印象吧,也方便自己后来的复习,同时呢,我之前运行权限也是用的rxpermission来进行权限申请的,但是看了这篇文章fragment申请权限后,除了学到了fragment的骚操作,自己还在这篇文章的基础上进行了封装,使得权限申请更为方便,甚至比rxpermissiom的权限申请更少了些许代码
因为最近自己在学习kotlin,所以我这里就改用了kotlin来写了,这也算活学活用吧

/**
 * Created by alan on  2019/4/4 14:50
 */
@SuppressLint("CheckResult", "NewApi")
class PermissionFragment : Fragment() {

    private val callBacks = SparseArray<PermissiomCallBack.CallBack>()
    private val eachCallBacks = SparseArray<PermissiomCallBack.EachCallBack>()
    private var pers: Array<String>? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
		//在activity被重新创建的时候,保证fragment实例不会被重新创建
        retainInstance = true

    }


    /**
     * 一次性请求多个权限并且全部被授权才会回调ongranded
     */
    fun requestPermissons(permission: Array<String>, callback: PermissiomCallBack.CallBack) {
        pers = permission
        var permissions = filter(permission).toTypedArray()
        if (permissions.isEmpty()) return
        //判断权限是否被禁止且不再询问
        if (isNeverAsk(permissions)) {
            showOpenPermissionSettingDialog(permissions)
            return
        }
        val requestCode: Int = generateCode()
        callBacks.put(requestCode, callback)
        requestPermissions(permissions, requestCode)
    }


    /*
    * 每个权限的请求结果都会被封装到permission类中并且回调到callback的回调方法中
    * */
    fun requestEachPermission(permission: Array<String>, callback: PermissiomCallBack.EachCallBack) {
        pers = permission
        var permissions = filter(permission).toTypedArray()
        if (permissions.isEmpty()) return
        if (isNeverAsk(permissions)) {
            showOpenPermissionSettingDialog(permissions)
            return
        }
        val requestCode: Int = generateCode()
        eachCallBacks.put(requestCode, callback)
        requestPermissions(permissions, requestCode)
    }


/*
* 弹出打开被禁掉且不再询问的权限的对话框
* */
private fun showOpenPermissionSettingDialog(permission: Array<String>) {
    SettingDialog.getInstance().setContent("需要打开${PermissionToChinese.toChinese(permission[0])}权限才可以使用该功能").setOnClickListener(object : SettingDialog.OnClickListener {
        override fun onPositive() {
            jumbToPermissionSetting()
        }

    }).show(activity!!.supportFragmentManager, "SettingDialog")
}


    /*
    * 去权限设置页面
    * */
    private fun jumbToPermissionSetting() {
        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
        val uri = Uri.fromParts("package", activity?.packageName, null)
        intent.data = uri
        startActivityForResult(intent, 1001)
    }


    /*
    * 权限是否被设置了不再询问
    * */
    private fun isNeverAsk(permissions: Array<String>): Boolean {
        var isNever = false
        for (per in permissions) {
            if (!activity!!.shouldShowRequestPermissionRationale(per)) {
                isNever = true
                break
            }
        }
        return isNever
    }


    /**
     * 生成随机的requestcode
     */
    private fun generateCode(): Int {
        //生成五位随机数
        var code: Int = Random().nextInt(10000)
        var times = 0
        do {
            times++
            if (callBacks.get(code) == null) break
        } while (10 > times)
        return code
    }


    /**
     * 每个权限单独回调到callback中
     */
    private fun handleEachPermission(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        var callBack = eachCallBacks.get(requestCode)
        if (callBack == null) return
        eachCallBacks.remove(requestCode)
        val permission = Permission()

        //android版本小于6.0
        if (Build.VERSION.SDK_INT < M) {
            allGranded(callBack, permissions)
            return
        }
        for ((index, e) in grantResults.withIndex()) {
            permission.name = permissions[index].substring(permissions[index].lastIndexOf(".") + 1)
            permission.isGranded = if (e == PackageManager.PERMISSION_DENIED) false else true
            callBack.onResult(permission)

        }
    }


    /*
    * 权限全部被授权
    * */
    private fun allGranded(callBack: PermissiomCallBack.EachCallBack, permissions: Array<out String>) {
        permissions.forEach { s ->
            callBack.onResult(Permission(s.substring(s.lastIndexOf(".") + 1), true))
        }

    }


    /**
     * 全部申请结果通过回调ongranded   否则  回调ondenied
     */
    private fun hadlePermissionCallBack(requestCode: Int, grantResults: IntArray) {
        val callBack = callBacks.get(requestCode)
        if (callBack == null) return
        callBacks.remove(requestCode)
        if (Build.VERSION.SDK_INT < M) {
            callBack.onGranded()
            return
        }


        grantResults.forEach { i ->
            if (i != PackageManager.PERMISSION_GRANTED) {
                callBack.onDenied()
                return
            }
        }

        callBack.onGranded()

    }


    /**
     * 过滤掉已经被授权的权限
     */
    fun filter(permissions: Array<String>): ArrayList<String> {
        var pers = ArrayList<String>()
        permissions.forEach { s ->
            if (activity?.checkSelfPermission(s) != PackageManager.PERMISSION_GRANTED) pers.add(s)
        }

        return pers
    }


    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        hadlePermissionCallBack(requestCode, grantResults)
        handleEachPermission(requestCode, permissions, grantResults);
    }


}

这里我特别处理了版本低于6.0时的情况和当一些权限被禁掉且不再询问的时候弹出自定义的dialog来询问用户是否要跳到设置页面打开权限,已经被授权的权限就会被过滤掉

 /**
     * 过滤掉已经被授权的权限
     */
    fun filter(permissions: Array<String>): ArrayList<String> {
        var pers = ArrayList<String>()
        permissions.forEach { s ->
            if (activity?.checkSelfPermission(s) != PackageManager.PERMISSION_GRANTED) pers.add(s)
        }

        return pers
    }

    /*
    * 弹出打开被禁掉且不再询问的权限的对话框
    * */
    private fun showOpenPermissionSettingDialog(permission: Array<String>) {
        SettingDialog.getInstance().setContent("需要打开${PermissionToChinese.toChinese(permission[0])}权限才可以使用该功能").setOnClickListener(object : SettingDialog.OnClickListener {
            override fun onPositive() {
                jumbToPermissionSetting()
            }

        }).show(activity!!.supportFragmentManager, "SettingDialog")
    }

最后用一个帮助类来包裹下,是调用者不知道内部是使用的fragment来申请的权限


object PermissionHelper {

    val FRAGMENT_TAG = "PermissionFragment"


    /**
     * 一次性请求权限
     */
    @JvmStatic
    fun requestPermissions(pers: Array<String>, callback: PermissiomCallBack.CallBack) {
        val fragmentManage = (AppManager.instance.getTopActivity() as AppCompatActivity).supportFragmentManager
        var fragment = fragmentManage.findFragmentByTag(FRAGMENT_TAG)
        if (fragment == null) {
            fragment = PermissionFragment()
            fragmentManage.beginTransaction().add(fragment, FRAGMENT_TAG).commit()
            fragmentManage.executePendingTransactions()
        }
        fragment as PermissionFragment
        fragment.requestPermissons(pers, callback)
    }


    /**
     * 别分返回每个权限的请求结果
     */
    @JvmStatic
    fun requestEachPermissions(permissions: Array<String>, callback: PermissiomCallBack.EachCallBack) {
        val fragmentManage = (AppManager.instance.getTopActivity() as AppCompatActivity).supportFragmentManager
        var fragment = fragmentManage.findFragmentByTag(FRAGMENT_TAG)
        if (fragment == null) {
            fragment = PermissionFragment()
            fragmentManage.beginTransaction().add(fragment, FRAGMENT_TAG).commit()
            fragmentManage.executePendingTransactions()
        }
        fragment as PermissionFragment
        fragment.requestEachPermission(permissions, callback)
    }


}

最后就是调用了,很简单

 PermissionHelper.requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CALL_PHONE}, new PermissiomCallBack.CallBack() {
                @Override
                public void onGranded() {
                    
                }

                @Override
                public void onDenied() {

                }
            });
        });

或者使用每个权限申请各自的回调结果来判断,就是有多少个权限,就会回调多少次 onResult方法,当然如果传入的权限中有一些是已经被授权的了,就会被过滤掉了

  PermissionHelper.requestEachPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CALL_PHONE}, new PermissiomCallBack.EachCallBack() {
            @Override
            public void onResult(@NotNull Permission permission) {
                
            }
        });

这里的onResult方法中的permission其实就两个成员变量

class Permission {
    var name = ""
    var isGranded = false

    constructor(name: String, isGranded: Boolean) {
        this.name = name
        this.isGranded = isGranded
    }

    constructor()
}

name -> 权限的名字
isGranded -> 权限是否被授权

顺便贴下其他几个类的代码吧

class SettingDialog : DialogFragment() {
    var onClickListener: OnClickListener? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.dialog_setting, container, false)

        view.findViewById<TextView>(R.id.tv_cancel).setOnClickListener {
            with(onClickListener) {
                this?.onCancel()
            }
            dismiss()
        }
        view.findViewById<TextView>(R.id.tv_positive).setOnClickListener {
            with(onClickListener) {
                this?.onPositive()
            }
            dismiss()
        }
        view.findViewById<TextView>(R.id.tv_content).text = arguments?.getString("content")

        return view
    }

    fun setContent(conetent: String): SettingDialog {
        val bundle = Bundle()
        bundle.putString("content", conetent)
        arguments = bundle
        return this
    }


    fun setOnClickListener(onClickListener: OnClickListener?): SettingDialog {
        this.onClickListener = onClickListener
        return this
    }


    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        var dialog = super.onCreateDialog(savedInstanceState)
        dialog.window.setBackgroundDrawableResource(R.drawable.bg_round4)


        return dialog
    }


    fun show() {
        show(activity?.supportFragmentManager, "SettingDialog")
    }

    companion object {
        fun getInstance() = SettingDialog()
    }

    interface OnClickListener {
        fun onPositive()
        fun onCancel() {

        }
    }

}
object PermissionToChinese {

    @JvmStatic
    fun toChinese(permission:String):String{
        var str=""
        when(permission){
            "android.permission.ACCESS_FINE_LOCATION" ->{str="位置"}
            "android.permission.CAMERA" ->{str="相机"}
            "android.permission.WRITE_EXTERNAL_STORAGE" ->{str="存储"}
            "android.permission.READ_EXTERNAL_STORAGE" ->{str="存储"}
            "android.permission.READ_PHONE_STATE" ->{str="电话"}
            "android.permission.ACCESS_NETWORK_STATE" ->{str="位置"}
            "android.permission.ACCESS_WIFI_STATE" ->{str="wify"}
         else -> str= "部分"
        }
        return str
    }



}
/**
 * Created by alan on  2019/4/4 17:40
 */
interface PermissiomCallBack {


    interface CallBack {
        fun onGranded()
        fun onDenied()
    }

    interface EachCallBack {
        fun onResult(permission: Permission)
    }

}
class AppManager {
    fun getActivityStack(): Stack<Activity>? {
        return activityStack
    }

    private var activityStack: Stack<Activity>? = null


    private constructor()

    companion object {
        val instance by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { AppManager() }


    }

    /* */
    /**
     * 单一实例
     *//*
    fun getInstance(): AppManager {
        if (instance == null) {
            instance = AppManager()
        }
        return instance as AppManager
    }*/

    /**
     * 添加Activity到堆栈
     */
    fun addActivity(activity: Activity) {
        if (activityStack == null) {
            activityStack = Stack()
        }
        activityStack!!.add(activity)
    }

    /**
     * 获取栈顶Activity(堆栈中最后一个压入的)
     */
    fun getTopActivity(): Activity {
        return activityStack!!.lastElement()
    }

    /**
     * 结束栈顶Activity(堆栈中最后一个压入的)
     */
    fun finishTopActivity() {
        val activity = activityStack!!.lastElement()
        finishActivity(activity)
    }

    /**
     * 结束指定类名的Activity
     *
     * @param cls
     */
    fun finishActivity(cls: Class<*>) {
        val iterator = activityStack!!.iterator()
        while (iterator.hasNext()) {
            val activity = iterator.next() as Activity
            if (activity.javaClass == cls) {
                iterator.remove()
                activity.finish()
            }
        }
    }

    /**
     * 结束所有Activity
     */
    fun finishAllActivity() {
        var i = 0
        val size = activityStack!!.size
        while (i < size) {
            if (null != activityStack!!.get(i)) {
                activityStack!!.get(i).finish()
            }
            i++
        }
        activityStack!!.clear()
    }

    /**
     * 退出应用程序
     */
    fun appExit() {
        try {
            finishAllActivity()
            System.exit(0)
            android.os.Process.killProcess(android.os.Process.myPid())

        } catch (e: Exception) {
        }

    }

    /**
     * 结束指定的Activity
     */
    fun finishActivity(activity: Activity?) {
        var activity = activity
        if (activity != null) {
            activityStack!!.remove(activity)
            activity.finish()
            activity = null
        }
    }

    /**
     * 得到指定类名的Activity
     */
    fun getActivity(cls: Class<*>): Activity? {
        for (activity in activityStack!!) {
            if (activity.javaClass == cls) {
                return activity
            }
        }
        return null
    }
}

ok,代码总体还是挺简单的,就是如果没有了解多kotlin的同学就会看得比较迷茫了,这里也给出代码的地址,想了解的可以去看下传送门

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值