8

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

Valentin
  • 5,379
  • 7
  • 36
  • 50
  • Have you managed _to "wake up" the Flutter side of the plugin_? Have you resolved the problem of calling Dart/Flutter code from BroadcastReceiver? – mspnr Jun 17 '23 at 00:23

1 Answers1

0

I finally found a very interesting post on Medium that explains how to send data from native (Android) code to Dart after the app was terminated: https://medium.com/@chetan882777/initiating-calls-to-dart-from-the-native-side-in-the-background-with-flutter-plugin-7d46aed32c47

Valentin
  • 5,379
  • 7
  • 36
  • 50