Browse Source

[documentation] Add documentation version 0.1

merge-requests/30/head
Vitaliy Zarubin 1 year ago
parent
commit
0fd94d47dd
  1. 124
      README.md
  2. BIN
      data/preview.png
  3. BIN
      data/preview_app.png
  4. 119
      documentation/dart_package.md
  5. BIN
      documentation/data/preview.png
  6. BIN
      documentation/data/preview_app.png
  7. 185
      documentation/ffi_plugin_package.md
  8. 166
      documentation/plugin_package.md
  9. 123
      documentation/qt_plugin_package.md
  10. 98
      example/app_run.sh

124
README.md

@ -1,60 +1,35 @@
<div align="center">
<img src="data/preview.png" />
</div>
# Плагины для ОС Аврора
Этот репозиторий содержит Flutter плагины для платформы ОС Аврора. Мы находимся в процессе создания необходимых плагинов для разработки всевозможных приложений пользователей.
Если плагин который вы ищете еще не реализован для ОС Аврора оставьте свое сообщение в [issue](https://gitlab.com/omprussia/flutter/flutter-plugins/-/issues), либо рассмотрите возможность самостоятельной разработки плагина для развития Open Source сообщества ОС Аврора. Мы будем рады вашим мерж-реквестам!
# Разработка плагина для ОС Аврора
Подробно процесс создания платформозависимых плагинов описан в статье [«Flutter на ОС Аврора»](#todo).
Если у вас имеются вопросы, присоединяйтесь к [сообществу](https://t.me/aurora_devs) ОС Аврора в Telegram канале, где вы сможете задать интересующий вас вопрос и следить за всеми актульными новостями.
Для разработки платформозависимого плагина, необходимо использовать адаптированный под ОС Аврора [Flutter SDK](https://gitlab.com/omprussia/flutter/flutter).
Ниже перечислены четыре вида плагинов, которые могут
применяться в ОС Аврора.
- ### Dart Package
Пакет написанный на языке Dart, например пакет [`path`](https://pub.dev/packages/path), расширяющий возможности Flutter, добавляя в него новые виджеты или функции, который не является платформозависимым.
- ### Plugin Package
Пакет, предоставляющий API на языке Dart в сочетании с одной или несколькими реализациями под конкретные платформы, использующий механизм [Platform Channels](https://docs.flutter.dev/platform-integration/platform-channels).
Для реализации плагина под ОС Аврора используется язык C++.
![preview.png](documentation/data/preview.png)
- ### Qt Plugin Package
Этот репозиторий содержит плагины Flutter для платформы ОС Аврора. Мы находимся в процессе создания необходимых плагинов для разработки всевозможных приложений пользователей. Если плагин который вы ищете еще не реализован для ОС Аврора оставьте сообщение в [issue](https://gitlab.com/omprussia/flutter/flutter-plugins/-/issues) либо рассмотрите возможность создать пакет самостоятельно. Мы будем рады вашим мерж-реквестам!
Пакет, аналогичный `Plugin Package`, но использующий в реализации под ОС Аврора библиотеку Qt. Данный вид пакета используется в случае, если системное API ОС Аврора, предоставляющее необходимую функциональность, использует библиотеку Qt.
## Разработка плагина для ОС Аврора
ОС Аврора старается минимизировать использование библиотеки Qt в Flutter плагинах, поэтому, если имеется возможность не использовать библиотеку Qt в реализации плагина под ОС Аврора, то лучше ее не использовать.
Что бы создать платформо-зависимый плагин воспользуйтесь [Flutter SDK](https://gitlab.com/omprussia/flutter/flutter) с поддержкой ОС Аврора. Для платформы Аврора доступно четыре варианта создания плагина, все они перечислены ниже с примерами:
- ### FFI Plugin Package
- [Dart package](documentation/dart_package.md);
- [Plugin package](documentation/plugin_package.md);
- [Qt plugin package](documentation/qt_plugin_package.md);
- [FFI Plugin package](documentation/ffi_plugin_package.md).
Пакет, предоставляющий API на языке Dart в сочетании с одной или несколькими реализациями под конкретные платформы, использующий механизм [Dart FFI](https://dart.dev/guides/libraries/c-interop).
Подробно процесс создания платформо-зависимых плагинов можно найти в статье "[Flutter на ОС Аврора](https://habr.com/ru/articles/761176/)". Если остаются вопросы присоединяйтесь к сообществу ОС Аврора "[Aurora Developers](https://t.me/aurora_devs)" в Telegram, там вы сможете задать вопрос по Flutter и следить за новостями.
# Демонстрационное приложение
## Демонстрационное приложение
Плагины из данного проекта объеденены в одно [общее приложение](./example), предназначеное для демонстрации работы реализованных и проверенных на ОС Аврора плагинов.
![preview.png](documentation/data/preview_app.png)
<div align="center">
<img src="data/preview_app.png" />
</div>
Все плагины имеют общее демонстрационное приложение **Flutter example packages**. Оно предназначено для демонстрации работы как платформо-зависимых так и нет плагинов/пакетов. Выполняет роль единого приложения-примера для платформо-зависимых плагинов и позволяет проверить работоспособность не платформо зависимых плагинов на платформе ОС Аврора.
# Платформозависимые плагины Flutter
## Платформо-зависимые плагины Flutter
Список платформозависимых плагинов, реализованых под ОС Аврора, либо зависящих от платформозависимых плагинов.
Список платформо-зависимых плагинов созданных для ОС Аврора либо зависящих от платформо-зависимых плагинов ОС Аврора.
| Плагин ОС Аврора | Версия | Внешний плагин | Версия | Версия ОС Аврора |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|-------------------------------------------------------------------------------------|----------|--------------------|
| [battery_plus_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/battery_plus/battery_plus_aurora) | `0.0.1` | [battery_plus](https://pub.dev/packages/battery_plus) | `4.0.1` | `4.0.2.269` |
| [device_info_plus_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/device_info_plus/device_info_plus_aurora) | `0.0.1` | [device_info_plus](https://pub.dev/packages/device_info_plus) | `8.2.2` | `4.0.2.269` |
| [flutter_keyboard_visibility_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/flutter_keyboard_visibility/flutter_keyboard_visibility_aurora) | `0.0.1` | [flutter_keyboard_visibility](https://pub.dev/packages/flutter_keyboard_visibility) | `5.4.1` | `4.0.2.269` |
| [flutter_keyboard_visibility_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/flutter_keyboard_visibility/flutter_keyboard_visibility_aurora) | `0.0.1` | [flutter_keyboard_visibility](https://pub.dev/packages/flutter_keyboard_visibility) | `5.4.1` | `4.0.2.269` |
| [flutter_local_notifications_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/flutter_local_notifications/flutter_local_notifications_aurora) | `0.0.1` | [flutter_local_notifications](https://pub.dev/packages/flutter_local_notifications) | `14.1.1` | `4.0.2.269` |
| [flutter_secure_storage_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/flutter_secure_storage/flutter_secure_storage_aurora) | `0.0.1` | [flutter_secure_storage](https://pub.dev/packages/flutter_secure_storage) | `8.0.0` | `4.0.2.269` |
| [package_info_plus_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/package_info_plus/package_info_plus_aurora) | `0.0.1` | [package_info_plus](https://pub.dev/packages/package_info_plus) | `3.1.2` | `4.0.2.269` |
@ -63,40 +38,35 @@
| [sqflite_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/sqflite/sqflite_aurora) | `0.0.1` | [sqflite](https://pub.dev/packages/sqflite) | `2.2.6` | `4.0.2.269` |
| [wakelock_aurora](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/wakelock/wakelock_aurora) | `0.0.1` | [wakelock](https://pub.dev/packages/wakelock) | `0.6.2` | `4.0.2.269` |
| [xdga_directories](https://gitlab.com/omprussia/flutter/flutter-plugins/-/tree/master/packages/xdga_directories) | `0.0.1` | - | - | `4.0.2.269` |
| - | - | [flutter_cache_manager](https://pub.dev/packages/flutter_cache_manager) | `3.3.0` | `4.0.2.269` |
| - | - | [cached_network_image](https://pub.dev/packages/cached_network_image) | `3.2.3` | `4.0.2.269` |
| - | - | [google_fonts](https://pub.dev/packages/google_fonts) | `4.0.4` | `4.0.2.269` |
# Пакеты Flutter
Список проверенных на совместимость c ОС Аврора пакетов, не являющихся платформозависимыми.
| Внешний плагин | Версия | Версия ОС Аврора |
|-------------------------------------------------------------------------------------|----------|--------------------|
| [crypto](https://pub.dev/packages/crypto) | `3.0.2` | `4.0.2.269` |
| [cupertino_icons](https://pub.dev/packages/cupertino_icons) | `1.0.5` | `4.0.2.269` |
| [get_it](https://pub.dev/packages/get_it) | `7.6.0` | `4.0.2.269` |
| [intl](https://pub.dev/packages/intl) | `0.17.0` | `4.0.2.269` |
| [photo_view](https://pub.dev/packages/photo_view) | `0.14.0` | `4.0.2.269` |
| [scoped_model](https://pub.dev/packages/scoped_model) | `2.0.0` | `4.0.2.269` |
| [dartz](https://pub.dev/packages/dartz) | `0.10.1` | `4.0.2.269` |
| [freezed](https://pub.dev/packages/freezed) | `2.3.3` | `4.0.2.269` |
| [equatable](https://pub.dev/packages/equatable) | `2.0.5` | `4.0.2.269` |
| [flutter_markdown](https://pub.dev/packages/flutter_markdown) | `0.6.15` | `4.0.2.269` |
| [build_runner](https://pub.dev/packages/build_runner) | `2.3.3` | `4.0.2.269` |
| [freezed_annotation](https://pub.dev/packages/freezed_annotation) | `2.2.0` | `4.0.2.269` |
| [json_annotation](https://pub.dev/packages/json_annotation) | `4.8.0` | `4.0.2.269` |
| [json_serializable](https://pub.dev/packages/json_serializable) | `6.6.1` | `4.0.2.269` |
| [provider](https://pub.dev/packages/provider) | `6.0.5` | `4.0.2.269` |
| [qr_flutter](https://pub.dev/packages/qr_flutter) | `4.0.0` | `4.0.2.269` |
| [rxdart](https://pub.dev/packages/rxdart) | `0.27.7` | `4.0.2.269` |
| [translator](https://pub.dev/packages/translator) | `0.1.7` | `4.0.2.269` |
# Вклад сообщества
Этот проект поддерживается сообществом. Оставляйте ваши вопросы и отзывы в [issues](https://gitlab.com/omprussia/flutter/flutter-plugins/-/issues) проекта,
либо публикуйте ваши наработки в репозиторий через [merge request](https://gitlab.com/omprussia/flutter/flutter-plugins/-/merge_requests).
Помните, что [демонстрационное приложение](./example) содержит не только сложные платформозависимые плагины, но и обычные пакеты, поэтому мы будем рады, если вы проверите ваши любимые Flutter пакеты на работоспособность в ОС Аврора и поделитесь вашими наработками с сообществом.
Мы будем рады любому вашему вкладу в развитие проекта.
| - | - | [flutter_cache_manager](https://pub.dev/packages/flutter_cache_manager) | 3.3.0 | `4.0.2.269` |
| - | - | [cached_network_image](https://pub.dev/packages/cached_network_image) | 3.2.3 | `4.0.2.269` |
| - | - | [google_fonts](https://pub.dev/packages/google_fonts) | 4.0.4 | `4.0.2.269` |
## Пакеты Flutter
Список проверенных на совместимость и работоспособность в ОС Аврора пакетов Flutter не являющиеся платформо-зависимыми.
| Внешний плагин | Версия | Версия ОС Аврора |
|-------------------------------------------------------------------------------------|---------|--------------------|
| [crypto](https://pub.dev/packages/crypto) | 3.0.2 | `4.0.2.269` |
| [cupertino_icons](https://pub.dev/packages/cupertino_icons) | 1.0.5 | `4.0.2.269` |
| [get_it](https://pub.dev/packages/get_it) | 7.6.0 | `4.0.2.269` |
| [intl](https://pub.dev/packages/intl) | 0.17.0 | `4.0.2.269` |
| [photo_view](https://pub.dev/packages/photo_view) | 0.14.0 | `4.0.2.269` |
| [scoped_model](https://pub.dev/packages/scoped_model) | 2.0.0 | `4.0.2.269` |
| [dartz](https://pub.dev/packages/dartz) | 0.10.1 | `4.0.2.269` |
| [freezed](https://pub.dev/packages/freezed) | 2.3.3 | `4.0.2.269` |
| [equatable](https://pub.dev/packages/equatable) | 2.0.5 | `4.0.2.269` |
| [flutter_markdown](https://pub.dev/packages/flutter_markdown) | 0.6.15 | `4.0.2.269` |
| [build_runner](https://pub.dev/packages/build_runner) | 2.3.3 | `4.0.2.269` |
| [freezed_annotation](https://pub.dev/packages/freezed_annotation) | 2.2.0 | `4.0.2.269` |
| [json_annotation](https://pub.dev/packages/json_annotation) | 4.8.0 | `4.0.2.269` |
| [json_serializable](https://pub.dev/packages/json_serializable) | 6.6.1 | `4.0.2.269` |
| [provider](https://pub.dev/packages/provider) | 6.0.5 | `4.0.2.269` |
| [qr_flutter](https://pub.dev/packages/qr_flutter) | 4.0.0 | `4.0.2.269` |
| [rxdart](https://pub.dev/packages/rxdart) | 0.27.7 | `4.0.2.269` |
| [translator](https://pub.dev/packages/translator) | 0.1.7 | `4.0.2.269` |
## Вклад
Этот проект поддерживается сообществом, и мы будем рады вашему вкладу и активности, оставляйте ваши вопросы, отзывы в [issue](https://gitlab.com/omprussia/flutter/flutter-plugins/-/issues) либо вашу работу в [мерж-реквесты](https://gitlab.com/omprussia/flutter/flutter-plugins/-/merge_requests). Помните что **Flutter example packages** содержит не только сложные платформо-зависимые плагины, мы будем рады вкладу в проверку на работоспособность платформо не зависимых плагинов.

BIN
data/preview.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

BIN
data/preview_app.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 KiB

119
documentation/dart_package.md

@ -0,0 +1,119 @@
# Dart package
Пакеты написанные на Dart, например package [`path`](https://pub.dev/packages/path). Они могут содержать специфичные для Flutter функции и иметь зависимость от инфраструктуры Flutter, ограничивая их использование только Flutter, например package [`fluro`](https://pub.dev/packages/fluro).
> Для демонстрации создания платформо-зависимого пакета для ОС Аврора типа "Dart package" был написан и опубликован проект "[Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages)" которые подробно описан в статье "[Flutter на ОС Аврора](https://habr.com/ru/articles/761176/)".
Проект "[Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages)" содержит в себе пакет реализующий платформо-зависимый пакет для ОС Аврора типа "Dart package". Вообще этот тип пакета может быть как платформо-зависимым так и нет. Пакет "[Flutter Device](https://gitlab.com/omprussia/flutter/demo-dart-packages/-/tree/master/packages/aurora/dart_package_device?ref_type=heads)" из проекта [Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages) становится платформо-зависимым использую [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/) ОС Аврора. Данный пакет использует API ОС Аврора - "[Device Info API](https://developer.auroraos.ru/doc/software_development/reference/device_info)".
Пакет Dart в минимальном виде состоит из файла [`pubspec.yaml`](https://dart.dev/tools/pub/pubspec), папки `lib` с как минимум одним файлом `<package-name>.dart`. Создать пакет можно командой:
```shell
$ flutter-aurora create --template=package <package-name>
```
Рассмотрим пакет "[dart_package_device](https://gitlab.com/omprussia/flutter/demo-dart-packages/-/tree/master/packages/aurora/dart_package_device?ref_type=heads)" из проекта [Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages). **dart_package_device** - платформо-зависимая реализация плагина "Flutter Device" для ОС Аврора типа "Dart package". В основе пакета лежит пакет `dbus` - нативная клиентская реализация D-Bus для Dart. С его помощью можно реализовать пакет Dart для ОС Аврора, ни строчки не написав на C++.
Структура пакета **dart_package_device**:
```shell
└── aurora
└── dart_package_device
   ├── lib
     ├── dart_package_device.dart
     └── ru_omp_device_info_features.dart
   ├── ru.omp.deviceinfo.Features.xml
   └── pubspec.yaml
```
Пакет `dbus` позволяет на основе xml-файла с интерфейсом D-Bus генерировать Dart-класс, который позволит выполнить доступные методы.
Файл `packages/aurora/dart_package_device/ru.omp.deviceinfo.Features.xml`
```xml
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="ru.omp.deviceinfo.Features">
<method name="getDeviceModel">
<arg type="s" direction="out"/>
</method>
</interface>
</node>
```
Выполнить генерацию можно командой:
```shell
$ dart-dbus generate-remote-object ./ru.omp.deviceinfo.Features.xml \
-o lib/ru_omp_device_info_features.dart
```
Результат генерации c файла `ru.omp.deviceinfo.Features.xml` следует рассматривать, как отправную точку для реализации.
Файл `packages/aurora/dart_package_device/lib/ru_omp_device_info_features.dart`
```dart
class RuOmpDeviceinfoFeatures extends DBusRemoteObject {
RuOmpDeviceinfoFeatures(
DBusClient client, String destination, DBusObjectPath path)
: super(client, name: destination, path: path);
/// Вызов ru.omp.deviceinfo.Features.getDeviceModel()
Future<String> callGetDeviceModel(
{bool noAutoStart = false,
bool allowInteractiveAuthorization = false}) async {
var result = await callMethod(
'ru.omp.deviceinfo.Features', 'getDeviceModel', [],
replySignature: DBusSignature('s'),
noAutoStart: noAutoStart,
allowInteractiveAuthorization: allowInteractiveAuthorization);
return result.returnValues[0].asString();
}
}
```
Теперь можно реализовать интерфейс **[device_platform_interface](https://gitlab.com/omprussia/flutter/demo-dart-packages/-/tree/master/device_platform_interface?ref_type=heads)** и в методе `registerWith` указать пакет **dart_package_device**, как платформо-зависимый плагин.
Файл `packages/aurora/dart_package_device/lib/dart_package_device.dart`
```dart
/// Метод, который выполнится при старте приложения
/// В этом методе можно установить платформо-зависимый плагин
static void registerWith() {
DevicePlatform.instance = DartPackageDevice();
}
/// Реализация метода интерфейса [DevicePlatform]
@override
Future<String?> get deviceName async {
// Инициализация клиента D-Bus
final client = DBusClient.session();
// Инициализация объекта
final features = RuOmpDeviceinfoFeatures(
client,
'ru.omp.deviceinfo',
DBusObjectPath('/ru/omp/deviceinfo/Features'),
);
// Выполнение метода
final deviceName = await features.callGetDeviceModel();
// Закрытие клиента D-Bus
await client.close();
// Возвращение результата
return deviceName == '' ? null : deviceName;
}
```
В `pubspec.yaml` плагина **dart_package_device** следует указать `dartPluginClass` для того, чтобы с помощью метода `registerWith` прошла регистрация плагина в `общем-плагине` **flutter_device** при старте приложения.
```yaml
flutter:
plugin:
platforms:
aurora:
dartPluginClass: DartPackageDevice
```

BIN
documentation/data/preview.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
documentation/data/preview_app.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

185
documentation/ffi_plugin_package.md

@ -0,0 +1,185 @@
# FFI Plugin package
Специализированный пакет Dart, содержащий API, написанный на Dart, с одной или несколькими реализациями для конкретной платформы, использующими [Dart FFI](https://dart.dev/guides/libraries/c-interop).
> Для демонстрации создания платформо-зависимого плагина для ОС Аврора типа "FFI Plugin package" был написан и опубликован проект "[Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages)" которые подробно описан в статье "[Flutter на ОС Аврора](https://habr.com/ru/articles/761176/)".
Проект "[Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages)" содержит в себе пакет реализующий платформо-зависимый плагин для ОС Аврора типа "FFI Plugin package". Данный пакет использует API ОС Аврора - "[Device Info API](https://developer.auroraos.ru/doc/software_development/reference/device_info)". Плагин использует [QtDBus](https://doc.qt.io/qt-5/qtdbus-index.html) но не является типом плагина "Qt plugin package" так как не использует сигналы и слоты.
Создать пакет "FFI Plugin package" можно командой:
```shell
$ flutter-aurora create --template=plugin_ffi <package-name>
```
Рассмотрим плагин "[ffi_plugin_device](https://gitlab.com/omprussia/flutter/demo-dart-packages/-/tree/master/packages/aurora/ffi_plugin_device?ref_type=heads)" из проекта [Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages). **ffi_plugin_device** - платформо-зависимая реализация плагина "Flutter Device" для ОС Аврора типа "FFI Plugin package".
Структура пакета **ffi_plugin_device**
```shell
└── aurora
└── ffi_plugin_device
   ├── aurora
     └── CMakeLists.txt
   ├── ffigen.yaml
   ├── lib
     ├── ffi_plugin_device_bindings_generated.dart
     └── ffi_plugin_device.dart
   ├── pubspec.yaml
   └── src
   ├── CMakeLists.txt
   ├── ffi_plugin_device.cpp
   └── ffi_plugin_device.h
```
Для генерации привязок FFI можно использовать плагин [`ffigen`](https://pub.dev/packages/ffigen). Пакет, предоставляющий утилиты для работы с кодом интерфейса внешних функций, называется [`ffi`](https://pub.dev/packages/ffi). В `pubspec.yaml` плагина нужно добавить зависимости и активировать `ffiPlugin` для платформы ОС Аврора.
```yaml
dependencies:
ffi: ^2.0.2
dev_dependencies:
ffigen: ^7.2.7
flutter:
plugin:
platforms:
aurora:
ffiPlugin: true
dartPluginClass: FFIPluginDevice
```
Для генерации привязок нужно добавить файл `ffigen.yaml` в корень плагина.
Файл `packages/aurora/ffi_plugin_device/ffigen.yaml`
```yaml
name: PluginDeviceBindings
llvm-path:
- '/usr/lib/llvm-14/lib/libclang.so' # Ubuntu 22.04
- '/usr/lib/llvm-15/lib/libclang.so' # Ubuntu 23.04
description: |
Bindings for `src/ffi_plugin_device.h`.
output: 'lib/ffi_plugin_device_bindings_generated.dart'
headers:
entry-points:
- 'src/ffi_plugin_device.h'
include-directives:
- 'src/ffi_plugin_device.h'
comments:
style: any
length: full
```
В файле `ffigen.yaml` указываются хедеры нужных библиотек. В данном случае библиотека лежит в папке `src`, которая получает название модели устройства с помощью [`Qt D-Bus`](https://doc.qt.io/qt-5/qtdbus-index.html).
Файл `packages/aurora/ffi_plugin_device/src/ffi_plugin_device.h`
```cpp
#ifdef __cplusplus
extern "C" {
#endif
char *getDeviceName();
#ifdef __cplusplus
}
#endif
```
Файл `packages/aurora/ffi_plugin_device/src/ffi_plugin_device.cpp`
```cpp
#include <QStandardPaths>
#include <QtDBus/QtDBus>
#include "ffi_plugin_device.h"
char *getDeviceName()
{
QString deviceName = "";
if (QDBusConnection::sessionBus().isConnected()) {
QDBusInterface iface("ru.omp.deviceinfo",
"/ru/omp/deviceinfo/Features",
"",
QDBusConnection::sessionBus()
);
if (iface.isValid()) {
QDBusReply<QString> reply = iface.call("getDeviceModel");
if (reply.isValid()) {
deviceName = reply.value();
}
}
}
return deviceName.toUtf8().data();
}
```
Выполнить генерацию FFI-привязок можно следующей командой, выполнив её из корня плагина (например, `packages/aurora/ffi_plugin_device`):
```shell
flutter-aurora pub run ffigen --config ffigen.yaml
```
В папке `lib` будет сгенерирован файл `ffi_plugin_device_bindings_generated.dart`.
Файл `packages/aurora/ffi_plugin_device/lib/ffi_plugin_device_bindings_generated.dart`
```dart
import 'dart:ffi' as ffi;
/// Bindings for `src/ffi_plugin_device.h`.
class PluginDeviceBindings {
/// Holds the symbol lookup function.
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
_lookup;
/// The symbols are looked up in [dynamicLibrary].
PluginDeviceBindings(ffi.DynamicLibrary dynamicLibrary)
: _lookup = dynamicLibrary.lookup;
/// The symbols are looked up with [lookup].
PluginDeviceBindings.fromLookup(
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
lookup)
: _lookup = lookup;
ffi.Pointer<ffi.Char> getDeviceName() {
return _getDeviceName();
}
late final _getDeviceNamePtr =
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>(
'getDeviceName');
late final _getDeviceName =
_getDeviceNamePtr.asFunction<ffi.Pointer<ffi.Char> Function()>();
}
```
Теперь можно создать класс `FFIPluginDevice`, реализующий интерфейс **[device_platform_interface](https://gitlab.com/omprussia/flutter/demo-dart-packages/-/tree/master/device_platform_interface?ref_type=heads)**.
Файл `packages/aurora/ffi_plugin_device/lib/ffi_plugin_device.dart`
```dart
class FFIPluginDevice extends DevicePlatform {
/// Метод, который выполнится при старте приложения
/// В этом методе можно установить платформо-зависимый плагин
static void registerWith() {
DevicePlatform.instance = FFIPluginDevice();
}
/// Привязки к нативным функциям в [_dylib].
final PluginDeviceBindings _bindings = PluginDeviceBindings(
DynamicLibrary.open('libffi_plugin_device.so'),
);
/// Реализация метода интерфейса [DevicePlatform]
@override
Future<String?> get deviceName async {
// Получение deviceName
final deviceName = _bindings.getDeviceName().cast<Utf8>().toDartString();
// Возврат результата
return deviceName == '' ? null : deviceName;
}
}
```

166
documentation/plugin_package.md

@ -0,0 +1,166 @@
# Plugin package
Специализированный пакет Dart, содержащий API, написанный на Dart, в сочетании с одной или несколькими реализациями для конкретной платформы. Пакеты плагинов могут быть написаны для Android (с использованием Kotlin или Java), ОС Аврора (с использование С++), iOS (с использованием Swift или Objective-C), Интернета, macOS, Windows или Linux или любой их комбинации.
> Для демонстрации создания платформо-зависимого пакета для ОС Аврора типа "Plugin package" был написан и опубликован проект "[Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages)" которые подробно описан в статье "[Flutter на ОС Аврора](https://habr.com/ru/articles/761176/)".
Проект "[Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages)" содержит в себе пакет реализующий платформо-зависимый плагин для ОС Аврора типа "Plugin package". Данный пакет использует API ОС Аврора - "[Device Info API](https://developer.auroraos.ru/doc/software_development/reference/device_info)". Плагин использует [QtDBus](https://doc.qt.io/qt-5/qtdbus-index.html) но не является типом плагина "Qt plugin package" так как не использует сигналы и слоты.
Создать пакет "Plugin package" можно командой:
```shell
$ flutter-aurora create --template=plugin <package-name>
```
Рассмотрим плагин "[plugin_device](https://gitlab.com/omprussia/flutter/demo-dart-packages/-/tree/master/packages/aurora/plugin_device?ref_type=heads)" из проекта [Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages). **plugin_device** - платформо-зависимая реализация плагина "Flutter Device" для ОС Аврора типа "Plugin package".
Структура пакета **plugin_device**:
```shell
└── 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`.
```yaml
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`
```cpp
#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`
```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](https://gitlab.com/omprussia/flutter/demo-dart-packages/-/tree/master/device_platform_interface?ref_type=heads)** и устанавливающий при выполнении метода `registerWith` нужный экземпляр для взаимодействия с платформо-зависимой частью плагина.
Файл `packages/aurora/plugin_device/lib/plugin_device.dart`
```dart
class PluginDevice extends DevicePlatform {
/// Метод, который выполнится при старте приложения
/// В этом методе можно установить платформо-зависимый плагин
static void registerWith() {
DevicePlatform.instance = MethodChannelPluginDevice();
}
/// Реализация метода интерфейса [DevicePlatform]
@override
Future<String?> get deviceName => DevicePlatform.instance.deviceName;
}
```
[MethodChannel](https://api.flutter.dev/flutter/services/MethodChannel-class.html) класс плагина отличается от подобного класса для Android только названием и ключом для взаимодействия с платформо-зависимой частью.
Файл `packages/aurora/plugin_device/lib/plugin_device_method_channel.dart`
```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');
}
}
```

123
documentation/qt_plugin_package.md

@ -0,0 +1,123 @@
# Qt plugin package
Qt plugin package - является обычным плагином типа "[Plugin package](#todo)", но использующего Qt сигналы и слоты. Проект "[Demo Dart Packages](https://gitlab.com/omprussia/flutter/demo-dart-packages)" содержит в себе пакет реализующий платформо-зависимый плагин для ОС Аврора типа "Plugin package", на его примере покажем как подключить сигналы и слоты к плагину.
Плагин уже имеет в зависимостях Qt, но в нем не будут работать сигналы и слоты. Для их подключения следует добавить зависимости в класс реализующий `PluginInterface`:
Файл `packages/aurora/plugin_device/aurora/include/plugin_device/plugin_device_plugin.h`
```cpp
#include <flutter/plugin-interface.h>
#include <plugin_device/globals.h>
#include <QtCore>
class PLUGIN_EXPORT PluginDevicePlugin final
: public QObject,
public PluginInterface
{
Q_OBJECT
public:
void RegisterWithRegistrar(PluginRegistrar &registrar) override;
private:
void onMethodCall(const MethodCall &call);
void onGetDeviceName(const MethodCall &call);
void unimplemented(const MethodCall &call);
};
```
А в файл реализации добавить в низ файла `#include "moc_sensors_plus_aurora_plugin.cpp"`:
Файл `packages/aurora/plugin_device/aurora/plugin_device_plugin.cpp`
```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);
}
#include "moc_sensors_plus_aurora_plugin.cpp"
```
И для того что бы мок файл сгенерировался добавим в [set_target_properties](https://cmake.org/cmake/help/latest/command/set_target_properties.html) `AUTOMOC ON`:
Файл `packages/aurora/plugin_device/aurora/CMakeLists.txt`
```
set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden AUTOMOC ON)
```
Для работы плагина в приложении Qt нужно включить отдельно. Сделать это можно добавив в `main` функцию приложения вызов метода `EnableQtCompatibility()`. Выглядеть это может следующим образом:
```cpp
#include <flutter/application.h>
#include <flutter/compatibility.h>
#include "generated_plugin_registrant.h"
int main(int argc, char *argv[]) {
Application::Initialize(argc, argv);
EnableQtCompatibility(); // Включение "Qt plugin package" плагинов
RegisterPlugins();
Application::Launch();
return 0;
}
```
Добавив зависимости в плагин начнут работать сигналы и слоты Qt. ОС Аврора очень зависит от Qt, во Flutter мы стараемся минимизировать эту зависимость. Если есть возможность выбора типа для реализации платформо-зависимого плагина использование Qt нежелательно.

98
example/app_run.sh

@ -0,0 +1,98 @@
#!/bin/bash
# Copyright (c) 2023. Open Mobile Platform LLC.
# License: Proprietary.
## Build example, sign rpm, upload/install/run rpm to device
## Usage
##
## chmod +x ./run.sh
##
## ./run.sh \
## -d <ip>:<password> \
## -s /home/user/sign/folder
## -p ru.auroraos.flutter_example_packages
sudo echo 'Run...';
## Flutter path
FLUTTER="$HOME/.local/opt/flutter/bin/flutter"
## https://developer.auroraos.ru/doc/software_development/psdk/setup
## Install Platform SDK path
## You may not have set the PSDK_DIR environment variable.
## export PSDK_DIR=$HOME/AuroraPlatformSDK/sdks/aurora_psdk
while getopts d:s:p: flag; do
case "${flag}" in
d) device=${OPTARG} ;;
s) sign=${OPTARG} ;;
p) package=${OPTARG} ;;
*)
echo "usage: $0 [-d] [-s] [-p]" >&2
exit 1
;;
esac
done
if [ -z "$package" ]; then
echo "Specify package"
exit 1;
fi
## Update dependency
$FLUTTER pub get
## Generate internationalizing
$FLUTTER pub run build_runner build --delete-conflicting-outputs
## Build aurora example app
{
$FLUTTER build aurora --release
} || {
exit 1;
}
if [ -n "$sign" ]; then
key=$(ls "$sign"/*key.pem)
if [ -z "$key" ]; then
echo "Key *key.pem not found."
exit 1;
fi
cert=$(ls "$sign"/*cert.pem)
if [ -z "$cert" ]; then
echo "Key *cert.pem not found."
exit 1;
fi
## Sign rpm system key
"$PSDK_DIR"/sdk-chroot rpmsign-external sign \
--key "$key" \
--cert "$cert" \
build/aurora/arm/release/RPMS/*.rpm
fi
if [ -n "$device" ]; then
IFS=':' read -ra ADDR <<< "$device"
D_IP="${ADDR[0]}"
D_PASS="${ADDR[1]}"
# shellcheck disable=SC2012
rpm=$(ls "$PWD"/build/aurora/arm/release/RPMS/*.rpm | sort -r | head -n 1)
# upload rpm
scp "$rpm" defaultuser@"$D_IP:/home/defaultuser/Downloads"
# install rpm
ssh -t defaultuser@"$D_IP" "echo $D_PASS | devel-su pkcon -y install-local /home/defaultuser/Downloads/$package*.rpm"
# run application
ssh -t defaultuser@"$D_IP" "/usr/bin/$package"
fi
Loading…
Cancel
Save