Skip to content

Instantly share code, notes, and snippets.

@RankoR
Created January 31, 2023 13:08
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 RankoR/7c8084bf3a7b58beae9b1ef9de2d0cc7 to your computer and use it in GitHub Desktop.
Save RankoR/7c8084bf3a7b58beae9b1ef9de2d0cc7 to your computer and use it in GitHub Desktop.
Flow broadcast receiver
package page.smirnov.sample
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
interface FlowBroadcastReceiver {
val events: Flow<BroadcastEvent>
data class BroadcastEvent(
val action: String,
val extras: Bundle? = null,
)
}
/**
* Flow wrapper for [BroadcastReceiver]
*
* @param context Context to register BroadcastReceiver. Use app context to prevent context leaks
* @param intentFilter Optional intent filter. Mutually exclusive with actions
* @param actions Set of actions for intent filter. Mutually exclusive with intentFilter
*/
abstract class FlowBroadcastReceiverImpl(
context: Context,
intentFilter: IntentFilter? = null,
actions: Set<String> = emptySet(),
) : FlowBroadcastReceiver {
override val events = callbackFlow {
require(intentFilter != null || actions.isNotEmpty()) {
"Pass intentFilter or actions"
}
require(!(intentFilter != null && actions.isNotEmpty())) {
"Pass one of intentFilter or actions, not both at once"
}
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val action = intent.action ?: return
if (!actions.contains(action)) {
return
}
FlowBroadcastReceiver.BroadcastEvent(
action = action,
extras = intent.extras
)
.let(::trySend)
}
}
val broadcastIntentFilter = intentFilter ?: IntentFilter().apply {
actions.iterator().forEach(::addAction)
}
context.registerReceiver(receiver, broadcastIntentFilter)
awaitClose {
try {
context.unregisterReceiver(receiver)
} catch (e: IllegalArgumentException) {
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment