安卓6.0以上的动态权限申请-kotlin

基于kotlin的对于安卓6.0以上的动态权限申请


安卓6.0以上的动态权限申请-kotlin_第1张图片安卓6.0以上的动态权限申请-kotlin_第2张图片

安卓6.0以上的动态权限申请-kotlin_第3张图片安卓6.0以上的动态权限申请-kotlin_第4张图片


总逻辑为:

(1)启动界面判断是否拥有所需权限

(2)启动时先提示用户本app所需要的权限

(3)用户选择是否接受

(4)不接受将会一直循环权限申请界面

(5)全部权限获取后进入app

在开启app时启用一个PageStartActivity来对权限进行判断与申请

class PageStartActivity : AppCompatActivity() {
    private var mActivity: Activity? = null
    private var mPermApplyDialog: AlertDialog? = null
    private var mPermSettingDialog: AlertDialog? = null
    private var mShowViewDis: Disposable? = null


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requestWindowFeature(Window.FEATURE_NO_TITLE)

        createView()
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
        supportActionBar!!.hide()
    }

    private fun createView(){
        verticalLayout {
            lparams(matchParent, matchParent)
            imageView(R.drawable.page_start){
                scaleType = ImageView.ScaleType.FIT_XY
            }
            val al = alert{
                icon = resources.getDrawable(R.mipmap.ic_launcher)
                title = "温馨提示"
                message = "使用该程序前,需要对手机的相机及储存权限进行申请"
                isCancelable = false
                neutralPressed("我知道了"){
                    initView()
                }
            }
            if(Util.isPermitted(context,true)){
                al.show()
            }else{
                initView()
            }
        }
    }



    private fun initView() {
        mActivity = this
        //动态申请权限
        if (!Util.isPermissionsApply(this, true)) {
            createShowViewSub()
        }
    }

    private fun createShowViewSub() {
        val fl = Flowable.timer(500, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext {
                    startActivity(Intent(mActivity, MainActivity::class.java))
                    finish()
                }

        mShowViewDis = fl.subscribe()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            PERM_SETTING_APPLY_CODE -> if (!Util.isPermissionsApply(this, false)) {     //权限已经全部申请
                if (mPermSettingDialog != null && mPermSettingDialog!!.isShowing()) {
                    mPermSettingDialog!!.dismiss()
                }
                createShowViewSub()
            }
        }
    }

    /**
     * 注册权限申请回调
     *
     * @param requestCode  申请码
     * @param permissions  申请的权限
     * @param grantResults 结果
     */
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
        when (requestCode) {

            Config.PERMS_APPLY_CODE -> if (!Util.isPermissionOk(grantResults)) {   //有未申请的权限
                var isCanShowApplyAgain = false
                for (i in permissions.indices) {
                    if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity!!, permissions[i])) {    //只要有一个权限显示可以弹出继续申请,则可以弹出申请权限对话框
                        isCanShowApplyAgain = true
                        break
                    }
                }
                if (isCanShowApplyAgain) {  //可以继续弹出权限申请
                    showPermApplyDialog()
                } else {    //不能够继续弹出
                    showPermSettingDialog()
                }
            } else {
                createShowViewSub()
            }
        }
    }

    /**
     * 有未申请的权限,未选择不再询问,继续弹出权限申请
     */
    private fun showPermApplyDialog() {
        mPermApplyDialog = AlertDialog.Builder(this)
                .setTitle(R.string.perm_apply_title)
                .setMessage(R.string.perm_apply_msg)
                .setPositiveButton(R.string.apply) { dialogInterface, i -> Util.isPermissionsApply(mActivity!!, true) }
                .setNegativeButton(R.string.cancel) { dialogInterface, i -> finish() }
                .setCancelable(false)
                .create()
        mPermApplyDialog!!.show()
    }

    /**
     * 有未申请的权限,并选了不再询问,进入设置设置应用权限
     */
    private fun showPermSettingDialog() {
        mPermSettingDialog = AlertDialog.Builder(this)
                .setTitle(R.string.perm_apply_title)
                .setMessage(R.string.perm_setting_msg)
                .setPositiveButton(R.string.goto_setting, null)
                .setNegativeButton(R.string.cancel) { dialogInterface, i -> finish() }
                .setCancelable(false)
                .create()
        mPermSettingDialog!!.show()
        //以下方式可以让alertDialog点击时不自动消失
        mPermSettingDialog!!.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
            val intent = Intent()
            //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
            intent.data = Uri.fromParts("package", packageName, null)
            startActivityForResult(intent, PERM_SETTING_APPLY_CODE)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        Util.disposeSubscribe(mShowViewDis!!)
    }

    companion object {
        private val PERM_SETTING_APPLY_CODE = 10
    }
}

util.kt中对于所需的权限进行判断并申请

object Util : ActivityCompat(){
    fun isPermissionOk(grantResults: IntArray): Boolean {
        var isOk = true
        for (i in grantResults.indices) {
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { //含有未申请到的权限
                isOk = false
                break
            }
        }
        return isOk
    }

    fun isPermitted(context: Context, isApplyPerm: Boolean): Boolean{
        var isNeedApplyPerm = false
        val unApplyedList = ArrayList()
        for (i in 0 until PERMISSIONS.size) {
            if (ContextCompat.checkSelfPermission(context, PERMISSIONS[i]) != PackageManager.PERMISSION_GRANTED) {
                unApplyedList.add(PERMISSIONS[i])   //申请过的权限将其删除,不要再提示给用户
            }
        }
        if (unApplyedList.size > 0) { //有未申请的权限,去申请
            isNeedApplyPerm = true
        }
        return isNeedApplyPerm
    }

    //动态申请权限(Android6.0以上需要如此)
    fun isPermissionsApply(context: Context, isApplyPerm: Boolean): Boolean {
        var isNeedApplyPerm = false
        //判断剩余还未申请的权限
        val unApplyedList = ArrayList()
        for (i in 0 until PERMISSIONS.size) {
            if (ContextCompat.checkSelfPermission(context, PERMISSIONS[i]) != PackageManager.PERMISSION_GRANTED) {
                unApplyedList.add(PERMISSIONS[i])   //申请过的权限将其删除,不要再提示给用户
            }
        }
        if (unApplyedList.size > 0) { //有未申请的权限,去申请
            isNeedApplyPerm = true
            if (isApplyPerm) {
                val unApplyedArray:Array = unApplyedList.toTypedArray()
                ActivityCompat.requestPermissions(context as Activity, unApplyedArray,PERMS_APPLY_CODE)
            }
        }

        return isNeedApplyPerm
    }

    //解注册观察者模式
    fun disposeSubscribe(vararg disposables: Disposable) {
        for (disposable in disposables) {
            if (disposable != null && !disposable.isDisposed) {
                disposable.dispose()
            }
        }
    }
}


一个用来存放权限的对象

object Config {
    //权限code
    val PERMS_APPLY_CODE = 0
    //需要申请的权限列表
    var PERMISSIONS = arrayOf(
            Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE)
}


当然还有一个什么都没有的主界面

class MainActivity : AppCompatActivity() {

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

由于引入了anko和rerxjava2的框架,不要忘记在build.gradle:app中添加实现

 implementation 'io.reactivex.rxjava2:rxjava:2.1.6'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'


    //Anko Version
    ext.anko_version='0.10.4'
    // Anko Commons
    implementation "org.jetbrains.anko:anko-commons:$anko_version"

    // Anko Layouts
    implementation "org.jetbrains.anko:anko-sdk25:$anko_version" // sdk15, sdk19, sdk21, sdk23 are also available
    implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"

    // Coroutine listeners for Anko Layouts
    implementation "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version"
    implementation "org.jetbrains.anko:anko-appcompat-v7-coroutines:$anko_version"

    // Anko SQLite
    implementation "org.jetbrains.anko:anko-sqlite:$anko_version"

    //anko 拓展
    implementation "org.jetbrains.anko:anko-sdk25:$anko_version"
    implementation "org.jetbrains.anko:anko-recyclerview-v7:$anko_version"

虽然有些用不到,但是每次都复制习惯了

一路下来参考了很多的代码,其中帮助最大的是GitHub上的这份点击打开链接

虽然我心目中想实现的是qq音乐启动时的那种样式,但是对于图形界面如何绘制还是不太了解,最终没能达到那种视觉效果,而且该方法还存在一个问题:如果qq音乐在启动时强行修改权限就会导致应用重启,从而在下次登录时重新检测权限以免出现意外,而我这段如果未关闭后台则会依然运行,有可能产生错误。

当然小小吐槽一句,网易云既不会在修改权限时重启,而且就算关闭后台也不进行二次检测,我就这样关闭了存储器读取权限,导致本地音乐无法读取却不做任何提示。

anko中对于dialog的个性化定制还是没有弄清楚,就只好采取了默认样式

源码在https://github.com/thirstysheep/thirstysheep-permission


你可能感兴趣的:(安卓学习资料,kotlin)