Android marshmallow request permission?

后端 未结 24 2082
無奈伤痛
無奈伤痛 2020-11-21 06:40

I am currently working on an application that requires several \"dangerous\" permissions. So I tried adding \"ask for permission\" as required in Android Marshmallow(API Lev

24条回答
  •  醉酒成梦
    2020-11-21 07:24

    My class for request runtime permissions in Activity or Fragment

    It also help you show rationale or open Setting to enable permission after user denied a permission (with/without Never ask again) option easier

    class RequestPermissionHandler(private val activity: Activity? = null,
                                   private val fragment: Fragment? = null,
                                   private val permissions: Set = hashSetOf(),
                                   private val listener: Listener? = null
    ) {
        private var hadShowRationale: Boolean = false
    
        fun requestPermission() {
            hadShowRationale = showRationaleIfNeed()
            if (!hadShowRationale) {
                doRequestPermission(permissions)
            }
        }
    
        fun retryRequestDeniedPermission() {
            doRequestPermission(permissions)
        }
    
        private fun showRationaleIfNeed(): Boolean {
            val unGrantedPermissions = getPermission(permissions, Status.UN_GRANTED)
            val permanentDeniedPermissions = getPermission(unGrantedPermissions, Status.PERMANENT_DENIED)
            if (permanentDeniedPermissions.isNotEmpty()) {
                val consume = listener?.onShowSettingRationale(unGrantedPermissions)
                if (consume != null && consume) {
                    return true
                }
            }
    
            val temporaryDeniedPermissions = getPermission(unGrantedPermissions, Status.TEMPORARY_DENIED)
            if (temporaryDeniedPermissions.isNotEmpty()) {
                val consume = listener?.onShowPermissionRationale(temporaryDeniedPermissions)
                if (consume != null && consume) {
                    return true
                }
            }
            return false
        }
    
        fun requestPermissionInSetting() {
            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            val packageName = activity?.packageName ?: run {
                fragment?.requireActivity()?.packageName
            }
            val uri = Uri.fromParts("package", packageName, null)
            intent.data = uri
            activity?.apply {
                startActivityForResult(intent, REQUEST_CODE)
            } ?: run {
                fragment?.startActivityForResult(intent, REQUEST_CODE)
            }
        }
    
        fun onRequestPermissionsResult(requestCode: Int, permissions: Array,
                                       grantResults: IntArray) {
            if (requestCode == REQUEST_CODE) {
                for (i in grantResults.indices) {
                    if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                        markNeverAskAgainPermission(permissions[i], false)
                    } else if (!shouldShowRequestPermissionRationale(permissions[i])) {
                        markNeverAskAgainPermission(permissions[i], true)
                    }
                }
                var hasShowRationale = false
                if (!hadShowRationale) {
                    hasShowRationale = showRationaleIfNeed()
                }
                if (hadShowRationale || !hasShowRationale) {
                    notifyComplete()
                }
            }
        }
    
        fun onActivityResult(requestCode: Int) {
            if (requestCode == REQUEST_CODE) {
                getPermission(permissions, Status.GRANTED).forEach {
                    markNeverAskAgainPermission(it, false)
                }
                notifyComplete()
            }
        }
    
        fun cancel() {
            notifyComplete()
        }
    
        private fun doRequestPermission(permissions: Set) {
            activity?.let {
                ActivityCompat.requestPermissions(it, permissions.toTypedArray(), REQUEST_CODE)
            } ?: run {
                fragment?.requestPermissions(permissions.toTypedArray(), REQUEST_CODE)
            }
        }
    
        private fun getPermission(permissions: Set, status: Status): Set {
            val targetPermissions = HashSet()
            for (p in permissions) {
                when (status) {
                    Status.GRANTED -> {
                        if (isPermissionGranted(p)) {
                            targetPermissions.add(p)
                        }
                    }
                    Status.TEMPORARY_DENIED -> {
                        if (shouldShowRequestPermissionRationale(p)) {
                            targetPermissions.add(p)
                        }
                    }
                    Status.PERMANENT_DENIED -> {
                        if (isNeverAskAgainPermission(p)) {
                            targetPermissions.add(p)
                        }
                    }
                    Status.UN_GRANTED -> {
                        if (!isPermissionGranted(p)) {
                            targetPermissions.add(p)
                        }
                    }
                }
            }
            return targetPermissions
        }
    
        private fun isPermissionGranted(permission: String): Boolean {
            return activity?.let {
                ActivityCompat.checkSelfPermission(it, permission) == PackageManager.PERMISSION_GRANTED
            } ?: run {
                ActivityCompat.checkSelfPermission(fragment!!.requireActivity(), permission) == PackageManager.PERMISSION_GRANTED
            }
        }
    
        private fun shouldShowRequestPermissionRationale(permission: String): Boolean {
            return activity?.let {
                ActivityCompat.shouldShowRequestPermissionRationale(it, permission)
            } ?: run {
                ActivityCompat.shouldShowRequestPermissionRationale(fragment!!.requireActivity(), permission)
            }
        }
    
        private fun notifyComplete() {
            listener?.onComplete(getPermission(permissions, Status.GRANTED), getPermission(permissions, Status.UN_GRANTED))
        }
    
        private fun getPrefs(context: Context): SharedPreferences {
            return context.getSharedPreferences("SHARED_PREFS_RUNTIME_PERMISSION", Context.MODE_PRIVATE)
        }
    
        private fun isNeverAskAgainPermission(permission: String): Boolean {
            return getPrefs(requireContext()).getBoolean(permission, false)
        }
    
        private fun markNeverAskAgainPermission(permission: String, value: Boolean) {
            getPrefs(requireContext()).edit().putBoolean(permission, value).apply()
        }
    
        private fun requireContext(): Context {
            return fragment?.requireContext() ?: run {
                activity!!
            }
        }
    
        enum class Status {
            GRANTED, UN_GRANTED, TEMPORARY_DENIED, PERMANENT_DENIED
        }
    
        interface Listener {
            fun onComplete(grantedPermissions: Set, deniedPermissions: Set)
            fun onShowPermissionRationale(permissions: Set): Boolean
            fun onShowSettingRationale(permissions: Set): Boolean
        }
    
        companion object {
            const val REQUEST_CODE = 200
        }
    }
    

    Using in Activity like

    class MainActivity : AppCompatActivity() {
        private lateinit var smsAndStoragePermissionHandler: RequestPermissionHandler
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            smsAndStoragePermissionHandler = RequestPermissionHandler(this@MainActivity,
                    permissions = setOf(Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_EXTERNAL_STORAGE),
                    listener = object : RequestPermissionHandler.Listener {
                        override fun onComplete(grantedPermissions: Set, deniedPermissions: Set) {
                            Toast.makeText(this@MainActivity, "complete", Toast.LENGTH_SHORT).show()
                            text_granted.text = "Granted: " + grantedPermissions.toString()
                            text_denied.text = "Denied: " + deniedPermissions.toString()
                        }
    
                        override fun onShowPermissionRationale(permissions: Set): Boolean {
                            AlertDialog.Builder(this@MainActivity).setMessage("To able to Send Photo, we need SMS and" + " Storage permission")
                                    .setPositiveButton("OK") { _, _ ->
                                        smsAndStoragePermissionHandler.retryRequestDeniedPermission()
                                    }
                                    .setNegativeButton("Cancel") { dialog, _ ->
                                        smsAndStoragePermissionHandler.cancel()
                                        dialog.dismiss()
                                    }
                                    .show()
                            return true // don't want to show any rationale, just return false here
                        }
    
                        override fun onShowSettingRationale(permissions: Set): Boolean {
                            AlertDialog.Builder(this@MainActivity).setMessage("Go Settings -> Permission. " + "Make SMS on and Storage on")
                                    .setPositiveButton("Settings") { _, _ ->
                                        smsAndStoragePermissionHandler.requestPermissionInSetting()
                                    }
                                    .setNegativeButton("Cancel") { dialog, _ ->
                                        smsAndStoragePermissionHandler.cancel()
                                        dialog.cancel()
                                    }
                                    .show()
                            return true
                        }
                    })
    
            button_request.setOnClickListener { handleRequestPermission() }
        }
    
        private fun handleRequestPermission() {
            smsAndStoragePermissionHandler.requestPermission()
        }
    
        override fun onRequestPermissionsResult(requestCode: Int, permissions: Array,
                                                grantResults: IntArray) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
            smsAndStoragePermissionHandler.onRequestPermissionsResult(requestCode, permissions,
                    grantResults)
        }
    
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
            smsAndStoragePermissionHandler.onActivityResult(requestCode)
        }
    }
    

    Code on Github

    Demo

提交回复
热议问题