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 ®istrar) 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 ®istrar)
{
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');
}
}