这篇博客谨以纪念我在python移动应用开发流逝的两个星期。趁着打包的漫漫时长,请让我从故事的开头一一道来。如果赶时间请直接前往“问题”一级标题。

萌芽的诞生

在某个温暖舒适的下午,我躺在床上准备阅读刚入坑的漫画。下载好压缩包并解压后,每章文件夹中存放着该话的jpg图片。我发现只能在手机图库上一张一张的翻,想根据目录检索还有些麻烦,不过漫画的精彩内容让我暂时忽略了这些不方便。津津有味地读完后,那种说不上的不爽感用上心头。为什么不能像电子书一样导入在书库看?参考了一些正版非正版的阅读软件,发现大部分都是在线图书没有本地导入。为什么不能整个本地阅读漫画工具呢?

于是第一个问题迎面而来:这类开发都较多使用java,可我能拿得出手的只有python。我要为了这个小想法多学一门新语言吗?

我的第一回答时否定的,我正好也趁着这个机会,试试非“寻常”的开发方法。于是我的方案有了开头。

剩下的问题是用谁来开发移动应用了,在一番调研后决定采用kivy,其一它的官方文档还挺友善,其二看上去它的已执行不错。

确定好大致方向后便先熟悉这个工具。

为了篇幅,我只对一些重要的情况写出来吧。

基于kivy的kivymd

在尝试了kivy的几个demo后,发现了kivymd,初次使用便觉得整体代码方便了不少,很多kivy需要手动设置的kivymd有现成素材。

在整个码代码过程就感觉在用kivymd的积木不断按照自己的蓝图构建样品,碰到不会的就查文档或者issue。

写代码的过程还是比较愉悦的,当看到在电脑(windows)的demo,愉悦感涌上心头。我以为第一个版本不久就能完成了,谁知道这只是开始。

打包平台的选择

也许实我神经大条亦或者目光短浅,在版本一的代码差不多后才想起来我是要把这玩意送到安卓上的。

Nuitka是不行了,它应该只能打包成可执行文件。在一番病急乱投医地查找过后,我发现了kivy的姐妹开源包–buildozer。

它可以只用一行代码就打包成apk文件,这正是我这种懒狗所需要的,缺陷就是它只能用在linux平台。虽说多了些不方便,但也可以理解,毕竟安卓的内核是linux嘛。

选择用自带的hyper-v,参考一些文章博客,花了点时间力气完成了环境配置。话说沉浸在虚拟机里听歌写代码别有一番风味呢,“目前Windows你的任务就是作为ubuntu的启动器了”。

真正的开始

第一阶段

buildozer虽然配置文件没什么要改的,大多是自动选择最合适的版本,但是运行起来多多少少都会有些问题。第一个最基本的条件是网络,必须能畅游互联网。第二是打包的时间比较长,没打包失败一次就要重新更改配置文件或者其它的环境问题,更改好有还要重置包,从安装依赖开始,这期间只能干瞪眼或者去issue页看看别人的问题(话说kivymd的贡献者有个二次元毛子欸,还有kivymd项目作者应该是俄国人)。辗转多次,花费的时间都快超过了我写代码的时间。

费了九牛二虎之力,当看到打包成功的那短短几个蓝色的单词 Android packaging done! 后,我感到了解脱,迎来了开发期间的第二次喜悦。

第二阶段

嗯?为什么闪退了。第一次软件打开在亮出kivymd的图标后便闪退到桌面了,之后又尝试多次,成功弹出了手机的闪退log信息。因为是第一次处理这种情况,手忙脚乱地搜索起来,看到一篇博客是将如何调试查看手机日志,便屁颠屁颠地去安装了adb,学了点调式方法。

查看日志后发现有一个库没有安装在python的虚拟环境中,之后更改buildozer配置文件重新打包。期间竟然又遇到了打包失败问题。

遇到个硬茬,无论我如何更改都出现的报错,看log似乎是出现在kivy的vbo.so文件中,于是我又去issus找,找到个相关问题但开源主没有正式回复,不过提出问题者找到了方法,便顺着链接到了kivymd,看到这个issue页讨论度蛮高的,作者也标了尽快在下个版本前处理的标签,经过完整翻阅一遍,解决方法就是安装路径指定为fix后的项目master分支。

程序终于不闪退了!就是有个“小瑕疵”,它不能打开文件管理器,这样的话最基本的导入漫画都做不到。

第三阶段

一通搜索下来,似乎问题在于不能直接/路径,在使用os.path.expanduser(“~”)后也不行,但这些在开发环境上都可以正常工作。

花了点时间搜索,之后发现可以通过android包(只有在安卓环境才能导入)来解决路径问题,参考后面的问题描述“MDFileManager不能正常在安卓机上打开”。

总结

一整个流程下来,学习了蛮多知识的,后端开发、简单GUI设计、虚拟机构建、ubuntu环境、安卓调试、以及我认为最重要的报错解决(时间占比80%以上)。

需要交流的话可以在侧边栏找到我的社交账号,私信就好啦。ヾ(≧▽≦*)o

感谢看我这么长的唠叨。(^_^)

一些遇到的问题

测试疯狂重复弹出一些log

这个情况相似,解决方法使用

1
adb logcat *:E | grep -v "ro.hardware.fp.sideCap" | grep -v "ro.hardware.fp.fod"

pip 问题

当我执行 pip install https://github.com/kivy/kivy/archive/master.zip
后报错

WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None,
status=None)) after connection broken by ‘ProxyError(‘Cannot connect to
proxy.’, OSError(‘Tunnel connection failed: 400 Bad Request’))’: /kivy/
kivy/archive/master.zip

参考了[1][2],以为是代理的问题,改了proxy后没有作用,又以为是pip环境出问题了,重装了pip、降级pip都不行。

后面又仔细看了报错,发现ProxyError后还有个OSError,又猜测问题出在OS上,在找了我用sudo解决问题了。联想到pip在usr的地方,推测是因为普通用户权限不够导致报错。这件事告诉我们要认真地看报错信息,而不是一口气复制整个报错问题粘贴到搜索框。

这里顺便提一嘴,sudo buildozer和buildozer不太一样,带sudo的在权限问题上都可以顺利通过,但有时用它打包的结果会出现一些问题,这个还需要自己仔细观察下。只要能确保自己的配置没有问题,那就大胆用sudo。

kivy开发用户指南文档

参考这里,有些的确很有用。

MDFileManager不能正常在安卓机上打开

参考这篇文章

在(/.buildozer/android/platform/python-for-android/pythonforandroid/bootstraps/sdl2/build/templates/AndroidManifest.tmpl.xml)文件中添加

1
2
3
<application android:requestLegacyExternalStorage="true" ... >
...
</application>

我的这段代码如下

1
2
3
4
5
6
7
8
9
10
from kivy.utils import platform

if platform == 'android':
from android.permissions import request_permissions, Permission
request_permissions([Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE]) # 获取权限

from android.storage import primary_external_storage_path
primary_ext_storage = primary_external_storage_path()

self.file_manager.show(primary_ext_storage)