前些天,我打算将基于 PyWebView 开发的桌面应用适配到移动端,查阅官网时惊喜地发现:PyWebView 天然支持移动端!这意味着只要桌面端的界面做好了屏幕自适应,大部分代码可以直接复用到移动端,堪称完美。

于是,我最近就开始了适配工作。与桌面端不同,PyWebView 移动端的打包依赖于 Buildozer 而非 PyInstaller,因此你需要提前熟悉 Buildozer 的使用。可以通过其官方文档学习,也可以参考我之前写过的 buildozer打包详解:细说那些我踩过的坑。
正如前文提到,即使使用 Buildozer 成功打包出 APK,仍可能因兼容性或代码问题导致应用闪退。这时,可以将生成的 Java 代码导入 Android Studio 进一步调试。代码路径通常位于:
\\wsl.localhost\Ubuntu-22.04\{项目目录}\.buildozer\android\platform\build-arm64-v8a\dists\{项目java代码目录}

接下来,我将重点分享在适配过程中踩到的几个"坑"及其解决方法。
1. Gradle 版本问题
这个问题通常出现在 Android Studio 打开项目时,一般会有明显的版本错误提示。解决方法很简单:按照提示修改 gradle-wrapper.properties 中的版本号,然后点击 File → Sync Project with Gradle Files(或工具栏的同步图标 🔄)。

如果启动时出现类似下面的错误,同样执行一次同步即可:
sql
Error running 'xxx'
getGradleProjectPath(Module: 'xxx')== null
2. nativeSetenv 未实现导致闪退
报错信息类似:
dart
2025-12-29 17:10:23.913 5520-5520 .todos.todolist com.pywebview.todos.todolist E No implementation found for void org.libsdl.app.SDLActivity.nativeSetenv(java.lang.String, java.lang.String) (tried Java_org_libsdl_app_SDLActivity_nativeSetenv and Java_org_libsdl_app_SDLActivity_nativeSetenv__Ljava_lang_String_2Ljava_lang_String_2) - is the library loaded, e.g. System.loadLibrary?
根据官方说明,该问题通常是因为 Buildozer 配置的架构(如 arm)与模拟器架构(如 x86)不匹配。解决方案是在 buildozer.spec 中添加 x86 支持:
ini
android.archs = arm64-v8a, armeabi-v7a, x86, x86_64
💡温馨提示:实际上只添加 x86 即可,但添加其他架构也没有影响,只是会略微增加应用体积。
3. ERR_CLEARTEXT_NOT_PERMITTED 权限问题
该错误通常出现在 Android 9.0(API 28)及以上版本 ,表示应用尝试使用 非加密的 HTTP 明文通信 ,而系统默认禁止此类行为。换句话说,你调用的是 HTTP 而不是 HTTPS。
按照 PyWebView 官网建议,可以在启动脚本中启用 SSL:
python
webview.start(ssl=True) # 开启 SSL 支持
4. 静态资源 404 问题
如果打包时未正确包含前端资源文件,应用启动后将无法加载 HTML、CSS 或 JS 文件。需要在 buildozer.spec 中配置资源包含规则:
ini
source.dir = .
source.include_exts = py,png,jpg,kv,atlas,html,jar,css,js
source.include_patterns = frontend/*,backend/*,lib/*,data/*
💡温馨提示:建议将启动的 Python 文件放在项目根目录,并命名为 main.py。
如果配置后依然找不到资源,可以检查 Buildozer 构建目录中的 app 文件夹,确认资源是否已被正确打包:
\\wsl.localhost\Ubuntu-22.04\{项目目录}\.buildozer\android\app

5. JS 报错:TypeError: Cannot read properties of null (reading 'getItem')
这个问题通常是因为移动端环境中 localStorage 不可用。建议实现一个自定义的存储方案,在系统 localStorage 不可用时自动降级使用。具体实现可咨询 AI 或参考相关前端兼容性方案。

📦 补充:buildozer.spec 关键配置说明
ini
[app]
# 应用名称
title = todoList
# 包名
package.name = todoList
# 包域名(反向域名风格)
package.domain = com.pywebview.todos
# 源码目录
source.dir = .
# 包含的文件类型
source.include_exts = py,png,jpg,kv,atlas,html,jar,css,js
# 包含的目录(支持通配符)
source.include_patterns = frontend/*,backend/*,lib/*,data/*
# 排除的文件类型
source.exclude_exts = spec
# 排除的目录
source.exclude_dirs = bin,build,dist,docs,logo,tests,pywebview.egg-info
# 排除的通配路径
source.exclude_patterns = venv*/*/*
# 应用版本
version = 0.1
# 依赖的 Python 包
requirements = python3,kivy,pywebview,bottle,proxy-tools,typing_extensions,cryptography
# 图标文件
icon.filename = todo_icon.ico
# 屏幕方向:portrait(竖屏)、landscape(横屏)等
orientation = portrait
# Python 版本
osx.python_version = 3
# Kivy 版本(PyWebView 在移动端依赖 Kivy)
osx.kivy_version = 1.9.1
# 是否全屏
fullscreen = 0
# 启动画面颜色
android.presplash_color = #FFFFFF
# 所需权限
android.permissions = INTERNET,WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE
# Android 版本配置
android.api = 33
android.minapi = 21
android.sdk = 33
android.ndk = 25b
android.ndk_api = 21
# 应用主题(隐藏 ActionBar)
android.apptheme = @android:style/Theme.Material.NoActionBar
# 额外 JAR 包(如 pywebview-android.jar)
android.add_jars = lib/pywebview-android.jar
# 支持的 CPU 架构
android.archs = arm64-v8a, armeabi-v7a, x86, x86_64
# 允许 Android 自动备份(API ≥ 23)
android.allow_backup = True
更多配置可参考 PyWebView 官方示例:
github.com/r0x0r/pyweb...
希望这篇记录能帮助你顺利将 PyWebView 应用部署到移动端。如有疑问,欢迎留言交流。如果觉得有用,别忘了点赞、收藏与关注哦!