Ali A.M.Hassani
Ali A.M.Hassani

Reputation: 53

Flutter platform-channel on windows

I need to access Windows Desktop API to change network settings. I have read flutter document and experiences with flutter platform channel. When I ran the code, I just got true in output, but I expect receiving string message from host.

Any help would be appreciated.

windows/runner/flutter_windows.cpp file

#include "flutter_window.h"

#include <optional>
#include "flutter/generated_plugin_registrant.h"

#include <flutter/binary_messenger.h>
#include <flutter/standard_method_codec.h>
#include <flutter/method_channel.h>
#include <flutter/method_result_functions.h>

#include <iostream>
using namespace std;

FlutterWindow::FlutterWindow(const flutter::DartProject& project)
    : project_(project) {}

FlutterWindow::~FlutterWindow() {}
void initMethodChannel(flutter::FlutterEngine* flutter_instance) {
    const static std::string channel_name("test_channel");
    flutter::BinaryMessenger *messenger = FlEngine->messenger();
    const flutter::StandardMethodCodec *codec = &flutter::StandardMethodCodec::GetInstance();
    auto channel = std::make_unique<flutter::MethodChannel<>>(messenger ,channel_name ,codec);

    auto channel =
        std::make_unique<flutter::MethodChannel<>>(
            flutter_instance->messenger(), channel_name,
            &flutter::StandardMethodCodec::GetInstance());

        channel->SetMethodCallHandler(
            [](const flutter::MethodCall<>& call,
        std::unique_ptr<flutter::MethodResult<>> result) {

                // check method name called from dart
                if (call.method_name().compare("test") == 0) {
                // do what ever you want
                res = flutter::EncodableValue("Channel is working!");
                result->Success(res);
                }
                else {
                    result->NotImplemented();
                }
            }
        );
 }
bool FlutterWindow::OnCreate() {
  if (!Win32Window::OnCreate()) {
    return false;
  }

  RECT frame = GetClientArea();

  // The size here must match the window dimensions to avoid unnecessary surface
  // creation / destruction in the startup path.
  flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
      frame.right - frame.left, frame.bottom - frame.top, project_);
  // Ensure that basic setup of the controller was successful.
  if (!flutter_controller_->engine() || !flutter_controller_->view()) {
    return false;
  }
  RegisterPlugins(flutter_controller_->engine());
  initMethodChannel(flutter_controller_->engine());
  SetChildContent(flutter_controller_->view()->GetNativeWindow());

  flutter_controller_->engine()->SetNextFrameCallback([&]() {
    this->Show();
  });

  return true;
}

void FlutterWindow::OnDestroy() {
  if (flutter_controller_) {
    flutter_controller_ = nullptr;
  }

  Win32Window::OnDestroy();
}

LRESULT
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
                              WPARAM const wparam,
                              LPARAM const lparam) noexcept {
  // Give Flutter, including plugins, an opportunity to handle window messages.
  if (flutter_controller_) {
    std::optional<LRESULT> result =
        flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
                                                      lparam);
    if (result) {
      return *result;
    }
  }

  switch (message) {
    case WM_FONTCHANGE:
      flutter_controller_->engine()->ReloadSystemFonts();
      break;
  }

  return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
}

Calling the platform and method channel in dart

MethodChannel channel = const MethodChannel('test_channel');
print(await channel.invokeMethod("test"));

Output

flutter: true

But expect getting Channel is working! in the output.

Upvotes: 1

Views: 805

Answers (1)

Ali A.M.Hassani
Ali A.M.Hassani

Reputation: 53

There were some errors in the flutter_window.cpp file:

1- Missing Header Inclusion

I added these headers at the top of the file:

  • #include <string>
  • #include <flutter/encodable_value.h>
  • #include <../standard_codec.cc>
  • #include "windows.h"
  • #include "windef.h"
  • #include "windowsx.h"

And removed these headers:

  • #include <iostream>
  • using namespace std;

2- Duplicated channel declaration:

This is what I need in this situation:

auto channel = std::make_unique<flutter::MethodChannel<>>(messenger ,channel_name ,codec);

3- Undefined res variable:

just defined it as below, before using it:

flutter::EncodableValue res;
res = flutter::EncodableValue("pass result here");
result->Success(res);

After all of those changes, It got working fine.

The final flutter_window.cpp file is like that:

#include "flutter_window.h"
#include <optional>
#include "flutter/generated_plugin_registrant.h"

#include <string>
#include <flutter/binary_messenger.h>
#include <flutter/standard_method_codec.h>
#include <flutter/method_channel.h>
#include <flutter/method_result_functions.h>
#include <flutter/encodable_value.h>
#include <../standard_codec.cc>
#include "windows.h"
#include "windef.h"
#include "windowsx.h"

FlutterWindow::FlutterWindow(const flutter::DartProject& project)
    : project_(project) {}

FlutterWindow::~FlutterWindow() {}
void initMethodChannel(flutter::FlutterEngine* flutter_instance) {
    const static std::string channel_name("test");
    flutter::BinaryMessenger* messenger = flutter_instance->messenger();
    const flutter::StandardMethodCodec* codec = &flutter::StandardMethodCodec::GetInstance();
    auto channel = std::make_unique<flutter::MethodChannel<>>(messenger ,channel_name ,codec);

        channel->SetMethodCallHandler(
            [](const flutter::MethodCall<>& call,
        std::unique_ptr<flutter::MethodResult<>> result) {

                // check method name called from dart
                if (call.method_name().compare("test") == 0) {
                // do what ever you want
                flutter::EncodableValue res;
                res = flutter::EncodableValue("pass result here");
                result->Success(res);
                }
                else {
                    result->NotImplemented();
                }
            }
        );
 }
bool FlutterWindow::OnCreate() {
  if (!Win32Window::OnCreate()) {
    return false;
  }

  RECT frame = GetClientArea();

  // The size here must match the window dimensions to avoid unnecessary surface
  // creation / destruction in the startup path.
  flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
      frame.right - frame.left, frame.bottom - frame.top, project_);
  // Ensure that basic setup of the controller was successful.
  if (!flutter_controller_->engine() || !flutter_controller_->view()) {
    return false;
  }
  RegisterPlugins(flutter_controller_->engine());
  initMethodChannel(flutter_controller_->engine());
  SetChildContent(flutter_controller_->view()->GetNativeWindow());

  flutter_controller_->engine()->SetNextFrameCallback([&]() {
    this->Show();
  });

  return true;
}

void FlutterWindow::OnDestroy() {
  if (flutter_controller_) {
    flutter_controller_ = nullptr;
  }

  Win32Window::OnDestroy();
}

LRESULT
FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
                              WPARAM const wparam,
                              LPARAM const lparam) noexcept {
  // Give Flutter, including plugins, an opportunity to handle window messages.
  if (flutter_controller_) {
    std::optional<LRESULT> result =
        flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
                                                      lparam);
    if (result) {
      return *result;
    }
  }

  switch (message) {
    case WM_FONTCHANGE:
      flutter_controller_->engine()->ReloadSystemFonts();
      break;
  }

  return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
}

Happy coding!

Upvotes: 0

Related Questions