Skip to content

Instantly share code, notes, and snippets.

@PaulWoitaschek
Last active April 13, 2017 12:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PaulWoitaschek/d2cf8240d5827c942756758bfd750948 to your computer and use it in GitHub Desktop.
Save PaulWoitaschek/d2cf8240d5827c942756758bfd750948 to your computer and use it in GitHub Desktop.
Activity Composition
/**
* A module that can be used to abstract logic from the activity
*
* @author Paul Woitaschek
*/
@Suppress("UNUSED_PARAMETER")
abstract class ActivityModule {
lateinit var activity: CompositionActivity
open fun onCreate(savedInstanceState: Bundle?) {}
open fun onDestroy() {}
open fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {}
open fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {}
open fun onStart() {}
open fun onStop() {}
}
/**
* Basic Activity that has modules for delegation
*
* @author Paul Woitaschek
*/
abstract class CompositionActivity : AppCompatActivity() {
private val modules = ArrayList<ActivityModule>()
fun <T : ActivityModule> registerModule(module: T): T {
modules.add(module)
return module
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
call {
activity = this@CompositionActivity
onCreate(savedInstanceState)
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
call { onRequestPermissionsResult(requestCode, permissions, grantResults) }
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
call { onActivityResult(requestCode, resultCode, data) }
}
override fun onDestroy() {
super.onDestroy()
call { onDestroy() }
}
override fun onStart() {
super.onStart()
call { onStart() }
}
override fun onStop() {
super.onStop()
call { onStop() }
}
// executes a function on each registered module
private inline fun call(action: ActivityModule.() -> Unit) {
modules.forEach { it.action() }
}
@Suppress("UNCHECKED_CAST")
fun <T : ActivityModule> getModule(clazz: Class<T>): T {
modules.forEach {
if (it.javaClass == clazz) return it as T
}
throw ModuleNotRegisteredException(clazz)
}
}
/**
* Request permissions
*
* @author Paul Woitaschek
*/
class PermissionModule : ActivityModule() {
private val PERMISSION_CODE = 72
private val permissionSubject = PublishSubject.create<Array<String>>()
/** request a permission. */
fun request(permission: String): Single<PermissionResult> =
if (hasPermission(permission)) Single.just(PermissionResult.GRANTED)
else permissionSubject
.doOnSubscribe { ActivityCompat.requestPermissions(activity, arrayOf(permission), PERMISSION_CODE) }
.filter { it.contains(permission) }
.firstOrError()
.map {
if (hasPermission(permission)) PermissionResult.GRANTED
else if (showRationale(permission)) PermissionResult.DENIED_SHOW_RATIONALE
else PermissionResult.DENIED_FOREVER
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
if (requestCode == PERMISSION_CODE) {
permissionSubject.onNext(permissions)
}
}
private fun hasPermission(permission: String) = ContextCompat.checkSelfPermission(activity, permission) == PackageManager.PERMISSION_GRANTED
private fun showRationale(permission: String) = ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)
}
/**
* The result of requesting a permission
*
* @author Paul Woitaschek
*/
public enum PermissionResult {
GRANTED,
DENIED_SHOW_RATIONALE,
DENIED_FOREVER
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment