一、项目背景
在Android应用开发流程中,打包发布是必不可少的环节。传统的打包方式需要手动执行多个步骤:
-
APK加固 - 使用第三方服务保护代码
-
APK签名 - 使用apksigner进行V1/V2/V3签名
-
多渠道打包 - 为不同应用市场生成渠道包
这些操作繁琐且容易出错,因此我开发了这个基于Python Tkinter的自动化打包工具,实现一键完成所有操作。
二、功能特性
🎯 核心功能
| 功能模块 | 说明 | 技术实现 |
|---------|------|---------|
| **APK加固** | 集成阿里云mPaaS专业版加固 | 调用msaEnhance模块 |
| **APK签名** | 支持V1/V2/V3多版本签名 | 使用apksigner工具 |
| **多渠道打包** | 支持15+主流应用市场渠道 | 自定义渠道信息注入 |
| **日志系统** | 实时显示打包进度和结果 | 线程安全队列机制 |
✨ 特色亮点
·自动化流程:选择APK后一键完成加固→签名→多渠道打包
·多应用支持:内置5个应用配置,自动识别包名
·渠道多选:支持全选/反选,灵活选择目标渠道
·现代UI:简洁美观的Tkinter图形界面
三、项目结构与核心代码
3.1 项目架构
├── android_package_tool.py # 主界面入口(Tkinter)
├── msaEnhance.py # 阿里云mPaaS加固模块
├── apkSign.py # APK签名模块(apksigner)
├── apkInfo.py # APK信息解析(aapt工具)
└── androidPackage.py # 渠道打包模块
3.2 核心代码解析
🔹 线程安全日志系统
python
def _process_log_queue(self):
"""处理日志队列,定时从队列中读取日志并显示"""
try:
while True:
msg = self.log_queue.get_nowait()
# 检查是否是特殊的"完成"标记
if msg == "_TASK_COMPLETED_":
self._on_task_completed()
else:
timestamp = self._get_time()
log_line = f"[{timestamp}] {msg}\n"
self.log_text.insert(tk.END, log_line)
self.log_text.see(tk.END)
except queue.Empty:
pass
self.root.after(100, self._process_log_queue)
设计思路:使用`queue.Queue`实现线程安全的日志更新,避免子线程直接操作UI控件导致的线程安全问题。
🔹 多应用配置管理
python
apk_package_info = {
"package_name_1": "app_name_1",
"package_name_2": "app_name_2",
"package_name_3": "app_name_3",
"package_name_4": "app_name_4",
"package_name_5": "app_name_5"
}
设计思路:通过字典映射实现多应用的配置管理,选择APK后自动识别包名并加载对应配置。
🔹 渠道选择实现
python
self.channel_options = [
('OGC', '官方'),
('LXS', '联想'),
('XMS', '小米'),
('BDS', '百度'),
('YYB', '应用宝'),
('QHS', '360'),
('WZJ', '豌豆荚'),
('RYS', '荣耀'),
('OPS', 'OPPO'),
('YYH', '应用汇'),
('KPS', '酷派'),
('HWS', '华为'),
('MZS', '魅族'),
('SXS', '三星'),
('VVS', 'VIVO')
]
# 存储选中的渠道(默认选中所有)
self.selected_channels = {code: tk.BooleanVar(value=True) for code, _ in self.channel_options}
# 创建渠道代号到名称的映射字典
self.channel_map = {code: name for code, name in self.channel_options}
设计思路:使用`BooleanVar`动态绑定复选框状态,支持全选/反选功能。
🔹 异步任务执行
python
def _start_process(self):
apk_path = self.apk_path.get().strip()
if not apk_path or not os.path.exists(apk_path):
self._log("错误:请选择有效的APK文件")
return
if self.is_processing:
self._log("正在处理中...")
return
enhance = self.is_enhance.get()
sign = self.is_sign.get()
# 获取选中的渠道列表
selected = [code for code, var in self.selected_channels.items() if var.get()]
if not selected:
self._log("错误:请至少选择一个渠道")
return
channels_str = ", ".join(selected)
self._log(f"开始处理: {os.path.basename(apk_path)}")
self._log(f"加固: {'是' if enhance else '否'}, 签名: {'是' if sign else '否'}")
self._log(f"选中渠道: {channels_str}")
self.is_processing = True
self.btn_start.config(state="disabled")
self.progress_bar.start()
# 使用非守护线程执行任务
thread = threading.Thread(target=self._execute, args=(apk_path, enhance, sign, selected))
thread.start()
设计思路:将耗时操作放在子线程中执行,避免阻塞UI主线程。
四、核心执行流程
选择APK → 解析APK信息 → 识别应用配置
↓
执行加固(可选)→ msaEnhance.excute_whole_flow()
↓
执行签名(可选)→ ApkSigner.sign_apk()
↓
多渠道打包 → 循环调用androidPackage.build_single_apk()
↓
任务完成 → 更新UI状态
关键代码:执行流程
python
def _execute(self, apk_path, enhance, sign, channels):
try:
enhance_output_apk = None # 初始化变量
sign_output_apk = None # 初始化变量
if enhance:
self._log("执行加固...")
try:
file_name = apk_path.split("/")[-1]
output_name = file_name.replace(".apk", "_enhanced.apk")
enhance_output_apk = apk_path.replace(os.path.basename(apk_path), output_name)
if not enhance_output_apk:
enhance_output_apk = "enhanced_apk.apk"
msaEnhance.set_config(app_package_name=self.package_name.get(), local_apk=apk_path, output_apk=enhance_output_apk)
msaEnhance.excute_whole_flow()
self._log("加固完成")
except Exception as e:
self._log(f"加固失败: {str(e)}")
import traceback
self._log(traceback.format_exc())
if sign:
self._log("执行签名...")
try:
self._log("初始化签名工具...")
signer = ApkSigner()
signer.set_app(app_package_name=self.package_name.get())
# 如果没有执行加固,使用原始APK路径
input_apk = enhance_output_apk if enhance_output_apk else apk_path
sign_file_name = input_apk.split("/")[-1]
sign_output_name = sign_file_name.replace(".apk", "_signed.apk")
sign_output_apk = input_apk.replace(os.path.basename(input_apk), sign_output_name)
if not sign_output_apk:
sign_output_apk = "enhanced_signed_apk.apk"
signer.set_config(input_apk=input_apk, output_apk=sign_output_apk)
self._log("签名工具初始化完成")
signer.sign_apk()
self._log("签名完成")
except Exception as e:
self._log(f"签名失败: {str(e)}")
import traceback
self._log(traceback.format_exc())
# 处理多个渠道
# 确定要使用的APK:签名后的 > 加固后的 > 原始的
channel_input_apk = sign_output_apk if sign_output_apk else (enhance_output_apk if enhance_output_apk else apk_path)
self._log(f"开始生成渠道包 ({len(channels)} 个渠道)")
for idx, channel in enumerate(channels, 1):
self._log(f" [{idx}/{len(channels)}] 渠道: {channel}")
try:
channel_id = channel
channel_name = self.channel_map.get(channel, channel)
log_message = f'------开始打包渠道号 {idx}/{len(channels)}------\n'
log_message += '渠道号:%s\n' % channel_id
log_message += '渠道名:%s\n' % channel_name
result = androidPackage.build_single_apk(channel_id, channel_name, channel_input_apk)
self._log(log_message)
self._log(f"✅ 渠道 {channel} 包生成成功: {result}")
except Exception as e:
self._log(f"❌ 渠道 {channel} 包生成失败: {str(e)}")
import traceback
self._log(traceback.format_exc())
self._log("✅ 处理完成!")
except Exception as e:
self._log(f"❌ 执行错误: {str(e)}")
import traceback
self._log(traceback.format_exc())
finally:
# 通过日志队列发送任务完成信号(线程安全)
self._log("_TASK_COMPLETED_")
五、界面设计
5.1 主界面布局

5.2 界面优化要点
| 优化项 | 实现方式 |
| 渠道布局 | 每行4个复选框,紧凑排列 |
| 按钮区域 | 居中分布,间距均匀 |
| 日志窗口 | 自适应高度,填充剩余空间 |
| 版本信息 | 动态获取当前年份 |
六、技术亮点总结
6.1 线程安全设计
-
使用队列实现日志的线程安全更新
-
子线程通过队列发送"任务完成"信号
-
主线程通过`after()`方法定时处理队列
6.2 模块化架构
-
各功能模块独立封装
-
通过回调函数实现日志集成
-
支持动态配置和扩展
6.3 用户体验优化
-
自动识别应用配置
-
支持渠道多选和快捷操作
-
实时进度展示和日志输出
七、使用指南
7.1 环境要求
# 依赖组件
Python 3.x # 开发语言
Tkinter # UI框架(Python内置)
Android SDK # 含aapt、apksigner工具
阿里云mPaaS账号 # 加固服务
7.2 快速开始
运行工具
python android_package_tool.py
操作步骤
-
点击「浏览」选择APK文件
-
勾选需要的操作(加固/签名)
-
选择目标渠道(默认全选)
-
点击「开始」执行打包流程
八、总结
这个Android打包工具通过Python实现了自动化打包流程,主要优势:
-
高效:一键完成加固、签名、多渠道打包
-
稳定:线程安全的日志系统,避免UI卡顿
-
灵活:支持多应用配置和渠道自定义
-
易用:直观的图形界面,降低使用门槛