Skip to content

return style for [startActivityForResult, requestPermission] using coroutine.

License

Notifications You must be signed in to change notification settings

cchcc/android-coroutine-arrp

Repository files navigation

android-coroutine-arrp

Download

Convenient version of startActivityForResult , requestPermission on coroutine.
You can get result as return. You don't need to care about requestCode.

CoroutineScope(Dispatchers.Main).launch {

  val permissionResult = requestPermissionAwait(android.Manifest.permission.READ_PHONE_STATE)
  if (permissionResult.isGranted) {
      // ...
  }
  
  
  val (resultCode, data) = startActivityForResultAwait(intent)
  if (resultCode == Activity.RESULT_OK) {
      // ...
  }
  
}

setup

prerequisite

  • kotlin version 1.3 or later
  • androidx AppCompat

step

  1. add to dependencies.
implementation 'cchcc.android:arrp:0.5.0'
  1. add some code below.
class BaseActivity : AppCompatActivity()
        , ActivityResult by ActivityResult.create()  // add
        , RequestPermission by RequestPermission.create()  // add
{
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        activityResult(requestCode, resultCode, data)  // add
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        permissionResult(requestCode, permissions, grantResults)  // add
    }
}

BaseActivity or BaseFragment would be a appropriate class to add.

usage

This lightweight library provides some methods below.

suspend fun requestPermissionAwait(vararg permissions: String): RequestPermission.Result
suspend fun startActivityForResultAwait_(intent: Intent, options: Bundle? = null): Pair<Int, Intent?>
suspend fun activityResultAwait(startActivity: (requestCode: Int) -> Unit): Pair<Int, Intent?>  

Those are all suspend method. So should be called only from a coroutine or another suspend function.

val permissionResult = requestPermissionAwait(android.Manifest.permission.CAMERA
                                            , android.Manifest.permission.RECORD_AUDIO)
if (permissionResult is RequestPermission.Result.Denied) {
    if (android.Manifest.permission.CAMERA in permissionResult.denied) {
        // ...
    }
    return@launch
}

// from here, permission is granted

requestPermissionAwait returns RequestPermission.Result.

sealed class Result {
    object Granted : Result()
    data class Denied(val granted: List<String>, val denied: List<String>) : Result()
    val isGranted: Boolean get() = this is Granted
}

startActivityForResultAwait returns Pair<Int, Intent?> corresponding to resultCode and data.

val (resultCode, data) = startActivityForResultAwait(intent)
if (resultCode != Activity.RESULT_OK)
    return@launch
val cursor = contentResolver.query(data!!.data!!, null, null, null, null)

// 

activityResultAwait has a lambda parameter for using requstCode. You sholud call own way like startActivityForResult in the block with requestCode.

val (resultCode, data) = activityResultAwait { requestCode ->
    startActivityForResult(intent, requestCode)
}
val (resultCode, data) = activityResultAwait { requestCode ->
    googleApiAvailability.getErrorDialog(
        activity
        , connectionStatusCode
        , requestCode
    ).show()
}

advance

avoid duplicated requestCode

There are maybe some cases that use own requestCode. In that case, let arrp knows the requestCode.

const val REQUEST_CODE = 1000
ActivityResult.addExcludeRequestCode(REQUEST_CODE)
RequestPermission.addExcludeRequestCode(REQUEST_CODE)

So arrp will not use the added requestCode. It is enough to add only once for lifecyle of App.

About

return style for [startActivityForResult, requestPermission] using coroutine.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages