一直有想自己制作移动APP的想法,特别是ChatGPT出现以后,可以给出非常完善的编码建议,让个人编程的门槛下降了一大截。有时候我也会编一些简单的算术练习小游戏,让小宝贝来玩。当然自己编的程序比较简单,游戏性比较差。玩了两回之后,她就没啥兴趣了,也没有起到很好的效果。不过,也总还是很有意思的。有时候我会想,如果能够把它编译成APK,在网上发布,无论是用来出售赚点小钱,或者在里面加入广告,免费使用,让这点兴趣爱好能够创造点收入,倒也是一个不错的想法。
我写程序一般都是用的简单易懂的python语言,那有没有什么办法将python脚本编译成可以在安卓上运行的APK文件呢?别说,还真有这样一种工具,叫做Buildozer,也就是推土机的意思。不过这个工具是一个命令行工具,只能运行在Linux下面。其实大家使用的都是Windows电脑,所以要想用到这个工具还挺麻烦的。不过前段时间,在玩大火的AI绘画程序Stable Diffusion的时候,接触到了谷歌的免费云计算环境——colab。这个平台背后实际上就是给用户创建了一个linux的实例。所以最简单的使用Buildozer的办法就是通过它了。也不用去安装Linux或者Windows支持的linux子系统,直接在CodeLab上运行一个笔记本就可以了。
在网上找了一下,有好几个版本的Buildozer的CoLab笔记本,其中感觉这个运行效率要稍微高一点。链接如下:
https://colab.research.google.com/drive/1lVsJPEkOGJWzjU206NzNKhwrSVCPFOfh?usp=sharing
其他的要么运行效率比较低,要么就已经过时了,编译会报错。于是就把先前编写的一个让小宝贝练习加减混合预算的小程序,试着用这个笔记本编译了一下。结果一开始,毫不意料的出错了。确实编译成了APK文件,在手机上也能够安装,但是点开图标的时候,这只闪了一下就崩溃了。于是折腾了很长时间,终于把这个事情搞顺了,编译出来的APK也可以在手机上完美运行。这里把一些踩过的坑简要记录一下,一来分享一下经验,二来也是为以后碰到类似的情况备查。
第一个容易踩的坑就是,先运行Buildozer的Collab脚本,运行到Buildozer init的时候,会生成一个叫做Buildozer.spec的文件。里面需要配置一下编译选项,其中需要更改的就是APP的名字,就是在手机上显示的那个名字,以及软件包的名字。注意软件包的名字里面是不能有中文汉字的,APP的名字倒是无所谓。
其次,我的这个计算练习程序里面使用了中文字体,它的后缀是.ttc,这个在默认配置里面是没有包含在内的。需要把它加到配置里面,这样在打包的时候才会把中文字体包含在内。然而,即便我把这个中文字体包含在打包的软件当中了,运行的时候仍然会报错。当然在手机上报错它就是闪退而已,你是看不到具体是什么错误的。所以你还需要一个调试的工具,就是Android Debug Bridge,又叫ADB。然后把手机用充电线和电脑的USB口连接起来,并在设置里找到USB调试选项。并把它打开,然后在电脑上输入adb.exe logcat -s python。这样就可以在电脑上看到运行后报错的内容了。我们发现运行的报错内容是找不到我的字体文件,但是这个程序在电脑上运行的时候是一切正常的呀。在电脑上我的字体文件和.py文件是放在同一个文件夹下面的,它们打包之后应该也是在同一个文件夹下面吧。事实确实如此,但是在安卓系统上,它就是不会去找同一文件夹下的资源。你必须插入python的OS模块,通过OS模块获取当前文件夹的绝对路径,然后将绝对路径和文件名连接在一起获得一条完整的到字体文件的路径。才能够让安卓上运行的程序读取到你的资源文件。在这里就是我的字体文件。这里还有坑,其实很简单,但是我花了很久才弄明白。就是在安卓系统上,对中文文件名的支持并不友好。如果你的字体文件的文件名用的是中文的话,即使你使用了绝对路径,仍然是读取不到的。所以你的资源文件尽量不要使用中文来作为文件名。
第三如果用python编写安卓APP的话,一般会使用一个叫做Kivy的用户界面框架。这个Kivy框架还有一个附加的包叫Kivy-MD,里面有一些更漂亮、更现代的用户界面控件。如果你使用了Kivy-MD的话,首先你得在buildozer .spec文件中的requirement项目下,添加Kivy-MD的依赖包,同时Kivy-MD还依赖另一个图形处理的包Pillow,把这两个包都要添加上去。同时新版的Kivy-MD和手机上的OpenGL库有冲突。如果不指定版本直接打包的话,在手机上还是会报错而运行不了,所以必须指定为Kivy-MD等于等于1.0.4版本,才能编译成功,并在手机上运行。
同时,一个很有特色的功能是buildozer还可以把使用Pygame库的Python程序也打包成APK。这样你就可以在电脑上编写有趣的游戏,然后打包成可以在安卓上运行的APK文件发布出来。当然,在编译的时候需要指定的依赖包也是比较多的,并不是只需要指定Pygame包就行了的。我把打包pygame程序的依赖包写在下面:
python3,pygame,jnius,sdl2,sdl2_image,sdl2_mixer,sdl2_ttf,png,jpeg
最后还有一个小窍门,buildozer编译apk的时间还是比较长的,至少需要20多分钟,有时还会更长,如果打包出来运行不了,修改后又要重新编译。一般来说重新编译之前需要运行buildozer clean清理一下编译环境,但是如果你只是对py文件做了少量的修改,可以略掉这一步骤,这样重新编译时间就变得很短。你只要等待不到一分钟的时间就可以看到修改的效果了。