使用python中kivy庫生成安卓APP

Python探索牛發表於2024-05-09

kivy的安裝

官方推薦的方式是使用虛擬環境來進行安裝和部署,關於虛擬環境的相關操作,在前面寫過的一篇部落格中有稍微詳細一點的介紹,這裡我們先給出操作步驟。假定我們已經在環境中用pip安裝了virtualenv,那麼我們先構建一個kivy的虛擬環境:

[dechin@dechin-manjaro kivy]$ virtualenv kivy_venv
created virtual environment CPython3.8.5.final.0-64 in 123ms
  creator CPython3Posix(dest=/home/dechin/projects/2021-python/kivy/kivy_venv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/home/dechin/.local/share/virtualenv)
    added seed packages: pip==21.0.1, setuptools==54.1.2, wheel==0.36.2

  activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

構建完成後會在當前目錄下生成一個資料夾:

[dechin@dechin-manjaro kivy]$ ll
總用量 4

drwxr-xr-x 4 dechin dechin 4096  4月  3 22:00 kivy_venv

我們可以用source ./kivy_env/bin/activate的方式對虛擬環境進行啟用,啟用後每次執行系統操作指令,會在指令的最前端顯示一個虛擬環境的標識,比如這裡我們在虛擬環境中用pip來安裝kivy:

(kivy_venv)[dechin@dechin-manjaro kivy]$ python3 -m pip install kivy -i https://mirrors.cloud.tencent.com/pypi/simple 
Looking in indexes: https://mirrors.cloud.tencent.com/pypi/simple
Collecting kivy
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/fd/4c/eb36890982bb11daaea68df62486ce36bde26cc9bec6a57e02c0e2aa8982/Kivy-2.0.0-cp38-cp38-manylinux2010_x86_64.whl (22.2 MB)
     |████████████████████████████████| 22.2 MB 7.7 MB/s 
Collecting pygments
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/3a/80/a52c0a7c5939737c6dca75a831e89658ecb6f590fb7752ac777d221937b9/Pygments-2.8.1-py3-none-any.whl (983 kB)
     |████████████████████████████████| 983 kB 688 kB/s 
Collecting Kivy-Garden>=0.1.4
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/7d/68/decaee596ff8168a39432eb3949fc7c0be952ebb9467806823bffc165d48/kivy-garden-0.1.4.tar.gz (6.8 kB)
Collecting docutils
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/9a/65/76aea825b59727b556cca74e28d68e4d73244d2e1e8a8945c29d6d3d5e11/docutils-0.17-py2.py3-none-any.whl (575 kB)
     |████████████████████████████████| 575 kB 912 kB/s 
Collecting requests
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/29/c1/24814557f1d22c56d50280771a17307e6bf87b70727d975fd6b2ce6b014a/requests-2.25.1-py2.py3-none-any.whl (61 kB)
     |████████████████████████████████| 61 kB 1.0 MB/s 
Collecting certifi>=2017.4.17
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/5e/a0/5f06e1e1d463903cf0c0eebeb751791119ed7a4b3737fdc9a77f1cdfb51f/certifi-2020.12.5-py2.py3-none-any.whl (147 kB)
     |████████████████████████████████| 147 kB 726 kB/s 
Collecting idna<3,>=2.5
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/a2/38/928ddce2273eaa564f6f50de919327bf3a00f091b5baba8dfa9460f3a8a8/idna-2.10-py2.py3-none-any.whl (58 kB)
     |████████████████████████████████| 58 kB 644 kB/s 
Collecting urllib3<1.27,>=1.21.1
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/09/c6/d3e3abe5b4f4f16cf0dfc9240ab7ce10c2baa0e268989a4e3ec19e90c84e/urllib3-1.26.4-py2.py3-none-any.whl (153 kB)
     |████████████████████████████████| 153 kB 564 kB/s 
Collecting chardet<5,>=3.0.2
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/19/c7/fa589626997dd07bd87d9269342ccb74b1720384a4d739a1872bd84fbe68/chardet-4.0.0-py2.py3-none-any.whl (178 kB)
     |████████████████████████████████| 178 kB 827 kB/s 
Building wheels for collected packages: Kivy-Garden
  Building wheel for Kivy-Garden (setup.py) ... done
  Created wheel for Kivy-Garden: filename=Kivy_Garden-0.1.4-py3-none-any.whl size=4532 sha256=70dd6bf0a005868e9aca0710f7b717432bda7925c0fac236b99d2527ec112b78
  Stored in directory: /home/dechin/.cache/pip/wheels/c9/d0/d4/2cb72931b74be8ce5fbee5ed87d66366f356a3161ea772d015
Successfully built Kivy-Garden
Installing collected packages: urllib3, idna, chardet, certifi, requests, pygments, Kivy-Garden, docutils, kivy

Successfully installed Kivy-Garden-0.1.4 certifi-2020.12.5 chardet-4.0.0 docutils-0.17 idna-2.10 kivy-2.0.0 pygments-2.8.1 requests-2.25.1 urllib3-1.26.4

為了加快安裝,我們使用了騰訊的pip源。安裝完成後,可以在已安裝列表中看到剛才安裝的kivy及其依賴元件:

(kivy_venv)[dechin@dechin-manjaro kivy]$ python3 -m pip list
Package     Version
----------- ---------
certifi     2020.12.5
chardet     4.0.0
docutils    0.17
idna        2.10
Kivy        2.0.0
Kivy-Garden 0.1.4
pip         21.0.1
Pygments    2.8.1
requests    2.25.1
setuptools  54.1.2
urllib3     1.26.4
wheel       0.36.2

kivy的hello world

配置好kivy的環境後,我們可以直接在電腦端測試python所編寫的app例項,比如kivy的hello world:

# kivy_hello_world.py
 
import kivy
kivy.require('2.0.0') # 注意匹配版本號
 
from kivy.app import App
from kivy.uix.label import Label
 
class MyApp(App):
    def build(self):
        return Label(text='Hello world')
 
if __name__ == '__main__':

    MyApp().run()

可以直接用python3 kivy_hello_world.py的指令來執行,執行結果如下圖所示:
在這裡插入圖片描述
執行期間我們可以在螢幕上看到一系列的日誌輸出,在有報錯問題的時候,查詢執行日誌是必須使用的定位手段:

[INFO   ] [Logger      ] Record log in /home/dechin/.kivy/logs/kivy_21-04-03_1.txt
[INFO   ] [Kivy        ] v2.0.0
[INFO   ] [Kivy        ] Installed at "/home/dechin/projects/2021-python/kivy/kivy_venv/lib/python3.8/site-packages/kivy/__init__.py"
[INFO   ] [Python      ] v3.8.5 (default, Sep  4 2020, 07:30:14) 
[GCC 7.3.0]
[INFO   ] [Python      ] Interpreter at "/home/dechin/projects/2021-python/kivy/kivy_venv/bin/python3"
[INFO   ] [Factory     ] 186 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2 (img_pil, img_ffpyplayer ignored)
[INFO   ] [Text        ] Provider: sdl2
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] Backend used <sdl2>
[INFO   ] [GL          ] OpenGL version <b'4.6 (Compatibility Profile) Mesa 20.3.1'>
[INFO   ] [GL          ] OpenGL vendor <b'Intel'>
[INFO   ] [GL          ] OpenGL renderer <b'Mesa Intel(R) UHD Graphics 620 (WHL GT2)'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 6
[INFO   ] [GL          ] Shading version <b'4.60'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [ProbeSysfs  ] device match: /dev/input/event16
[INFO   ] [MTD         ] Read event from </dev/input/event16>
[INFO   ] [Base        ] Start application main loop
[INFO   ] [GL          ] NPOT texture support is available
[WARNING] [MTD         ] Unable to open device "/dev/input/event16". Please ensure you have the appropriate permissions.
[INFO   ] [Base        ] Leaving application in progress...

到這裡,我們的第一步工作就基本完成了,但是需要注意的是,這裡我們的程式還是執行在電腦端的,我們需要將其打包成apk檔案之後,才能在手機端執行。

選擇使用虛擬環境的原因

這裡我們單獨一個小章節,說明一下為什麼官方推薦的使用方法很多都是使用虛擬環境,這個其實跟後面要介紹的apk打包有較大關係。我們在打包apk的過程中,如果有相關的python依賴包,都需要在配置檔案中提前標識。這一點非常重要,最好是能夠指定具體的版本號進行安裝,否則會出現打包失敗的問題,如果到了打包的階段再去定位和解決此類問題,會非常的麻煩。

apk構建環境配置

我們在本地採用了buildozer的方案來進行apk的構建,如果在本地其他環境依賴如jdk等都已經部署完畢,在虛擬環境裡面直接安裝buildozer是沒有問題的。但是由於本地環境中依賴都比較缺乏,因此為了避免環境切換混亂,這裡我們使用虛擬環境來展示安裝和使用的基本方法,但是實際應用場景下,我們還是直接使用了本地的python3環境,而不是虛擬環境。

安裝buildozer

跟其他python庫一樣的,我們可以透過pip來對buildozer進行安裝和管理:

(kivy_venv)[dechin@dechin-manjaro kivy]$ python3 -m pip install buildozer -i https://mirrors.cloud.tencent.com/pypi/simple
Looking in indexes: https://mirrors.cloud.tencent.com/pypi/simple
Collecting buildozer
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/ac/62/a53738c604ebc86d3b62f654c3169e8c0b4178a066d7398cf53377a5cb3b/buildozer-1.2.0-py3-none-any.whl (77 kB)
     |████████████████████████████████| 77 kB 783 kB/s 
Collecting sh
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/50/38/f7dcc62943d0870f02df9e2fa527b7f0cd86b233a80d6e503a08f3ef5ddc/sh-1.14.1-py2.py3-none-any.whl (40 kB)
     |████████████████████████████████| 40 kB 1.7 MB/s 
Collecting pexpect
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/39/7b/88dbb785881c28a102619d46423cb853b46dbccc70d3ac362d99773a78ce/pexpect-4.8.0-py2.py3-none-any.whl (59 kB)
     |████████████████████████████████| 59 kB 1.0 MB/s 
Collecting virtualenv
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/91/fb/ca6c071f4231e06a9f0c3bd81c15c233bbacd4a7d9dbb7438d95fece8a1e/virtualenv-20.4.3-py2.py3-none-any.whl (7.2 MB)
     |████████████████████████████████| 7.2 MB 2.2 MB/s 
Collecting ptyprocess>=0.5
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl (13 kB)
Collecting distlib<1,>=0.3.1
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/f5/0a/490fa011d699bb5a5f3a0cf57de82237f52a6db9d40f33c53b2736c9a1f9/distlib-0.3.1-py2.py3-none-any.whl (335 kB)
     |████████████████████████████████| 335 kB 721 kB/s 
Collecting six<2,>=1.9.0
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/ee/ff/48bde5c0f013094d729fe4b0316ba2a24774b3ff1c52d924a8a4cb04078a/six-1.15.0-py2.py3-none-any.whl (10 kB)
Collecting appdirs<2,>=1.4.3
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB)
Collecting filelock<4,>=3.0.0
  Downloading https://mirrors.cloud.tencent.com/pypi/packages/93/83/71a2ee6158bb9f39a90c0dea1637f81d5eef866e188e1971a1b1ab01a35a/filelock-3.0.12-py3-none-any.whl (7.6 kB)
Installing collected packages: six, ptyprocess, filelock, distlib, appdirs, virtualenv, sh, pexpect, buildozer

Successfully installed appdirs-1.4.4 buildozer-1.2.0 distlib-0.3.1 filelock-3.0.12 pexpect-4.8.0 ptyprocess-0.7.0 sh-1.14.1 six-1.15.0 virtualenv-20.4.3

安裝完成後,應該要在本地可以看到buildozer的安裝位置:

(kivy_venv)[dechin@dechin-manjaro kivy]$ which buildozer
/home/dechin/projects/2021-python/kivy/kivy_venv/bin/buildozer

buildozer的基本使用

從框架上來說,buildozer的使用方法其實只有兩個步驟:先用init生成配置檔案,然後使用buildozer debug就可以構造一個apk檔案了,如果順利的話:)

(kivy_venv) [dechin@dechin-manjaro kivy]$ buildozer init

File buildozer.spec created, ready to customize!

按照流程第一步初始化完成後,當前的目錄下會生成一個buildozer.spec的配置檔案,與其他軟體所不一樣的是,這個配置檔案又臭又長,修改起來非常的不便,對新手極其不友好。但是,運氣好的情況下也不需要去修改這個配置檔案就可以成功構建apk。

(kivy_venv) [dechin@dechin-manjaro kivy]$ ll
總用量 24
-rw-r--r-- 1 dechin dechin 10489  4月  3 22:17 buildozer.spec
-rw-r--r-- 1 dechin dechin   243  4月  3 22:06 kivy_hello_world.py

drwxr-xr-x 4 dechin dechin  4096  4月  3 22:00 kivy_venv

當你執行下面的指令,正常情況下麻煩才剛剛開始:

(kivy_venv) [dechin@dechin-manjaro kivy]$ buildozer android debug deploy run
# Check configuration tokens
# Ensure build layout
# Create directory /home/dechin/.buildozer
# Create directory /home/dechin/.buildozer/cache
# Create directory /home/dechin/projects/2021-python/kivy/.buildozer
# Create directory /home/dechin/projects/2021-python/kivy/bin
# Create directory /home/dechin/projects/2021-python/kivy/.buildozer/applibs
# Create directory /home/dechin/.buildozer/android/platform/android/platform
# Create directory /home/dechin/projects/2021-python/kivy/.buildozer/android/platform
# Create directory /home/dechin/projects/2021-python/kivy/.buildozer/android/app
# Check configuration tokens
# Read available permissions from api-versions.xml
# Preparing build
# Check requirements for android
# Run 'dpkg --version'
# Cwd None
/bin/sh:行1: dpkg:未找到命令
# Search for Git (git)
#  -> found at /usr/bin/git
# Search for Cython (cython)
#  -> found at /home/dechin/anaconda3/bin/cython
# Search for Java compiler (javac)

# Java compiler (javac) not found, please install it.

沒有dpkg,沒有jdk,在參考連結5裡面還有人專門整理了各種可能猜到的坑,對這些環境有依賴,為何不能在文件中提前說明呢?這裡還有一點需要注意的是,雖然buildozer官方提供了docker的解決方案,但是我們極其不推薦使用官方提供的docker解決方案,因為官方的docker方案只解決buildozer的問題,不解決其他的環境依賴問題。

構建問題處理

以下整理了一些在使用過程中所遇到的問題,正是為了解決這些問題,所以我們後來放棄了在虛擬環境中繼續測試的方法,改用本地環境直接來執行。這裡有個區別需要注意,buildozer每次初始化會在特定帳號和環境的目錄下產生一個.buildozer的目錄,而普通帳號和root帳號的~/目錄是不一樣的,這點首先要明確。而如果使用虛擬環境,在虛擬環境下也可以產生一個獨立的.buildozer目錄。

dpkg的依賴安裝

我們使用了基於Arch的Manjaro Linux系統,大部分的軟體透過pacman、yay和yaourt都是可以直接下載到的,當然,最好是配置好AUR的源,這裡dpkg我們直接使用pacman來安裝:

[dechin-root kivy]# pacman -S dpkg
正在解析依賴關係...
正在查詢軟體包衝突...
 
軟體包 (1) dpkg-1.20.5-2
 
下載大小:  1.75 MiB
全部安裝大小:  8.26 MiB
 
:: 進行安裝嗎? [Y/n] Y
:: 正在獲取軟體包......
 dpkg-1.20.5-2-x86_64      1795.8 KiB   524 KiB/s 00:03 [#############################] 100%
(1/1) 正在檢查金鑰環裡的金鑰                            [#############################] 100%
(1/1) 正在檢查軟體包完整性                              [#############################] 100%
(1/1) 正在載入軟體包檔案                                [#############################] 100%
(1/1) 正在檢查檔案衝突                                  [#############################] 100%
(1/1) 正在檢查可用儲存空間                              [#############################] 100%
:: 正在處理軟體包的變化...
(1/1) 正在安裝 dpkg                                     [#############################] 100%
    dpkg installs Debian package manager.
    This is useful for those who want to create/modify DEB files.
    However, *do not* use dpkg to install Debian packages in your ArchLinux machine.
    This will break your system!
    You will need to go back to Arch wiki and read the installation guide again.
    You've been warned!
:: 正在執行事務後鉤子函式...
(1/1) Arming ConditionNeedsUpdate...

中間如果沒有報錯即為安裝成功。

基於docker的buildozer方案

雖然並不是很推薦這個容器化方案,因為這個容器所能夠解決的問題實在太少,但是這裡我們還是展示一下buildozer官方容器的配置和使用方法。首先是下載官方映象:

[dechin-root kivy]# docker pull kivy/buildozer
Using default tag: latest
latest: Pulling from kivy/buildozer
5d3b2c2d21bb: Pull complete 
3fc2062ea667: Pull complete 
75adf526d75b: Pull complete 
1e25f7347ef2: Pull complete 
5f20dec9b37e: Pull complete 
50f409884337: Pull complete 
eee420e57cec: Pull complete 
cf2da2cede0f: Pull complete 
6581da051d43: Pull complete 
e9f936019286: Pull complete 
517947681358: Pull complete 
Digest: sha256:b2923081b45829555cd27356fbc0ab364474c64d9879fa730eccd4ce63e22cc4
Status: Downloaded newer image for kivy/buildozer:latest

docker.io/kivy/buildozer:latest

下載完成後,繫結當前目錄執行容器映象:

[dechin-root first_app]# docker run --volume "$(pwd)":/home/user/hostcwd kivy/buildozer

Buildozer 1.2.0.dev0

可以直接檢視幫助:

[dechin-root first_app]# docker run -it --volume "$(pwd)":/home/user/hostcwd kivy/buildozer --help
Usage:
    buildozer [--profile <name>] [--verbose] [target] <command>...
    buildozer --version
 
Available targets:
  ios                iOS target, based on kivy-ios project
  android            Android target, based on python-for-android project
 
Global commands (without target):
  appclean           Clean the .buildozer folder in the app directory.
  distclean          Clean the whole Buildozer environment.
  help               Show the Buildozer help.
  init               Create a initial buildozer.spec in the current directory
  serve              Serve the bin directory via SimpleHTTPServer
  setdefault         Set the default command to run when no arguments are given
  version            Show the Buildozer version
 
Target commands:
  clean      Clean the target environment
  update     Update the target dependencies
  debug      Build the application in debug mode
  release    Build the application in release mode
  deploy     Deploy the application on the device
  run        Run the application on the device
  serve      Serve the bin directory via SimpleHTTPServer
 
Target "ios" commands:
  list_identities    List the available identities to use for signing.
  xcode              Open the xcode project.
 
Target "android" commands:
  adb                Run adb from the Android SDK. Args must come after --, or
                     use --alias to make an alias
  clean              Clean the build and distribution
  logcat             Show the log from the device
  p4a                Run p4a commands. Args must come after --, or use --alias

                     to make an alias

第一次初始化,出現了許可權不足的問題,一開始以為是容器內部讀寫許可權配置的問題,因此這裡先給容器加上了privileged許可權,但是執行後發現這個問題依然存在:

[dechin-root first_app]# docker run -it --volume "$(pwd)":/home/user/hostcwd --privileged=True kivy/buildozer init
Traceback (most recent call last):
  File "/home/user/.local/bin/buildozer", line 8, in <module>
    sys.exit(main())
  File "/home/user/.local/lib/python3.8/site-packages/buildozer/scripts/client.py", line 13, in main
    Buildozer().run_command(sys.argv[1:])
  File "/home/user/.local/lib/python3.8/site-packages/buildozer/__init__.py", line 1010, in run_command
    getattr(self, cmd)(*args)
  File "/home/user/.local/lib/python3.8/site-packages/buildozer/__init__.py", line 1049, in cmd_init
    copyfile(join(dirname(__file__), 'default.spec'), 'buildozer.spec')
  File "/usr/lib/python3.8/shutil.py", line 261, in copyfile
    with open(src, 'rb') as fsrc, open(dst, 'wb') as fdst:

PermissionError: [Errno 13] Permission denied: 'buildozer.spec'

那就有可能是本地配置檔案和目錄許可權的問題,因為目錄是在普通帳號下產生的,一般是644的許可權,那麼就算是root許可權的寫入可能也會首先,乾脆直接遞迴的改成777:

[dechin-root kivy]# chmod -R 777 first_app/

再次執行,發現在本地一樣也可以生成配置檔案:

[dechin-root first_app]# docker run -it --volume "$(pwd)":/home/user/hostcwd --privileged=True kivy/buildozer init && ll
File buildozer.spec created, ready to customize!
總用量 24
-rw-r--r-- 1 dechin dechin 12305  4月  4 10:59 buildozer.spec
-rwxrwxrwx 1 root   root     243  4月  4 10:42 main.py

drwxrwxrwx 3 root   root    4096  4月  4 10:43 user

但是這個容器映象跟常規的有所不同,整個的容器映象就只能執行buildozer的指令,這尤其對國內使用者非常的不友好,因為我們缺乏的就是buildozer那一堆依賴環境,在國內網路上會受到一定的限制。比如我們下述展示的執行結果,就卡在這個地方很久:

[dechin-root first_app]# docker run -it --volume "$(pwd)":/home/user/hostcwd --privileged=True kivy/buildozer android debug deploy run
# Check configuration tokens
# Ensure build layout
# Create directory /home/user/.buildozer
# Create directory /home/user/.buildozer/cache
# Create directory /home/user/hostcwd/.buildozer
# Create directory /home/user/hostcwd/bin
# Create directory /home/user/hostcwd/.buildozer/applibs
# Create directory /home/user/.buildozer/android/platform/android/platform
# Create directory /home/user/hostcwd/.buildozer/android/platform
# Create directory /home/user/hostcwd/.buildozer/android/app
# Check configuration tokens
# Read available permissions from api-versions.xml
# Preparing build
# Check requirements for android
# Run 'dpkg --version'
# Cwd None
Debian 'dpkg' package management program version 1.19.7 (amd64).
This is free software; see the GNU General Public License version 2 or
later for copying conditions. There is NO warranty.
# Search for Git (git)
#  -> found at /usr/bin/git
# Search for Cython (cython)
#  -> found at /home/user/.local/bin/cython
# Search for Java compiler (javac)
#  -> found at /usr/lib/jvm/java-13-openjdk-amd64/bin/javac
# Search for Java keytool (keytool)
#  -> found at /usr/lib/jvm/java-13-openjdk-amd64/bin/keytool
# Install platform
# Run 'git clone -b master --single-branch https://github.com/kivy/python-for-android.git python-for-android'
# Cwd /home/user/hostcwd/.buildozer/android/platform

Cloning into 'python-for-android'...

網路卡了很長一段時間後會彈出眾多的報錯:

Cloning into 'python-for-android'...
fatal: unable to access 'https://github.com/kivy/python-for-android.git/': GnuTLS recv error (-54): Error in the pull function.
# Command failed: git clone -b master --single-branch https://github.com/kivy/python-for-android.git python-for-android
# ENVIRONMENT:
#     PATH = '/home/user/.buildozer/android/platform/apache-ant-1.9.4/bin:/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
#     HOSTNAME = '69325b48f53a'
#     TERM = 'xterm'
#     USER = 'user'
#     HOME_DIR = '/home/user'
#     WORK_DIR = '/home/user/hostcwd'
#     SRC_DIR = '/home/user/src'
#     LANG = 'en_US.UTF-8'
#     LANGUAGE = 'en_US.UTF-8'
#     LC_ALL = 'en_US.UTF-8'
#     HOME = '/home/user'
# 
# Buildozer failed to execute the last command
# The error might be hidden in the log above this error
# Please read the full log, and search for it before
# raising an issue with buildozer itself.

# In case of a bug report, please add a full log with log_level = 2

實際上這就是網路的問題,如果你能上谷歌,那麼你就同時解決了這個問題。如果網路不行的話,即使在官方商店裡面可以看到也是下載安裝不了的:

在這裡插入圖片描述

adb日誌定位apk問題

假定你已經解決了上述提到了訪問谷歌網站的問題,那麼環境依賴的問題基本上就已經解決了,只需要注意jdk跟gradle的版本配套關係即可,這裡我們本地使用的是jdk-8,同樣的也可以使用yaourt來進行安裝。最後就還有可能出現,部署到安卓裝置上面之後,app閃退的問題。首先我們如果執行buildozer androiid debug deploy run,並且同時保障安卓手機USB接入以及USB除錯開關的開啟,順利情況下會出現以下資訊:

List of devices attached
xxx        device
 
# Deploy on xxx
# Run '/home/dechin/.buildozer/android/platform/android-sdk/platform-tools/adb install -r "/home/dechin/projects/2021-python/kivy/first_app/bin/myapp-0.1-armeabi-v7a-debug.apk"'
# Cwd /home/dechin/.buildozer/android/platform
Performing Streamed Install
Success
# Application pushed.
# Run on xxx
# Run '/home/dechin/.buildozer/android/platform/android-sdk/platform-tools/adb shell am start -n org.test.myapp/org.kivy.android.PythonActivity -a org.kivy.android.PythonActivity'
# Cwd /home/dechin/.buildozer/android/platform
Starting: Intent { act=org.kivy.android.PythonActivity cmp=org.test.myapp/org.kivy.android.PythonActivity }

# Application started.

但這並不是終點,我們發現在手機上用apk安裝的app會出現閃退,這一般都是由於程式報錯而導致的,我們可以在連線USB除錯的狀態下,進入adb shell檢視日誌:

[dechin@dechin-manjaro first_app]$ adb shell
HWPCT:/ $ run-as org.test.myapp
HWPCT:/data/data/org.test.myapp 
$ cd files/app/.kivy/logs/                                  
HWPCT:/data/data/org.test.myapp/files/app/.kivy/logs 
$ ls
kivy_21-04-06_0.txt
$ cat kivy_21-04-06_0.txt                                                                     <
[INFO   ] Logger: Record log in /data/user/0/org.test.myapp/files/app/.kivy/logs/kivy_21-04-06_0.txt
[WARNING] [Config      ] Upgrading configuration in progress.
[WARNING] [Config      ] Older configuration version detected (0 instead of 21)
[INFO   ] Kivy: v1.11.1
[INFO   ] Kivy: Installed at "/data/user/0/org.test.myapp/files/app/_python_bundle/site-packages/kivy/__init__.pyc"
[INFO   ] Python: v3.8.1 (default, Apr  6 2021, 10:41:43) 
[Clang 8.0.2 (https://android.googlesource.com/toolchain/clang 40173bab62ec7462
[INFO   ] Python: Interpreter at ""
[WARNING] stderr: Traceback (most recent call last):
[WARNING] stderr:   File "/home/dechin/projects/2021-python/kivy/first_app/.buildozer/android/app/main.py", line 4, in <module>
[WARNING] stderr:   File "/home/dechin/projects/2021-python/kivy/first_app/.buildozer/android/platform/build-armeabi-v7a/build/python-installs/myapp/kivy/__init__.py", line 138, in require
[WARNING] stderr: Exception: The version of Kivy installed on this system is too old. (You have 1.11.1, but the application requires 2.0.0)

HWPCT:/data/data/org.test.myapp/files/app/.kivy/log

從日誌中我們看到,這是因為對應的kivy程式版本過低導致的,這需要我們修改buildozer.spec配置檔案。我們找到requirements這裡,發現這裡的兩個倉庫都沒有指定版本號,這裡我們採取的方案是加上版本號的要求,然後清除.buildozer目錄,重新進行環境安裝。

requirements = python3,kivy

修改後如下:

requirements = python3,kivy==2.0.0

然後在重新執行buildozer debug deploy run,得到手機介面上的效果如下(如果只執行debug或者release,那就不需要連線手機USB除錯,這裡的操作相當於直接把apk傳輸到手機上進行安裝和執行):

在這裡插入圖片描述

總結

基於python也可以開發安卓APP,這需要使用到kivy庫來進行開發,再透過buildozer來編譯構建。這兩個庫的安裝和使用方式都相對比較簡單,我們推薦直接在本地的系統環境下直接部署使用,最大的困難其實在於部署的過程以及配置檔案的修改,這也都是比較基礎的操作了。最後我們演示了使用文字框和按鈕事件,加上python的eval()函式和math數學倉庫,實現了一個可以在移動端呼叫math庫中的函式執行數學計算的簡單APP,並提供了apk下載網盤地址。

相關文章