Kivy. Construir pacotes para Android e sem mágica


No artigo de ontem de Python sobre desenvolvimento Mobile , que falou sobre a biblioteca KivyMD (uma coleção de widgets no estilo Design de Materiais para uso na estrutura de plataforma cruzada Kivy), nos comentários me pediram nos comentários para falar sobre o processo de criação do pacote para a plataforma Android. Para muitos, esse processo, infelizmente, foi e continua sendo uma espécie de xamanismo mágico e não um assunto para iniciantes. Bem, vamos descobrir, tudo é realmente complicado e eu sou realmente um mágico e mago ...



Claro que ele poderia! Então, você escreveu seu código em Python e Kivy. O que é necessário para executá-lo em dispositivos Android? Vá para o repositório do KivyMD e verá que estas instruções explicaram há muito tempo as etapas que permitem coletar o pacote APK:

  1. Faça o download do XUbuntu 18.04

Instale o Virtual Box no seu computador.
Crie uma nova máquina virtual com base em uma imagem baixada do XUbuntu
Inicie a máquina virtual XUbuntu, abra um terminal e execute o seguinte comando:

wget https://github.com/HeaTTheatR/KivyMD-data/raw/master/install-kivy-buildozer-dependencies.sh 

 chmod +x install-kivy-buildozer-dependencies.sh 

 ./install-kivy-buildozer-dependencies.sh 

Isso é tudo! Agora você tem uma máquina virtual para criar pacotes APK para aplicativos Kivy! O que vem a seguir? Vamos realmente criar um aplicativo de teste. Crie o diretório TestKivyMD no diretório inicial da sua máquina virtual com o arquivo main.py vazio:


Em seguida, abra o arquivo main.py e escreva o código para o nosso aplicativo de teste que usará a biblioteca KivyMD:

 from kivy.lang import Builder from kivymd.app import MDApp KV = """ Screen: MDToolbar: title: "My firt app" elevation: 10 md_bg_color: app.theme_cls.primary_color left_action_items: [["menu", lambda x: x]] pos_hint: {"top": 1} MDRaisedButton: text: "Hello World" pos_hint: {"center_x": .5, "center_y": .5} """ class HelloWorld(MDApp): def build(self): return Builder.load_string(KV) HelloWorld().run() 

Salve, abra o terminal no diretório com o arquivo main.py e instale a biblioteca KivyMD:

 sudo pip3 install kivymd 

Após a instalação, você pode testar nosso código:

 python3 main.py 

O resultado do script será uma tela com a barra de ferramentas e um botão "Hello World":


Em seguida, precisamos criar o arquivo de especificação buildozer.spec, que deve estar localizado no mesmo diretório que o arquivo main.py:


Se você não fechou o terminal (se o terminal estiver fechado, abra-o no diretório TestKivyMD), digite o comando:

 buildozer init 

Este comando criará um arquivo de especificação padrão. Abra-o e edite:

 [app] # (str) Title of your application title = KivyMDTest # (str) Package name package.name = kivymd_test # (str) Package domain (needed for android/ios packaging) package.domain = com.heattheatr # (str) Source code where the main.py live source.dir = . # (list) Source files to include (let empty to include all the files) source.include_exts = py,png,jpg,jpeg,ttf # (list) Application version version = 0.0.1 # (list) Application requirements # comma separated eg requirements = sqlite3,kivy requirements = python3,kivy==1.11.1,kivymd # (str) Supported orientation (one of landscape, sensorLandscape, portrait or all) orientation = portrait # (bool) Indicate if the application should be fullscreen or not fullscreen = 1 # (list) Permissions android.permissions = INTERNET,WRITE_EXTERNAL_STORAGE # (int) Target Android API, should be as high as possible. android.api = 28 # (int) Minimum API your APK will support. android.minapi = 21 # (str) Android NDK version to use android.ndk = 17c # (bool) If True, then skip trying to update the Android sdk # This can be useful to avoid excess Internet downloads or save time # when an update is due and you just want to test/build your package android.skip_update = False # (bool) If True, then automatically accept SDK license # agreements. This is intended for automation only. If set to False, # the default, you will be shown the license when first running # buildozer. android.accept_sdk_license = True # (str) The Android arch to build for, choices: armeabi-v7a, arm64-v8a, x86, x86_64 android.arch = armeabi-v7a [buildozer] # (int) Log level (0 = error only, 1 = info, 2 = debug (with command output)) log_level = 2 # (int) Display warning if buildozer is run as root (0 = False, 1 = True) warn_on_root = 0 # (str) Path to build artifact storage, absolute or relative to spec file build_dir = ./.buildozer # (str) Path to build output (ie .apk, .ipa) storage bin_dir = ./bin 

Tudo está claro aqui, portanto, comentários adicionais são desnecessários. Leia atentamente a especificação padrão, nela você pode especificar o caminho para o ícone, piscar ao carregar o aplicativo e muito mais. Deixei apenas o que precisamos agora para criar nosso pacote de teste. E, de fato, começamos o processo de construção com o comando no terminal:

 buildozer android debug 

Você pode ir à cozinha com segurança e fazer café, porque pela primeira vez o processo de carregamento e compilação de bibliotecas levará muito tempo. Todas as montagens subsequentes levam de 10 a 20 segundos.

O café está bêbado e é hora de olhar para o terminal:


Voila! Nossa aplicação é construída! É hora de soltá-lo em seu smartphone e executar:


Tudo funciona! E acontece que nem tudo é tão complicado quanto parecia.

Eles também me perguntaram:


Nem o Flutter nem o React Native têm vantagens sobre a linguagem de marcação do Kivy Language, que permite criar e posicionar layouts e widgets ao vivo. Quanto a mim, a maneira como a interface do usuário é criada no Flutter é uma verdadeira perversão. Somente uma pessoa doente poderia pensar nisso. Para não ser infundado, vejamos o código Flutter e o código Kivy do mesmo aplicativo simples ... Ele ficará assim:


A seguir, dou o código do artigo Sobre o Flutter, brevemente: Noções básicas :

 import 'package:flutter/widgets.dart'; main() => runApp( Directionality( textDirection: TextDirection.ltr, child: Container( color: Color(0xFFFFFFFF), child: App(), ), ), ); class App extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: GestureDetector( //     onTap: () { //    GestureDetector //    ,      print('You pressed me'); }, child: Container( //     decoration: BoxDecoration( //   shape: BoxShape.circle, //     color: Color(0xFF17A2B8), //      ), width: 80.0, height: 80.0, ), ), ); } } class Counter extends StatefulWidget { //      ,     , //   createState() @override State<Counter> createState() => _CounterState(); //        State, //   State<> } class _CounterState extends State<Counter> { //    -    , //      . //   ,     int counter = 0; //     ,       //   ,      Stateless . @override Widget build(BuildContext context) { //          , //     —  : return Center( child: GestureDetector( onTap: () { //  ,   ,    //  counter. setState(() { // setState()   ,    //      ,    ++counter; }); }, child: Container( decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF17A2B8), ), width: 80.0, child: Center( child: Text( //    counter '$counter', //      style: TextStyle(fontSize: 30.0), ), ), ), ), ); } } 

E aqui é exatamente o mesmo, mas usando o Kivy e o KivyMD:

 from kivy.lang import Builder from kivymd.app import MDApp KV = """ #:import get_color_from_hex kivy.utils.get_color_from_hex Screen: MDCard: MDLabel: value: 0 text: str(self.value) halign: "center" on_touch_down: self.value += 1 canvas.before: Color: rgba: get_color_from_hex("#4eaabe") Ellipse: pos: self.center[0] - dp(25), self.center[1] - dp(25) size: dp(50), dp(50) """ class HelloWorld(MDApp): def build(self): return Builder.load_string(KV) HelloWorld().run() 

Na minha opinião, a conclusão é óbvia e não precisa do meu comentário ...

Espero que tenha sido útil para você. Estou deixando uma enquete sobre o tópico "Você conseguiu criar um aplicativo para Android".

Source: https://habr.com/ru/post/pt479236/


All Articles