Flutter plugin: Send data from Android BroadcastReceiver to Flutter code

Viewed 876

I'm developing a Flutter plugin (for Android only) that automatically executes a Flutter task when the device connects to a specific bluetooth device.

Here is what I do in the Android side of the plugin:

  1. In the manifest, I register a BroadcastReceiver that listen to bluetooth events.
<receiver android:name=".BluetoothBroadcastReceiver">
    <intent-filter>
        <action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
        <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
        <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
    </intent-filter>
</receiver>
  1. In my 'FlutterPlugin' class, I initialise an EventChannel and set a StreamHandler. Then, I keep a reference of the EventSink that is provided in the onListen function of the StreamHandler. This allows me to send data from the Android side of the plugin to the Flutter side of the plugin.
class BluetoothPlugin : FlutterPlugin {

    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        EventChannel(flutterPluginBinding.binaryMessenger, "event_channel_bluetooth_event")
            .setStreamHandler(object : StreamHandler {

                override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink) {
                    BluetoothPlugin.eventSink = eventSink
                }

                override fun onCancel(arguments: Any?) {}

        })
    }

    companion object {
        var eventSink: EventChannel.EventSink? = null
    }

}
  1. Inside the onReceive function of my BroadCastReceiver, I use the EventSink to notify the Flutter side of the plugin that a bluetooth event happened.
class BluetoothReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == BluetoothDevice.ACTION_ACL_CONNECTED) {
            BluetoothPlugin.eventSink?.success("Bluetooth device is connected")
        }
    }

}

Here is what I do in the Flutter side of the plugin:

  1. I setup an EventChannel that will listen to any message that is passed to the EventSink.
EventChannel('event_channel_bluetooth_event').receiveBroadcastStream().listen(
  (data) {
    // A bluetooth event happened
  },
);

Everything works perfectly when the app is running (in the foreground and in the background). However, if the app is killed, the BluetoothBroadcastReceiver (in the Android side of the plugin) can't pass any data to the Flutter side of the plugin because the EventChannel is not initialised.

I could not find any way to "wake up" the Flutter side of the plugin (and thus initialise the EventChannel) when the BroadcastReceiver is triggered.

Can anyone help me with that?

Thank you very much in advance

1 Answers
Related