Created
January 31, 2023 13:08
-
-
Save RankoR/7c8084bf3a7b58beae9b1ef9de2d0cc7 to your computer and use it in GitHub Desktop.
Flow broadcast receiver
This file contains hidden or 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
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