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) {
// ...
}
}
- kotlin version 1.3 or later
- androidx AppCompat
- add to dependencies.
implementation 'cchcc.android:arrp:0.5.0'
- 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.
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()
}
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.