上次分享了使用buildozer打包apk的方法,虽然buildozer可以实现自动化打包apk,但过程漫长,且磁盘空间消耗比较大。因为buildozer打包apk实际上是使用python-for-android实现的,所以这次我和大家分享如何使用python-for-android打包apk。
注意,python-for-android打包apk同样需要在Linux系统中运行。
1 工作目录
当前目录:~/apk-ex
代码目录:~/apk-ex/src
虚拟环境:~/apk-ex/venv
依赖库:kivy[base]==2.2.1
2 安装软件
2.1 python-for-android
python -m pip install python-for-android==2023.9.16 -i https://mirrors.aliyun.com/pypi/simple
2.2 必要的依赖项
- ant
- autoconf (for libffi and other recipes)
- automake
- ccache (optional)
- cmake (required for some native code recipes like jpeg’s recipe)
- cython (can be installed via pip)
- gcc
- git
- libncurses (including 32 bit)
- libtool (for libffi and recipes)
- libssl-dev (for TLS/SSL support on hostpython3 and recipe)
- openjdk-17
- patch
- python3
- unzip
- virtualenv (can be installed via pip)
- zlib (including 32 bit)
- zip
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y build-essential ccache git zlib1g-dev python3 python3-dev libncurses5:i386 libstdc++6:i386 zlib1g:i386 openjdk-17-jdk unzip ant ccache autoconf libtool libssl-dev
2.3 Android SDK
2.3.1 安装命令行工具
wget https://dl.google.com/android/repository/commandlinetools-linux-9123335_latest.zip
mkdir android-sdk
unzip commandlinetools-linux-9123335_latest.zip -d android-sdk
mkdir android-sdk/cmdline-tools/latest
mv android-sdk/cmdline-tools/lib android-sdk/cmdline-tools/bin android-sdk/cmdline-tools/NOTICE.txt android-sdk/cmdline-tools/source.properties -t android-sdk/cmdline-tools/latest
export PATH=./android-sdk/cmdline-tools/latest/bin:$PATH
2.3.2 下载Android SDK和NDK
sdkmanager "build-tools;26.0.3"
sdkmanager "platforms;android-26"
sdkmanager "ndk;25.2.9519653"
sdkmanager "system-images;android-26;default;arm64-v8a"
sdkmanager "system-images;android-26;google_apis;arm64-v8a"
sdkmanager "ndk-bundle"
sdkmanager "sources;android-26"
sdkmanager "add-ons;addon-google_apis-google-24"
2.4 编辑~/.gitconfig
[url "https://hub.nuaa.cf/"]
insteadof = https://github.com/
[url "https://gitee.com/libsdl-org/jpeg.git"]
insteadof = https://github.com/libsdl-org/jpeg.git
[url "https://gitee.com/libsdl-org/libpng.git"]
insteadof = https://github.com/libsdl-org/libpng.git
[url "https://gitee.com/libsdl-org/libwebp.git"]
insteadof = https://github.com/libsdl-org/libwebp.git
[url "https://gitee.com/libsdl-org/libtiff.git"]
insteadof = https://github.com/libsdl-org/libtiff.git
[url "https://gitee.com/libsdl-org/zlib.git"]
insteadof = https://github.com/libsdl-org/zlib.git
[url "https://gitee.com/libsdl-org/libavif.git"]
insteadof = https://github.com/libsdl-org/libavif.git
[url "https://gitee.com/libsdl-org/dav1d.git"]
insteadof = https://github.com/libsdl-org/dav1d.git
[url "https://gitee.com/djmxmu/lodepng"]
insteadof = https://github.com/lvandeve/lodepng
[url "https://gitee.com/ffgpu/esaxx"]
insteadof = https://github.com/hillbig/esaxx
[url "https://gitee.com/ffgpu/libdivsufsort.git"]
insteadof = https://github.com/y-256/libdivsufsort.git
[url "https://gitee.com/djmxmu/Little-CMS"]
insteadof = https://github.com/mm2/Little-CMS
[url "https://gitee.com/sunny8654/google_googletest"]
insteadof = https://github.com/google/googletest
[url "https://gitee.com/rzkn/sjpeg.git"]
insteadof = https://github.com/webmproject/sjpeg.git
[url "https://gitee.com/djmxmu/libsdl-highway.git"]
insteadof = https://github.com/libsdl-org/highway.git
[url "https://gitee.com/Pretzel/libjxl.git"]
insteadof = https://github.com/libsdl-org/libjxl.git
2.5 autoreconf
sudo apt-get install dh-autoreconf
2.6 libltdl7-dev
sudo apt-get install libltdl7-dev
2.7 libffi-dev
sudo apt-get install libffi-dev
3 编写setup.py脚本
from setuptools import setup
from setuptools import find_packages
import os
os.environ['ANDROIDSDK'] = os.path.abspath('android-sdk')
os.environ['ANDROIDNDK'] = os.path.abspath('android-sdk/ndk/25.2.9519653')
os.environ['ANDROIDAPI'] = '26'
os.environ['NDKAPI'] = '21'
options = {'apk': {'requirements': 'python3==3.10.6, hostpython3==3.10.6, sdl2, kivy, android',
'debug': None,
'dist-name': 'apk-ex-setup',
'package': 'org.apk.example',
'bootstrap': 'sdl2',
'arch': 'arm64-v8a'}}
setup(
name='apk-ex',
version='0.0',
description='python-for-android setup',
author='C+ detective',
packages=find_packages(),
options=options,
package_data={'src': ['*.py']}
)
setup.py脚本保存到当前目录
4 运行setup.py脚本
python setup.py apk
4.1 安装第三方库失败
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_internal/operations/prepare.py", line 552, in prepare_linked_requirements_more
self._complete_partial_requirements(
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_internal/operations/prepare.py", line 467, in _complete_partial_requirements
for link, (filepath, _) in batch_download:
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_internal/network/download.py", line 183, in __call__
for chunk in chunks:
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_internal/cli/progress_bars.py", line 53, in _rich_progress_bar
for chunk in iterable:
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_internal/network/utils.py", line 63, in response_chunks
for chunk in response.raw.stream(
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_vendor/urllib3/response.py", line 622, in stream
data = self.read(amt=amt, decode_content=decode_content)
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_vendor/urllib3/response.py", line 560, in read
with self._error_catcher():
File "/home/finance/.local/share/python-for-android/build/other_builds/hostpython3/desktop/hostpython3/Lib/contextlib.py", line 153, in __exit__
self.gen.throw(typ, value, traceback)
File "/home/finance/.local/share/python-for-android/build/venv/lib/python3.10/site-packages/pip/_vendor/urllib3/response.py", line 443, in _error_catcher
raise ReadTimeoutError(self._pool, None, "Read timed out.")
pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.
STDERR:
运行脚本的过程中会创建虚拟环境'~/.local/share/python-for-android/build/venv',并在其中安装一些第三方库。 和buildozer一样,安装过程往往会因为远程链接超时而终止脚本,这时候我们可以多运行几次脚本直到安装成功为止;如果想快一点安装,自己直接往这个虚拟环境安装相应的第三方库,然后再运行脚本。
4.2 下载gradle失败
[WARNING]: ERROR: /home/finance/.local/share/python-for-android/dists/apk-ex-setup/gradlew failed!
[WARNING]: ERROR: /home/finance/.local/share/python-for-android/dists/apk-ex-setup/gradlew failed!
失败乃成功之母,多运行几次脚本总会成功的,加油!!!
5. 打包成功
[DEBUG]: Dist matching name and arch: [<Distribution: name apk-ex-setup with recipes (hostpython3, libffi, openssl, sdl2_image, sdl2_mixer, sdl2_ttf, sqlite3, python3, sdl2, setuptools, six, pyjnius, android, kivy, certifi, chardet, requests, urllib3, idna)>]
[DEBUG]: Dist matching ndk_api and recipe: [<Distribution: name apk-ex-setup with recipes (hostpython3, libffi, openssl, sdl2_image, sdl2_mixer, sdl2_ttf, sqlite3, python3, sdl2, setuptools, six, pyjnius, android, kivy, certifi, chardet, requests, urllib3, idna)>]
[DEBUG]: Dist matching ndk_api and recipe: [<Distribution: name apk-ex-setup with recipes (hostpython3, libffi, openssl, sdl2_image, sdl2_mixer, sdl2_ttf, sqlite3, python3, sdl2, setuptools, six, pyjnius, android, kivy, certifi, chardet, requests, urllib3, idna)>]
[INFO]: Of the existing distributions, the following meet the given requirements:
[INFO]: Of the existing distributions, the following meet the given requirements:
[INFO]: apk-ex-setup: min API 21, includes recipes (hostpython3, libffi, openssl, sdl2_image, sdl2_mixer, sdl2_ttf, sqlite3, python3, sdl2, setuptools, six, pyjnius, android, kivy, certifi, chardet, requests, urllib3, idna), built for archs (arm64-v8a)
[INFO]: apk-ex-setup: min API 21, includes recipes (hostpython3, libffi, openssl, sdl2_image, sdl2_mixer, sdl2_ttf, sqlite3, python3, sdl2, setuptools, six, pyjnius, android, kivy, certifi, chardet, requests, urllib3, idna), built for archs (arm64-v8a)
[INFO]: apk-ex-setup has compatible recipes, using this one
[INFO]: apk-ex-setup has compatible recipes, using this one
[INFO]: # Copying android package to current directory
[INFO]: # Copying android package to current directory
[INFO]: # Android package filename not found in build output. Guessing...
[INFO]: # Android package filename not found in build output. Guessing...
[INFO]: # Found android package file: /home/finance/.local/share/python-for-android/dists/apk-ex-setup/build/outputs/apk/debug/apk-ex-setup-debug.apk
[INFO]: # Found android package file: /home/finance/.local/share/python-for-android/dists/apk-ex-setup/build/outputs/apk/debug/apk-ex-setup-debug.apk
[INFO]: # Add version number to android package
[INFO]: # Add version number to android package
[INFO]: # Android package renamed to apk-ex-setup-debug-0.0.apk
[INFO]: # Android package renamed to apk-ex-setup-debug-0.0.apk
[DEBUG]: -> running cp /home/finance/.local/share/python-for-android/dists/apk-ex-setup/build/outputs/apk/debug/apk-ex-setup-debug.apk apk-ex-setup-debug-0.0.apk
[DEBUG]: -> running cp /home/finance/.local/share/python-for-android/dists/apk-ex-setup/build/outputs/apk/debug/apk-ex-setup-debug.apk apk-ex-setup-debug-0.0.apk
<Command '/usr/bin/cp /home/finance/.local/share/python-for-android/dists/apk-ex-setup/build/outputs/apk/debug/apk-ex-setup-debug.apk apk-ex-setup-debug-0.0.apk', pid 124420>: process started
最后,打包成功就会把打包好的apk复制到当前目录。