How to check permission is granted in ViewModel?

前端 未结 3 1592
天涯浪人
天涯浪人 2021-02-08 19:53

I need to ask permission for contacts and when application starts I\'m asking,in ViewModel part I need to call method which requires permission. I need to check permission is gr

3条回答
  •  难免孤独
    2021-02-08 20:18

    I have reworked the solution. The PermissionRequester object is everything you need to request permissions from any point where you have at least an application context. It uses its helper PermissionRequestActivity to accomplish this job.

    @Parcelize
    class PermissionResult(val permission: String, val state: State) : Parcelable
    enum class State { GRANTED, DENIED_TEMPORARILY, DENIED_PERMANENTLY }
    typealias Cancellable = () -> Unit
    private const val PERMISSIONS_ARGUMENT_KEY = "PERMISSIONS_ARGUMENT_KEY"
    private const val REQUEST_CODE_ARGUMENT_KEY = "REQUEST_CODE_ARGUMENT_KEY"
    
    object PermissionRequester {
        private val callbackMap = ConcurrentHashMap) -> Unit>(1)
        private var requestCode = 256
        get() {
            requestCode = field--
            return if (field < 0) 255 else field
        }
    
        fun requestPermissions(context: Context, vararg permissions: String, callback: (List) -> Unit): Cancellable {
            val intent = Intent(context, PermissionRequestActivity::class.java)
                    .putExtra(PERMISSIONS_ARGUMENT_KEY, permissions)
                    .putExtra(REQUEST_CODE_ARGUMENT_KEY, requestCode)
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
            callbackMap[requestCode] = callback
            return { callbackMap.remove(requestCode) }
        }
    
        internal fun onPermissionResult(responses: List, requestCode: Int) {
            callbackMap[requestCode]?.invoke(responses)
            callbackMap.remove(requestCode)
        }
    }
    
    class PermissionRequestActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            if (savedInstanceState == null) {
                requestPermissions()
            }
        }
    
        private fun requestPermissions() {
            val permissions = intent?.getStringArrayExtra(PERMISSIONS_ARGUMENT_KEY) ?: arrayOf()
            val requestCode = intent?.getIntExtra(REQUEST_CODE_ARGUMENT_KEY, -1) ?: -1
            when {
                permissions.isNotEmpty() && requestCode != -1 -> ActivityCompat.requestPermissions(this, permissions, requestCode)
                else -> finishWithResult()
            }
        }
    
        override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    
            val permissionResults = grantResults.zip(permissions).map { (grantResult, permission) ->
                val state =  when {
                    grantResult == PackageManager.PERMISSION_GRANTED -> State.GRANTED
                    ActivityCompat.shouldShowRequestPermissionRationale(this, permission) -> State.DENIED_TEMPORARILY
                    else -> State.DENIED_PERMANENTLY
                }
                PermissionResult(permission, state)
            }
    
            finishWithResult(permissionResults)
        }
    
        private fun finishWithResult(permissionResult: List = listOf()) {
            val requestCode = intent?.getIntExtra(REQUEST_CODE_ARGUMENT_KEY, -1) ?: -1
            PermissionRequester.onPermissionResult(permissionResult, requestCode)
            finish()
        }
    }
    

    Usage:

    class MyViewModel(application: Application) : AndroidViewModel(application) {
    
        private val cancelRequest: Cancellable = requestPermission()
    
        private fun requestPermission(): Cancellable {
            return PermissionRequester.requestPermissions(getApplication(), "android.permission.SEND_SMS") {
                if (it.firstOrNull()?.state == State.GRANTED) {
                    Toast.makeText(getApplication(), "GRANTED", Toast.LENGTH_LONG).show()
                } else {
                    Toast.makeText(getApplication(), "DENIED", Toast.LENGTH_LONG).show()
                }
            }
        }
    
        override fun onCleared() {
            super.onCleared()
            cancelRequest()
        }
    }
    

提交回复
热议问题