前言:
这个周末,学会了Python并写了一个打包的脚本,可以很方便的打包并安装。因为刚开始使用Python,不知道Python怎么面向对象,面向过程的写,一个流程走下来,之后深入学习后可以写的方便修改一点。
本文代码在: LearnTechDemo下00Something目录下的auto.py
和auto.config
两个文件。
1. 主要功能介绍:
- 自动从Git拉取代码
git pull
或git clone
此过程中如果第一次执行脚本,则需要向根目录写local.properties
文件,设置SDK路径。 - 执行打包命令
gradle clean
后gradle assembleDebug
- 自动安装到机器
adb install
后adb shell am start -n
自动打开
该脚本主要功能就是这三个,看完后就有个大概认识,只要一执行,就能自动将最新apk运行到手机上并打开。
还有些其他很方便的功能:
-
在指定目录下创建
AndroidApp
,并在该目录下创建Apk
和SourceCode
两目录。
Apk目录
:打包后build
目录下的apk文件
拷贝一份该目录,方便再次找到。
SourceCode目录
:git clone的项目代码到该目录下 -
添加
auto.config
配置文件,用来配置一些基本的路径。使用Python的ConfigParser
包来读取配置文件。
- 现在主要配置:
Root_SDK_Dir
: SDK的绝对路径,用于local.properties
git_clone_address
:项目的Git地址
git_branch_name
:要拉取的远端分支名
assembleRelease
:boolean值,是否打release包
base_file_dir
:是在哪个目录下创建AndroidApp文件夹
create_dir_name
:就是这个AndroidApp文件夹的名字,可以设置这个更改 - 这两个可以不设置
optional
:
create_code_dir_name
:这个SourceCode文件夹的名字
create_apk_dir_name
:这个Apk文件夹的名字
-
解析
manifest.xml
文件获取PackageName
和LauncherActivityName
。
使用ElementTree来解析xml,使用递归获取到LauncherActivity的名字用于打开app。 -
兼容了python2 和 python3。
Mac上运行的是python2,在windows上运行时又适配到python3了。
2. 使用方法
-
将
auto.py
和auto.config
文件放在同一级目录下。 -
然后配置
auto.config
文件:
Root_SDK_Dir
是你的SDK的绝对路径
git_clone_address
是你的Git地址
git_branch_name
要拉取的远端分支名
assembleRelease
boolean值,是否打release包
base_file_dir
是一个绝对路径,可随便填
create_dir_name
将在base_file_dir
生成一个目录,用于存放项目代码和打出来的APK文件
配置好后你就可以使用python命令行运行该脚本,等待打包完成后运行到机器。
3. 主要代码介绍
1.git拉取代码
# 进入SourceCode目录下
os.chdir(code_dir)
print('进入SourceCode下: ' + os.getcwd())
print('\n')
print('=============================================')
print('git clone or git pull')
print('=============================================')
if not os.listdir(code_dir):
#空文件夹
os.system('git clone ' + git_clone_address +' ' + code_dir)
else:
#已经clone过
os.system('git pull')
2.gradle打包
# 生成local.properties文件
def createLocalPropertiesFile(sourceDir,fileName,root_sdk_dir):
if not os.path.exists(sourceDir):
return
fileDir = sourceDir + '/' + fileName
if os.path.exists(fileDir):
return
f = open(fileDir,'w');
f.write('sdk.dir=' + root_sdk_dir)
f.close()
createLocalPropertiesFile(code_dir,'local.properties',Root_SDK_Dir)
# 打包
print('\n')
print('=============================================')
print('gradle clean')
print('=============================================')
os.system('gradle clean');
print('\n')
print('=============================================')
print('gradle assembleDebug, generate apk')
print('=============================================')
os.system('gradle assembleDebug')
3.安装apk
#安装apk
print('\n')
print('=============================================')
print('install apk')
print('=============================================')
def getFileName(sourceDir):
if not os.path.exists(sourceDir):
return;
for filename in os.listdir(sourceDir):
if '.apk' in filename:
return filename
apkName = getFileName(apk_dir)
apkPath = apk_dir + '/' + apkName
print(apkPath)
os.system('adb install -r ' + apkPath)
4.打开app
#获取PackageName,launcherActivity
def findLauncherActivityName(ele,targetString):
for childElem in ele:
if len(list(childElem)) == 0:
if cmp(childElem.get('{http://schemas.android.com/apk/res/android}name'),"'" + targetString +"'"):
return True
else:
return False
else:
# print('has child, ' + childElem.tag, childElem.attrib)
return findLauncherActivityName(childElem,targetString)
def getLauncherActivity(xmlFileDir):
tree = ET.ElementTree(file=xmlFileDir)
root = tree.getroot()
packageName = root.get('package')
for elem in tree.iter(tag = 'activity'):
if findLauncherActivityName(elem,'android.intent.action.MAIN'): #if has
if(findLauncherActivityName(elem,'android.intent.category.LAUNCHER')):
return packageName,elem.get('{http://schemas.android.com/apk/res/android}name')
PackageName,LauncherActivity = getLauncherActivity(code_dir + '/app/src/main/AndroidManifest.xml')
# 先关闭该进程
os.system('adb shell am force-stop ' + PackageName)
# 打开该LauncherActivity
if PackageName in LauncherActivity:
os.system('adb shell am start -n '+ PackageName +'/' + LauncherActivity)
else:
os.system('adb shell am start -n '+ PackageName +'/' + PackageName + LauncherActivity)
4. 缺点
该脚本需要大量的环境配置,尤其是Gradle的配置。在打包过程中,需要一系列的工具,BuildTools、gradle plungin等,并不适合开发以外的人使用,需要学习的东西太多。
但是这个脚本是个学习python练手的好项目。
结语
发现Python很容易上手,而且很方便。没有分号和大括号代码看起来真的很清爽,字符串也可以用单引号,很方便。恩,在这个过程中,发现好像 jenkins 就能很方便的做这种事,可以研究研究。
恩,希望能对大家有帮助。在使用过程中有Bug或者有更好的实现请留issue或留言。