Last active
January 14, 2024 10:23
-
-
Save afollestad/d6c0f6a80c99b3e7033caea997b2f061 to your computer and use it in GitHub Desktop.
A Lifecycle components aware BroadcastReceiver DSL (Kotlin)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Context | |
import android.content.Intent | |
import android.content.IntentFilter | |
import androidx.lifecycle.Lifecycle.Event.ON_DESTROY | |
import androidx.lifecycle.Lifecycle.Event.ON_START | |
import androidx.lifecycle.LifecycleObserver | |
import androidx.lifecycle.LifecycleOwner | |
import androidx.lifecycle.OnLifecycleEvent | |
import android.content.BroadcastReceiver as StockReceiver | |
/** @author Aidan Follestad (@afollestad) */ | |
class BroadcastReceiver<T>( | |
context: T, | |
constructor: Builder.() -> Unit | |
) : LifecycleObserver where T : Context, T : LifecycleOwner { | |
private val appContext = context.applicationContext | |
private val filter: IntentFilter | |
private val instructions: List<Instructions> | |
init { | |
val builder = Builder() | |
constructor(builder) | |
filter = builder.filter() | |
instructions = builder.instructions() | |
context.lifecycle.addObserver(this) | |
} | |
private val broadcastReceiver = object : StockReceiver() { | |
override fun onReceive( | |
context: Context, | |
intent: Intent | |
) { | |
for (ins in instructions) { | |
if (ins.matches(intent)) { | |
ins.execution() | |
.invoke(intent) | |
break | |
} | |
} | |
} | |
} | |
@OnLifecycleEvent(ON_START) | |
fun start() { | |
appContext.registerReceiver(broadcastReceiver, filter) | |
} | |
@OnLifecycleEvent(ON_DESTROY) | |
fun stop() = appContext.unregisterReceiver(broadcastReceiver) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.IntentFilter | |
/** @author Aidan Follestad (@afollestad) */ | |
class Builder internal constructor() { | |
private val filter = IntentFilter() | |
private val instructions = mutableListOf<Instructions>() | |
fun onAction( | |
action: String, | |
execution: Execution | |
) { | |
filter.addAction(action) | |
instructions.add(OnAction(action, execution)) | |
} | |
fun onDataScheme( | |
scheme: String, | |
execution: Execution | |
) { | |
filter.addDataScheme(scheme) | |
instructions.add(OnDataScheme(scheme, execution)) | |
} | |
fun onCategory( | |
category: String, | |
execution: Execution | |
) { | |
filter.addCategory(category) | |
instructions.add(OnCategory(category, execution)) | |
} | |
internal fun filter() = filter | |
internal fun instructions() = instructions | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.content.Intent | |
typealias Execution = (Intent) -> Unit | |
/** @author Aidan Follestad (@afollestad) */ | |
sealed class Instructions { | |
abstract fun matches(intent: Intent): Boolean | |
abstract fun execution(): Execution | |
data class OnAction( | |
val action: String, | |
val execution: Execution | |
) : Instructions() { | |
override fun matches(intent: Intent): Boolean { | |
return intent.action == action | |
} | |
override fun execution() = execution | |
} | |
data class OnDataScheme( | |
val scheme: String, | |
val execution: Execution | |
) : Instructions() { | |
override fun matches(intent: Intent): Boolean { | |
return intent.data?.scheme == scheme | |
} | |
override fun execution() = execution | |
} | |
data class OnCategory( | |
val category: String, | |
val execution: Execution | |
) : Instructions() { | |
override fun matches(intent: Intent): Boolean { | |
return intent.hasCategory(category) | |
} | |
override fun execution() = execution | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyActivity : AppCompatActivity() { | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
// Will automatically unregister itself when the Activity pauses, and register again when it resumes. | |
BroadcastReceiver(this) { | |
onAction("com.yourapp.helloworld.SOME_ACTION") { | |
// Do something | |
} | |
onCategory("messages") { | |
// Do something | |
} | |
onDataScheme("file://") { | |
// Do something | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This... is wonderful. Thank you very much.