目录
4.1 了解buildozer.spec配置文件中的常用参数
4.2 修改配置文件打包apk
在上一节内容中,我们配置好了打包环境,还顺带成功打包出了一个apk文件(读者可以把这个apk安装到手机上运行)。不过在打包这个apk前,我们没有修改buildozer.spec配置文件中的内容。在本节,笔者会带大家了解下配置文件中的一些常用参数,并正式打包一个apk文件。
4.1 了解buildozer.spec配置文件中的常用参数
title:应用名称。名称不要太长,否则会在界面上显示不完全。而且最好不要使用奇奇怪怪的字符,不一定能够成功显示。
package.name:apk的包名称。不要出现特殊字符,用全英文。
package.domain:该参数应包含开发者信息,而且会用作apk包的标识符。比如一家名为ABC的公司开发了一个记事本应用,那这个参数可以填写成com.abc.notebook。有很多包命名的规范,大家可以网上用关键词“安卓包命名规范”搜索下。
source.dir:包含被打包的入口程序(即main.py)所在的文件夹路径。
source.include_exts:打包时要包含进去的文件类型,不在这个参数中表明的文件类型是不会被打包进去的。如果这个参数不填,值是空白的话,就表示会打包所有文件。
source.include_patterns:使用模式匹配表示要打包进去的文件。
source.exclude_exts:打包时要排除的文件类型。
source.exclude_dirs:打包时要排除的文件夹名称,即该文件夹中的文件不会被打包进去。
source.exclude_patterns:使用模式匹配表示不会打包进去的文件。
version:包版本。和程序第一行__version__ = "1.0.0"代码中填写的版本一样即可。当然,如果程序中没有写版本信息的话,填写该参数也是一样的。
version.regex和version.filename:前者匹配类似这样的代码__version__ = "1.0.0"行;后者指定包含版本代码的py文件。如果version参数没有填,那通过这两个参数,Buildozer会自动从程序中获取版本信息。
requirements:应用包含的库或模块。该参数非常重要,必须填写正确。读者在程序中导入的库或模块都在填写在这个参数中。比方说,我们使用了kivy和requests这两个库,那么该参数就可以写成下面这样。
requirements = kivy,requests
requirements.source.kivy:指定要打包进去的kivy库文件夹路径,如果注释掉该参数的话,Buildozer会自动去Python的安装路径下去寻找这个库。如果要指定requests库的文件夹路径,那可以再配置文件中再加上一行requirements.source.requests = requests库文件夹的路径。
presplash.filename:应用启动画面图片路径。
icon.filename:应用图标的路径。
orientation:应用横屏还是竖屏显示。landscape表示横屏,portrait表示竖屏,sensorLandscape也是横屏,但会根据手机方向自动适应调整,all表示都可以。
fullscreen:是否全屏显示,默认是全屏。0的话表示非全屏,我们还可以看到手机的状态栏。要全屏的话可以填写1。
4.2 修改配置文件打包apk
在上一节打包后,demo文件夹下出现了两个新的文件夹:bin和.buildozer。
打包生成的apk会放在bin文件夹中,而.buildozer文件夹则包含一些依赖文件。如果我们要打包一个类似的程序,可以不用.buildozer文件夹删除了再重新打包(bin文件夹可以删除),否则可能某些依赖文件就需要重新下载,很浪费时间,更不用说可能还会因为网络原因下载失败。如果针对新程序的某些依赖文件不存在,Buildozer会再去另外下载。
如果是要打包完全不同的程序(指用的库或模块完全不同),则建议全部删除后再重新下载依赖打包(防止出现一些难搞的报错),不过某些依赖文件像Android SDK、NDK等是存放在主目录文件夹下的,打包时Buildozer会从这里面直接复制,不会再重新下载。
现在我们开始打包一个新的程序,程序代码来自Kivy官方文档。虽然程序与上一节内容中的类似,只使用了kivy,但笔者还是决定带大家从头开始一步步演示,这样大家也可以更熟悉一些。
第一步:删除之前打包生成的bin以及buildozer.spec,把.buildozer移到其他路径下,然后在终端中输入touch pong.kv生成一个kv格式的文件。
注:之所以不删除之前打包生成的.buildozer文件夹,而是移到其他路径下,是担心重新打包时会因为网络原因下载不了某些文件。如果出现这样的情况,那可以直接从之前的.buildozer文件夹中复制相关文件,节省时间。
第二步:分别在main.py和pong.kv中输入以下代码。
注:笔者删除了官方文档中pong.kv的第一行代码 #:kivy 1.0.9
main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import (
NumericProperty, ReferenceListProperty, ObjectProperty
)
from kivy.vector import Vector
from kivy.clock import Clock
class PongPaddle(Widget):
score = NumericProperty(0)
def bounce_ball(self, ball):
if self.collide_widget(ball):
vx, vy = ball.velocity
offset = (ball.center_y - self.center_y) / (self.height / 2)
bounced = Vector(-1 * vx, vy)
vel = bounced * 1.1
ball.velocity = vel.x, vel.y + offset
class PongBall(Widget):
velocity_x = NumericProperty(0)
velocity_y = NumericProperty(0)
velocity = ReferenceListProperty(velocity_x, velocity_y)
def move(self):
self.pos = Vector(*self.velocity) + self.pos
class PongGame(Widget):
ball = ObjectProperty(None)
player1 = ObjectProperty(None)
player2 = ObjectProperty(None)
def serve_ball(self, vel=(4, 0)):
self.ball.center = self.center
self.ball.velocity = vel
def update(self, dt):
self.ball.move()
# bounce of paddles
self.player1.bounce_ball(self.ball)
self.player2.bounce_ball(self.ball)
# bounce ball off bottom or top
if (self.ball.y < self.y) or (self.ball.top > self.top):
self.ball.velocity_y *= -1
# went of to a side to score point?
if self.ball.x < self.x:
self.player2.score += 1
self.serve_ball(vel=(4, 0))
if self.ball.right > self.width:
self.player1.score += 1
self.serve_ball(vel=(-4, 0))
def on_touch_move(self, touch):
if touch.x < self.width / 3:
self.player1.center_y = touch.y
if touch.x > self.width - self.width / 3:
self.player2.center_y = touch.y
class PongApp(App):
def build(self):
game = PongGame()
game.serve_ball()
Clock.schedule_interval(game.update, 1.0 / 60.0)
return game
if __name__ == '__main__':
PongApp().run()
pong.kv
<PongBall>:
size: 50, 50
canvas:
Ellipse:
pos: self.pos
size: self.size
<PongPaddle>:
size: 25, 200
canvas:
Rectangle:
pos: self.pos
size: self.size
<PongGame>:
ball: pong_ball
player1: player_left
player2: player_right
canvas:
Rectangle:
pos: self.center_x - 5, 0
size: 10, self.height
Label:
font_size: 70
center_x: root.width / 4
top: root.top - 50
text: str(root.player1.score)
Label:
font_size: 70
center_x: root.width * 3 / 4
top: root.top - 50
text: str(root.player2.score)
PongBall:
id: pong_ball
center: self.parent.center
PongPaddle:
id: player_left
x: root.x
center_y: root.center_y
PongPaddle:
id: player_right
x: root.width - self.width
center_y: root.center_y
第三步:在终端中输入python3 main.py命令运行main.py,确保程序运行正常。读者可以用鼠标拖动两边的白板试玩下。
第四步:在终端中输入buildozer init命令生成配置文件。
第五步:从iconfont网站上下载一个大小为128px的icon图标文件,放到共享文件夹中后复制到demo文件夹下。
第六步:修改配置文件中的一些参数。
title = Pong Game
package.name = ponggame
package.domain = org.louis.ponggame
version = 1.0.0
icon.filename = game.png
orientation = landscape
第七步:将配置文件保存后,在终端中输入buildozer -v android debug命令开始打包。
最终打包成功,我们可以在bin文件夹中看到生成的apk文件。
在模拟器中也运行成功。