Configuração no Android
Introdução
O Qt oferece um excelente suporte ao Android, mas os aplicativos exigem uma quantidade considerável de modificações para funcionar corretamente no Android.
Algumas coisas são necessárias:
- Um blueprint Craft
- Configurando o qqc2-breeze-style
- Ícones incluídos no aplicativo
- Um manifesto Android
- Opcionalmente, um arquivo de build do Gradle
- Opcionalmente, um arquivo XML de tela de apresentação
- Função do CMake para empacotar para Android
O blueprint Craft é necessário para agrupar todas as dependências com o aplicativo para gerar um pacote APK do Android.
O qqc2-breeze-style é uma alternativa ao qqc2-desktop-style, voltada especialmente para plataformas móveis, como o Android e o Plasma Mobile.
O blueprint do Craft para o aplicativo requer código condicional para evitar a mistura de estilos para desktop e dispositivos móveis, enquanto o código em C++ exigirá cuidado especial para não utilizar configurações inadequadas para cada um desses ambientes. O código do CMake também pode, opcionalmente, precisar de trechos condicionais, embora isso possa ser evitado.
O empacotamento dos ícones necessários para o funcionamento do aplicativo é realizado com o auxílio dos extra-cmake-modules do KDE, das ferramentas de empacotamento de recursos do Qt, bem como das funções CMake do Kirigami e do Kirigami Addons.
O manifesto do Android declara os metadados e os arquivos adicionais que precisam ser incluídos no pacote do aplicativo Android.
O arquivo de compilação do Gradle é necessário caso você utilize a integração com o extra-cmake-modules para aplicar metadados existentes do seu aplicativo à compilação para Android — como a versão do aplicativo —, ou caso deseje definir opções de compilação específicas.
O arquivo XML da tela de apresentação é necessário caso você queira adicionar uma tela de apresentação com ícone, plano de fundo e posicionamento personalizados.
Blueprint Craft
Configurando o qqc2-breeze-style
Para começar a usar o qqc2-breeze-style, você precisará adicioná-lo ao Craft. Como ele é utilizado apenas no Android, será necessária uma cláusula condicional, especialmente se o aplicativo já estiver configurado para ser compilado no Windows e/ou Linux usando o qqc2-desktop-style. Isso exige a importação do módulo CraftCore:
from CraftCore import CraftCore
# ...
def setDependencies(self):
# ...
if not CraftCore.compiler.isAndroid:
self.runtimeDependencies["kde/frameworks/tier1/breeze-icons"] = None
self.runtimeDependencies["kde/frameworks/tier3/qqc2-desktop-style"] = None
else:
self.runtimeDependencies["kde/plasma/qqc2-breeze-style"] = NoneUma lógica semelhante — "se não for Android, use qqc2-desktop-style; caso contrário, use qqc2-breeze-style" — também precisa ser aplicada ao CMake, para o caso de qualquer um dos métodos de localização do qqc2-desktop-style ser utilizado:
if (NOT ANDROID)
find_package(KF6QQC2DesktopStyle REQUIRED)
ecm_find_qmlmodule(org.kde.desktop REQUIRED)
endif()Código condicional também é necessário em C++.
No Android, os aplicativos KDE não utilizam QApplication, mas sim QGuiApplication. Além de definir o qqc2-breeze-style especificamente para o Android, é preciso cuidar da ordem de inicialização, considerando a grande probabilidade de que seu aplicativo já seja compatível com a versão para desktop. Isso pode ser feito da seguinte maneira:
int main(int argc, char* argv[])
{
KIconTheme::initTheme();
#ifdef Q_OS_ANDROID
QGuiApplication app(argc, argv);
QQuickStyle::setStyle("org.kde.breeze");
#else
QIcon::setFallbackThemeName("breeze");
if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE"))
{
QQuickStyle::setStyle("org.kde.desktop");
}
QApplication app(argc, argv);
// ...
#endif
}Uso do KirigamiAppDefaults
Se você utilizar KirigamiAppDefaults::Apply(), o código C++ acima já é gerenciado para você.Empacotando os ícones
A primeira coisa necessária para que o aplicativo use os ícones do Breeze é incluir KIconThemes em seu projeto.
Alguns comandos CMake são necessários para incluir o ícone do seu aplicativo no pacote do app.
Por fim, um comando CMake adicional, proveniente do Kirigami, pode ser utilizado para incorporar ícones do Kirigami à sua aplicação (e, opcionalmente, ícones do Kirigami Addons).
KIconThemes
Isso pode ser feito por meio de:
- Adicionando-o como uma dependência no Craft:
def setDependencies(self):
self.runtimeDependencies["kde/frameworks/tier3/kiconthemes"] = None- Adicionando-o como uma dependência no CMake:
find_package(KF6 REQUIRED COMPONENTS IconThemes)
# ...
target_link_libraries(kirigami-hello
PRIVATE
# ...
KF6::IconThemes
)- Utilizando-o em código C++, no arquivo
main.cpp:
#include <KIconTheme>
// ...
int main(int argc, char* argv[])
{
KIconTheme::initTheme();
QApplication app(argc, argv);
// ...
}Observe que, embora o nome do projeto e a chamada do CMake usem o plural (KIconThemes, KF6IconThemes), a chamada do C++ usa o singular (KIconTheme).
O KIconThemes precisa ser inicializado antes da aplicação.
Uso do KirigamiAppDefaults
Se você utilizar KirigamiAppDefaults::Apply(), a inicialização do KIconThemes mencionada acima, no código em C++, já é gerenciada automaticamente para você.Ícone do aplicativo
Se o seu aplicativo tiver um ícone, ele precisa ser adicionado ao seu projeto tanto como um recurso QML quanto como parte da instalação do ícone.
Normalmente, no Linux, o ícone do aplicativo pode ser simplesmente instalado no diretório correto e será buscado pelo aplicativo quando necessário. Geralmente, o ícone do aplicativo consiste em um ícone SVG principal, combinado com vários tamanhos de ícones PNG.
A instalação do ícone SVG é feita da seguinte forma no CMake:
install(FILES ${CMAKE_SOURCE_DIR}/icons/org.kde.myapp.svg
DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps)E a instalação dos ícones PNG é feita da seguinte forma:
ecm_install_icons(ICONS
16-apps-myapp.png
24-apps-myapp.png
32-apps-myapp.png
48-apps-myapp.png
64-apps-myapp.png
128-apps-myapp.png
256-apps-myapp.png
512-apps-myapp.png
DESTINATION share/icons)Quando o ícone do aplicativo é instalado no Linux, um ícone PNG como 48-apps-myapp.png é instalado em ${INSTALL_PREFIX}/share/icons/hicolor/48x48/apps/myapp.png, e um ícone SVG é instalado em ${INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/org.kde.myapp.svg, onde ${INSTALL_PREFIX} geralmente representa /usr, /usr/local ou ~/.local. Observe como, no caso dos PNGs, o nome do ícone se traduz no caminho que ele terá no sistema de arquivos.
Uma vez que o ícone esteja instalado dessa forma, ele pode ser referenciado no código QML simplesmente como meuapp ou org.kde.meuapp, da mesma maneira que seria chamado por meio de QIcon::fromTheme(). Isso pode ser utilizado com qualquer componente QML que possua uma propriedade icon.name.
O Android não possui um diretório padrão como esse, e instalar o ícone não tem efeito; ele precisa ser incluído no aplicativo. Para isso, o PNG pode ser enviado para seu próprio diretório de instalação ecm_add_app_icon() e um arquivo PNG ou SVG pode ser incorporado ao aplicativo como um arquivo de recurso Qt em ecm_add_qml_module() ou ecm_target_qml_sources().
O ícone PNG do aplicativo é instalado com:
ecm_add_app_icon(myapp ICONS ${PROJECT_SOURCE_DIR}/icons/256-apps-myapp.png)E o ícone principal do aplicativo é incluído como um recurso Qt com:
ecm_add_qml_module(myapp URI org.kde.myapp)
ecm_target_qml_sources(myapp SOURCES Main.qml RESOURCES ../icons/org.kde.myapp.svg)Isso tornará o ícone do aplicativo disponível como um recurso Qt em qrc:/qt/qml/org/kde/myapp/org.kde.myapp.svg. Isso pode ser usado com qualquer controle QML que tenha uma propriedade icon.source.
O caminho RESOURCES depende do local onde os ícones estão instalados. Tradicionalmente, uma pasta icons/ é criada na raiz do projeto para armazenar todos os ícones, já que eles não são considerados arquivos de fonte.
Após os ícones serem instalados (para Linux) e empacotados (para Windows e Android), você pode defini-los no código. No código QML, para compatibilidade com Windows e Android, você deve usar o ícone empacotado; no código C++, principalmente ao definir o ícone da janela, você pode usar o ícone do tema por padrão e o ícone empacotado como alternativa para QGuiApplication::setWindowIcon():
QGuiApplication::setWindowIcon(QIcon::fromTheme("org.kde.myapp", QIcon(":/qt/qml/org/kde/myapp/org.kde.myapp.svg")));Ícones do Kirigami
Embora o Android não tenha um diretório padrão para instalar ícones de um tema de ícones, é possível incluir os ícones Kirigami necessários junto com seu aplicativo Android.
Duas coisas são necessárias para que isso seja feito:
- Prepare o projeto com o KIconThemes
- Inclua breeze-icons no seu blueprint do Craft
- kirigami_package_breeze_icons()
Para configurar os temas KIconThemes, consulte a seção acima KIconThemes.
Para adicionar os breeze-icons como uma dependência do seu projeto, adicione isto ao seu blueprint do Craft:
def setDependencies(self):
# ...
self.runtimeDependencies["kde/frameworks/tier1/breeze-icons"] = NoneDevido à forma como a compilação para Android é realizada, não é possível que o Craft realize automaticamente o empacotamento dos ícones. Por isso, o Kirigami disponibiliza uma função do CMake kirigami_package_breeze_icons(), que, durante a compilação, clona e prepara os ícones para o empacotamento. Este comando deve ser executado antes da etapa detalhada na Função do CMake para empacotamento para Android.
O comando kirigami_package_breeze_icons() do CMake não precisa estar envolto em uma condicional, visto que ele só é executado quando o sistema é o Android.
Além disso, se você estiver utilizando o Kirigami Addons em seu aplicativo, pode passar a variável ${KIRIGAMI_ADDONS_ICONS} para também incluir os ícones necessários para componentes como FormCard.AboutPage e outros semelhantes.
kirigami_package_breeze_icons(ICONS
org.kde.myapp insert-image-symbolic kde application-exit-symbolic
edit-clear-all-symbolic edit-undo-symbolic document-save-symbolic
applications-development-symbolic system-user-list donate-symbolic
${KIRIGAMI_ADDONS_ICONS}
)Manifesto Android
Um manifesto do Android é um arquivo XML que descreve o aplicativo para as ferramentas de compilação do Android, para o sistema operacional e para as lojas de aplicativos. O arquivo deve se chamar AndroidManifest.xml.
O Qt utiliza o manifesto do Android e oferece suporte a configurações adicionais para acionar as ferramentas necessárias à criação de um APK que possa ser instalado no Android.
Os aplicativos do KDE mantêm o manifesto armazenado em um diretório android/ na raiz do projeto.
Um manifesto do Android pode ser assim:
<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.kde.myapp"
android:installLocation="auto">
<application android:name="org.qtproject.qt.android.bindings.QtApplication" android:label="MyApp" android:usesCleartextTraffic="true" android:icon="@drawable/myapp">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="org.qtproject.qt.android.bindings.QtActivity"
android:label="MyApp"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<meta-data android:name="android.app.lib_name" android:value="myapp"/>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
</manifest>Trata-se, em grande parte, de um modelo padrão que pode ser copiado e adaptado a um projeto existente; no entanto, vale a pena entender quais elementos precisam ser levados em consideração.
Na etiqueta <manifest>, o atributo package corresponde ao nome que identifica o aplicativo internamente no Android. Ele deve utilizar a notação de DNS reverso. Além disso, deve coincidir com o ID do aplicativo especificado no código.
Nas etiquetas <application> e <activity>, o atributo android:label deve corresponder ao nome do aplicativo que será exibido ao usuário. Na etiqueta <meta-data>, o atributo android:value deve corresponder ao nome de destino especificado no CMake.
Na etiqueta <application>, o atributo android:icon="@drawable/myapp" deve referenciar um ícone armazenado em android/res/drawable/, sem a extensão do arquivo. Neste exemplo, o arquivo seria android/res/drawable/myapp.png. A pasta res significa "recursos". Caso não seja especificado, o ícone padrão do Android será exibido no menu do aplicativo e na tela de instalação.
Uma Atividade representa o que o aplicativo fará em diferentes estados. Por exemplo, ele pode executar determinadas ações enquanto está em primeiro plano e outras ações enquanto está em segundo plano. Normalmente, um aplicativo Qt/KDE possui apenas uma atividade.
Cada Atividade pode ter um ou mais Filtros de Intent. Uma Intent representa algo que a Atividade é capaz de realizar — no caso de um aplicativo KDE, trata-se geralmente de uma ação, mas também pode ser um serviço. Por exemplo, se o aplicativo tem a intenção de ser iniciado, ele precisa sinalizar ao Android que aquela Atividade é o ponto de entrada do aplicativo (android.intent.action.MAIN) e que essa Intent é do tipo LAUNCHER, permitindo que ele apareça na tela do menu de aplicativos e possa ser executado. Em geral, isso deve ser suficiente para a maioria dos aplicativos KDE.
A etiqueta <meta-data> pode ser repetida várias vezes e ter diversas finalidades; além disso, é possível utilizar configurações específicas do Qt. O metadado android.app.lib_name é obrigatório.
A etiqueta <uses-permission> é simples e permite que o aplicativo solicite permissão para realizar uma ação específica. Uma permissão difere de uma Intent pelo fato de que a Intent solicita a outro componente a execução de uma ação relacionada à atividade, enquanto uma permissão é uma solicitação de acesso a uma funcionalidade que, por padrão, não está disponível.
A etiqueta <supports-screens> especifica quais formatos (tamanhos de tela e densidades de pixels, celulares ou tablets) o aplicativo suporta. Como os aplicativos QML são convergentes, "qualquer tamanho" deve ser um padrão razoável.
As únicas partes do exemplo acima que não são obrigatórias são android:icon="@drawable/myapp" (utilizada apenas se o seu aplicativo já possuir um ícone) e <uses-permissions> (que deve ser adicionada somente quando for realmente necessária).
Tela de apresentação
Uma tela de apresentação é uma tela opcional, contendo uma imagem estática ou uma animação, que aparece ao iniciar um aplicativo, permitindo que ele tenha alguns segundos para ser inicializado. Quando nenhuma tela de apresentação é definida, o aplicativo é exibido assim que é aberto, mesmo que ainda não esteja pronto.
Para adicioná-la ao seu aplicativo, você precisará especificá-la nos metadados do AndroidManifest.xml:
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>Por sua vez, um arquivo android/res/drawable/splash.xml deve existir:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:width="128dp" android:height="128dp" android:gravity="center">
<bitmap
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitXY"
android:src="@drawable/myapp"/>
</item>
</layer-list>Este exemplo simples, comumente utilizado em aplicativos KDE, centraliza o ícone do aplicativo em um fundo vazio; por isso, é necessário que um ícone de aplicativo esteja presente em android/res/drawable/.
Preparando um APK
O último passo necessário para, de fato, permitir a criação de um APK para Android é uma função simples do CMake que utiliza os arquivos presentes no diretório android/:
ecm_add_android_apk(myapp
ANDROID_DIR ${PROJECT_SOURCE_DIR}/android
)Compilação
Para compilar seu aplicativo no Android, siga Compilando aplicativos para Android.
Compilações CI
Se o projeto foi configurado corretamente para compilar no Windows e está usando a infraestrutura do KDE para hospedagem de código (KDE Invent), é possível configurar tarefas de CI/CD para Android.
Para fazer isso, você precisará adicionar os modelos de CI relevantes para Windows com um arquivo .gitlab-ci.yaml e listar suas dependências em um arquivo .kde-ci.yaml, como mencionado em Sistema de Integração Contínua.