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

来源:互联网 发布:单链表java实现 编辑:程序博客网 时间:2024/05/11 16:23

前言:

这个周末,学会了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文件夹的名字
  3. 解析manifest.xml文件获取PackageNameLauncherActivityName
    使用ElementTree来解析xml,使用递归获取到LauncherActivity的名字用于打开app。

  4. 兼容了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

#安装apkprint('\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 filenameapkName = getFileName(apk_dir)apkPath = apk_dir + '/' + apkNameprint(apkPath)os.system('adb install -r ' + apkPath)

4.打开app

#获取PackageName,launcherActivitydef 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)# 打开该LauncherActivityif 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或留言。

2 0