In Flutter it is possible to develop plugins for executing platform specific code. For example on a windows host it is possible to invoke c++ code from the Flutter client with:
final int result = await platform.invokeMethod('getBatteryLevel');
At the windows host you can send a reply to this call for example with:
channel.SetMethodCallHandler(
[](const flutter::MethodCall<>& call,
std::unique_ptr<flutter::MethodResult<>> result) {
if (call.method_name() == "getBatteryLevel") {
int battery_level = GetBatteryLevel();
if (battery_level != -1) {
result->Success(battery_level);
}
else {
result->Error("UNAVAILABLE", "Battery level not available.");
}
}
else {
result->NotImplemented();
}
});
I want to go the other direction. The following code sends the battery level from the host to the Flutter client:
int battery_level = GetBatteryLevel();
method_channel_->InvokeMethod(
"sendBatteryLevel",
std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("batteryLevel"), flutter::EncodableValue(battery_level)},
}));
//string answer = await a string answer from method_channel_
But how can I send a return value back from the client to the host? I want to answer this call on the client, for example like
_handleMethodCall(MethodCall call) async {
switch (call.method) {
case "batteryLevel":
final args = call.arguments as Map;
final batteryLevel= args['batteryLevel'] as int;
//Send return value
call.answer('Thank you for informing me!'); //not working, this is what I want to do
break;
}
}
The method InvokeMethod(...)
from flutter::MethodChannel has a flutter::MethodResult parameter. But i didn't manage to to call it properly in order to receive a return value for the call from the flutter client
Update: I tried smorgans suggestion already using this client code:
_handleMethodCall(MethodCall call) async {
switch (call.method) {
case "batteryLevel":
final args = call.arguments as Map;
final batteryLevel= args['batteryLevel'] as int;
//Send return value
return 'Thank you for informing me!'; //I want to receive this string at the C++ host code
}
}
My problem is that i don't get the C++ host code working to receive the answer. I tried the following:
int battery_level = GetBatteryLevel();
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> resultPointer; // How do I declare this properly?
method_channel_->InvokeMethod(
"sendBatteryLevel",
std::make_unique<flutter::EncodableValue>(flutter::EncodableMap{
{flutter::EncodableValue("batteryLevel"), flutter::EncodableValue(battery_level)},
}), resultPointer);
//std::string answer = exctractAnswerFromMethodResult(resultPointer); // how do I do this?
I tried to receive the answer as shown above, but i didn't manage to pass the MethodResult parameter properly to method_channel_->InvokeMethod. The code from above results in the this compiler error:
On the Dart side:
As it says in the MethodChannel
documentation:
If the future returned by the handler completes with a result, that value is sent back to the platform plugin caller
Your call.answer
line (which doesn't work because there is no such method on MethodCall
) should just be a return
.
On the C++ side:
MethodResult
is an abstract class, so you cannot instantiate it. You need to either make your own subclass with the functionality you want and instantiate that, or use the provided MethodResultFunctions
class if you want to use lambdas instead.
You also need to std::move
the object you declare when you pass it, since it's a unique_ptr
; you are passing ownership of the handler to the method.
The method channel unit tests might be useful as examples, but it also looks like you may want to spend some time with some general C++ class tutorials. Using these C++ APIs correctly is going to require require familiarity with core C++ concepts like classes and unique_ptr
.