10 changed files with 738 additions and 77 deletions
			
			
		| Before Width: | Height: | Size: 134 KiB | 
| Before Width: | Height: | Size: 318 KiB | 
| After Width: | Height: | Size: 160 KiB | 
| After Width: | Height: | Size: 367 KiB | 
| @ -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 ®istrar) 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 ®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); | ||||
| } | ||||
| 
 | ||||
| #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 нежелательно.  | ||||
| @ -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…
					
					
				
		Reference in new issue