What is the difference between MethodChannel, EventChannel & BasicMessageChannel? - flutter

In Flutter, there are three types of platform channels, and I want to know about the difference between them.

These channels are used to communicate between native code (plugins or native code inside of your project) and the Flutter framework.
MethodChannel
A MethodChannel is used for "communicating with platform plugins using asynchronous method calls". This means that you use this channel to invoke methods on the native side and can return back a value and vise versa.
You can e.g. call a method that retrieves the device name this way.
EventChannel
An EventChannel is used to stream data. This results in having a Stream on the Dart side of things and being able to feed that stream from the native side.
This is useful if you want to send data every time a particular event occurs, e.g. when the wifi connection of a device changes.
BasicMessageChannel
This is probably not something you will want to use. BasicMessageChannel is used to encode and decode messages using a specified codec.
An example of this would be working with JSON or binary data. It is just a simpler version because your data has a clear type (codec) and you will not send multiple parameters etc.

Here is a link to a good explanation for you https://medium.com/flutter-io/flutter-platform-channels-ce7f540a104e
Basically there are two main types:
Method Channels: designed for invoking named pieces of code across Dart and Java/Kotlin or Objective-C/Swift. (From flutter to the platform)
Event Channels: specialized platform channel intended for the use case of exposing platform events to Flutter as a Dart stream. (From the platform to flutter)

#creativecreatorormaybenot answer clears the things, let me add more to this.
Method Channel
This is more like RPC call. You invoke a method from your Flutter app to the native code, the native code does something and finally responds with a success or error. This call could be to get the current battery status, network information or temperature data. Once the native side has responded, it can no longer send more information until the next call.
Method Channel provides platform communication using asynchronous method calls.
Note:- If desired, method calls can also be sent in the reverse
direction, with the platform acting as client to methods implemented
in Dart.
Event Channel
This is more like reactive programming where platform communication using asynchronous event streams. These events could be anything that you need streamed to your Flutter application.Streaming data from the native code to Flutter app like continuously updating BLE or WiFi scanning results, accelerometer and gyro, or even periodic status updates from intensive data collection.
Basic Message Channel
It provides basic messaging services similar to BinaryMessages, but with pluggable message codecs in support of sending strings or semi-structured messages. Messages are encoded into binary before being sent, and binary messages received are decoded into Dart values. The MessageCodec used must be compatible with the one used by the platform plugin.

Related

WidgetsFlutterBinding.ensureInitialized() equivalent for the platform/ host side

Is there a way to ensure the bindings are initialized between Flutter and Host/ Platform (Android, iOS)? I want to do this because I want to invoke methods from host to dart.
For example, in Android (java), I create a flutter engine, register plugins, and create a method channel, and launch the application:
FlutterEngine flutterEngine = new FlutterEngine(context, null);
// Remember to register plugins
GeneratedPluginRegister.registerGeneratedPlugins(flutterEngine);
DartExecutor executor = flutterEngine.getDartExecutor();
methodChannel = new MethodChannel(executor.getBinaryMessenger(), "my background method channel");
methodChannel.setMethodCallHandler(this);
// Launch app
DartExecutor.DartEntrypoint appEntrypoint = DartExecutor.DartEntrypoint.createDefault();
executor.executeDartEntrypoint(appEntrypoint);
I'd like to use methodChannel.invokeMethod, but the application might not be ready for me yet, even though in appEntrypoint, the same MethodChannel is created on the dart side. If I call methodChannel.invokeMethod too early, I get:
2021-09-14 16:41:01.102 30103-30425/com.example.app E/flutter:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception:
MissingPluginException
(No implementation found for method MethodName on channel com.example.app.package)
A solution would be to ask the Dart side to call a PlatformMethod when it's ready initializing, which would inform me that it's ready to receive messages. But I would prefer to avoid having to set up 2 way communication if I only need to send one message to the Dart side.
I have a feeling it's not possible. If so, could someone still explain why the binding has to be awaited from the Dart side? Something to do with no listeners available on the Platform side?
The methods were actually being called.
It was working. This was a bad idea, but the actual methods were being called: the 2 Method Channels on dart side and 2 method channels on Platform side were calling each other just fine. They all had the same channel name. Probably not a good idea for complexity reasons (see below), but it worked. 😅
My specific issue:
The reason I was getting No implementation found for method MethodName was exactly because I had two MethodChannels on the dart side, and two on Platform side. I was recreating the same isolate, so I had 2 Flutter applications running simultaneously. When one Isolate called a dart method I did not implement on on Method Call Handler on Platform side, I got this error.
Lesson learnt
If you have separate components on your app (Android components: Activity, Service, Broadcast Receiver or Dart Isolates):
Don't re-create the main application entrypoint. Create a new separate DartEntrypoint.
Use unique channel names for the MethodChannel.

Passing Isolate/ControlPort through MethodChannel

Within our flutter app we are doing some background processing. For that, we need to create new flutter isolate in our native code so we can run code when activity is not open, based on this guide: https://medium.com/#chetan882777/initiating-calls-to-dart-from-the-native-side-in-the-background-with-flutter-plugin-7d46aed32c47
Now, to not duplicate code and to not cause any concurrency issues, we would also like to have access to that background processing isolate from main flutter UI isolate. That way we can begin processing from both native code and from flutter UI code.
However, there does not seem to be a way for native to pass this Isolate / ControlPort to the main UI side so it can communicate with it. Is there a way I can achieve this (communicate to the same Isolate from both native and UI side)?
From what I see, only way to do this would require native to be the broker between the two sides (send the task to native and then native sends it back to the other side), but it seems like a lot of hassle for one flutter talking to another flutter.
Solution to this is the IsolateNameServer.
One side can call IsolateNameServer.registerPortWithName() and other side can then send messages to that port via IsolateNameServer.lookupPortByName()

How can i use sockets with Flutter web

I'm trying to make a connection between a socket server written in Python using socketio to a client made with Flutter Web.
I tested various socket packages like adhara_socket_io and flutter_socket_io and nothing worked. I tried the same code snippets on Android and they didn't work too.
I kept searching and i found this code snippet. It uses the Socket class from the dart.io package.
Socket socket = await Socket.connect('192.168.2.190', 7003);
print('connected');
// listen to the received data event stream
socket.listen((List<int> event) {
print(utf8.decode(event));
});
// send hello
socket.add(utf8.encode('hello'));
// wait 5 seconds
await Future.delayed(Duration(seconds: 5));
// .. and close the socket
socket.close();
This one connected to the Python server and sent the data from Android but when i tested it from Web i didn't connect.
Is there some things extra i need to add for it to work on Web?
Or in the worst case, is there another way to do what i want to do, my goal is to display a video feed in a website. The video is actually a bunch of images taken from Python, there is some machine learning that will be performed on them and i want to send them over socket and each image is displaying as soon as it is received so it looks like a video feed. (Similar thing was done using React)
dart.io package is not compatible with flutter web. And I suppose As pskink suggested websockets is the way to go. You can use HtmlWebSocketChannel from the web_socket_channel package as documented here. I have used this package and can confirm it works well in flutter web.
In your case should be using something as follows.
var channel = HtmlWebSocketChannel.connect("ws://192.168.2.190:7003");
But do note that this is not inter operable with regular flutter app. If you aim to target both android and flutter web, then you should handle this channel creation conditionally depending on target you are building it for and decide between HtmlWebSocketChannel or IOWebSocketChannel to create the connection. If you are interested you can use a conditional stub based implementation as suggested in this post*.
* Note: its my post. :)

Flutter: why ever use a Future over a Stream?

If a Future displays a once off piece of data while a Stream offers the additional advantage of updating information in real-time when data is modified at the source (ie, Firestore database), then why would one ever use a Future? What disadvantages would using a Stream over a Future have?
Why would one ever use a Future?
A Future handles a single event when an asynchronous operation completes or fails. It can be used for simple HTTP requests (GET, POST, ...).
You can have a look to the boring flutter development show where Google engineers build a simple Hacker News app, with Futures.
EDIT
New video from Flutter team about dart Futures
What disadvantages would using a Stream over a Future have?
They are made for different needs : real time updates or asynchronous calls, so they cannot really be compared in terms of advantages of one over the other.

Does the Rx Framework have any use in a web application?

I have been looking at the Rx Framework aslo refered to as LINQ to events. This is definately a great thing but I have been wondering if anyone sees this as having any uses in web applications rather than just normal windows based apps?
You can use Rx in various call back scenarios, not just when you work 'normal windows apps'. Especially, when you work with Async operations - for ex, you might need to make a call to the server or cloud from your silverlight or desktop client and to receive the data back. Or in cases you'll get a call back from the server (in cases like Polling Duplex).
Also, another scenario for web apps - to invalidate your cache when you receive a data changed event from the model. Just some 'imaginary' code here if you've a cache and model designed accordingly...
var cacheListeners=from sender in myModel.GetDataChangedEvents()
select sender;
//Subscribe
cacheListeners.Subscribe(data=>Cache.Invalidate(data.Key));
Have a look at this http://amazedsaint.blogspot.com/2009/11/systemreactive-or-net-reactive.html
It appears that the original spark for the Rx was around web based programming - in particular to simplify the challenges of AJAX style applications.
Here's a web based example
http://blogs.msdn.com/somasegar/archive/2009/11/18/reactive-extensions-for-net-rx.aspx
See the project http://reactivetrader.com/ to see Rx in use in a web application.