Этот репозиторий содержит Flutter плагины для платформы ОС Аврора.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

7.7 KiB

Plugin package

Специализированный пакет Dart, содержащий API, написанный на Dart, в сочетании с одной или несколькими реализациями для конкретной платформы. Пакеты плагинов могут быть написаны для Android (с использованием Kotlin или Java), ОС Аврора (с использование С++), iOS (с использованием Swift или Objective-C), Интернета, macOS, Windows или Linux или любой их комбинации.

Для демонстрации создания платформо-зависимого пакета для ОС Аврора типа "Plugin package" был написан и опубликован проект "Demo Dart Packages" которые подробно описан в статье "Flutter на ОС Аврора".

Проект "Demo Dart Packages" содержит в себе пакет реализующий платформо-зависимый плагин для ОС Аврора типа "Plugin package". Данный пакет использует API ОС Аврора - "Device Info API". Плагин использует QtDBus но не является типом плагина "Qt plugin package" так как не использует сигналы и слоты.

Создать пакет "Plugin package" можно командой:

$ flutter-aurora create --template=plugin <package-name>

Рассмотрим плагин "plugin_device" из проекта Demo Dart Packages. plugin_device - платформо-зависимая реализация плагина "Flutter Device" для ОС Аврора типа "Plugin package".

Структура пакета plugin_device:

└── aurora
    └── plugin_device
        ├── aurora
   ├── CMakeLists.txt
   ├── include
     └── plugin_device
         └── plugin_device_plugin.h
   └── plugin_device_plugin.cpp
        ├── lib
   ├── plugin_device.dart
   └── plugin_device_method_channel.dart
        └── pubspec.yaml

В pubspec.yaml плагина plugin_device нужно указать pluginClass и dartPluginClass.

flutter:
  plugin:
    platforms:
      aurora:
        pluginClass: PluginDevicePlugin
        dartPluginClass: PluginDevice

PluginDevicePlugin - C++ класс реализующий PluginInterface пакета flutter-embedder.

Файл packages/aurora/plugin_device/aurora/include/plugin_device/plugin_device_plugin.h

#include <flutter/plugin-interface.h>
#include <plugin_device/globals.h>

class PLUGIN_EXPORT PluginDevicePlugin final : public PluginInterface
{
public:
    void RegisterWithRegistrar(PluginRegistrar &registrar) override;

private:
    void onMethodCall(const MethodCall &call);
    void onGetDeviceName(const MethodCall &call);
    void unimplemented(const MethodCall &call);
};

Файл packages/aurora/plugin_device/aurora/plugin_device_plugin.cpp

#include <plugin_device/plugin_device_plugin.h>
#include <flutter/method-channel.h>
#include <QtDBus/QtDBus>

/**
 * Регистрация [MethodChannel].
 */
void PluginDevicePlugin::RegisterWithRegistrar(PluginRegistrar &registrar)
{
    registrar.RegisterMethodChannel("plugin_device",
                                    MethodCodecType::Standard,
                                    [this](const MethodCall &call) { this->onMethodCall(call); });
}

/**
 * Метод onMethodCall будет выполняться при вызове MethodChannel из Dart-плагина.
 * По названию, передаваемому из плагина, можно вызвать нужный платформо-зависимый метод.
 */
void PluginDevicePlugin::onMethodCall(const MethodCall &call)
{
    const auto &method = call.GetMethod();
    if (method == "getDeviceName") {
        onGetDeviceName(call);
        return;
    }
    unimplemented(call);
}

/**
 * Платформо-зависимый метод, получающий название устройства
 */
void PluginDevicePlugin::onGetDeviceName(const MethodCall &call)
{
    if (!QDBusConnection::sessionBus().isConnected()) {
        call.SendSuccessResponse(nullptr);
        return;
    }
    QDBusInterface iface("ru.omp.deviceinfo",
        "/ru/omp/deviceinfo/Features",
        "",
        QDBusConnection::sessionBus()
    );
    if (iface.isValid()) {
        QDBusReply<QString> reply = iface.call("getDeviceModel");
        if (reply.isValid()) {
            call.SendSuccessResponse(reply.value().toStdString());
            return;
        }
    }
    call.SendSuccessResponse(nullptr);
}

/**
 * Метод возвращающий [nullptr], если запрашиваемый метод не найден
 */
void PluginDevicePlugin::unimplemented(const MethodCall &call)
{
    call.SendSuccessResponse(nullptr);
}

PluginDevice - Dart-класс, реализующий device_platform_interface и устанавливающий при выполнении метода registerWith нужный экземпляр для взаимодействия с платформо-зависимой частью плагина.

Файл packages/aurora/plugin_device/lib/plugin_device.dart

class PluginDevice extends DevicePlatform {
  /// Метод, который выполнится при старте приложения
  /// В этом методе можно установить платформо-зависимый плагин
  static void registerWith() {
    DevicePlatform.instance = MethodChannelPluginDevice();
  }

  /// Реализация метода интерфейса [DevicePlatform]
  @override
  Future<String?> get deviceName => DevicePlatform.instance.deviceName;
}

MethodChannel класс плагина отличается от подобного класса для Android только названием и ключом для взаимодействия с платформо-зависимой частью.

Файл packages/aurora/plugin_device/lib/plugin_device_method_channel.dart

/// Реализация [PluginDevicePlatform], которая использует каналы методов
class MethodChannelPluginDevice extends DevicePlatform {
  /// Канал метода, используемый для взаимодействия с собственной платформой
  @visibleForTesting
  final methodChannel = const MethodChannel('plugin_device');

  /// Реализация метода получения названия устройства
  /// getDeviceName - название метода, который можно проверить
  /// в платформо-зависимой части плагина
  @override
  Future<String?> get deviceName async {
    return await methodChannel.invokeMethod<String>('getDeviceName');
  }
}