Python 实现Android打包并安装后启动

前言:

这个周末,学会了Python并写了一个打包的脚本,可以很方便的打包并安装。因为刚开始使用Python,不知道Python怎么面向对象,面向过程的写,一个流程走下来,之后深入学习后可以写的方便修改一点。

本文代码在: LearnTechDemo下00Something目录下的auto.pyauto.config两个文件。

1. 主要功能介绍:

  1. 自动从Git拉取代码 git pullgit clone
    此过程中如果第一次执行脚本,则需要向根目录写local.properties文件,设置SDK路径。
  2. 执行打包命令gradle cleangradle assembleDebug
  3. 自动安装到机器adb installadb shell am start -n 自动打开

该脚本主要功能就是这三个,看完后就有个大概认识,只要一执行,就能自动将最新apk运行到手机上并打开。

还有些其他很方便的功能:

  1. 在指定目录下创建AndroidApp,并在该目录下创建ApkSourceCode两目录。
    Apk目录:打包后build目录下的apk文件拷贝一份该目录,方便再次找到。
    SourceCode目录:git clone的项目代码到该目录下

  2. 添加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文件夹的名字
  1. 解析manifest.xml文件获取PackageNameLauncherActivityName
    使用ElementTree来解析xml,使用递归获取到LauncherActivity的名字用于打开app。

  2. 兼容了python2 和 python3。
    Mac上运行的是python2,在windows上运行时又适配到python3了。

2. 使用方法

  1. auto.pyauto.config 文件放在同一级目录下。

  2. 然后配置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或留言。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baiiu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值