美文网首页
一切都是因为懒—Android Studio自动打包

一切都是因为懒—Android Studio自动打包

作者: _compass | 来源:发表于2017-08-11 18:06 被阅读470次

    这是一篇在Mac上Android Studio自动打包脚本的产生以及优化的文章。

    其实自动打包的脚本大家已经写的很多了,我这里只是一个总结,有需要的同学,可以参考一下。

    起初我们项目有2个app(android,iOS各一个),测试版本加上线上版本,一共是4个app。打包app的时候,需要替换工程里的某些资源文件(例如服务器基地址,h5包等)。手工拷贝我打包过一次就再不想有第二次了,耗时太长,并且容易出错。所以当时写了一个简单的自动打包脚本:

    1.脚本这么写:

    1.1定义需要区分的类型:

    buildtype=Sample-hd-ol
    hosttype=ol
    

    1.2.获取当前工作路径:

    为什么要获取当前工作路径,而不是写死工程路径,是为了分支之后,我只需要找到编译脚本所在的位置,而不需要修改工程路径。
    例如我现在脚本所在位置是Sample/Shell目录下,工程代码路径在Sample/SampleHD下,那么获取当前路径这么写:

    #工作路径
    current_dir=$(pwd)
    echo $current_dir
    cd $current_dir
    cd ..
    cd Sample/SampleHD
    workspace_path=$(pwd)
    #打印一下代码路径
    echo $workspace_path
    
    

    1.3.拷贝项目所需要的资源:

    例如,我需要拷贝一个某个资源文件到工程:

    #resource在工程里的路径
    #拷贝resource路径
    resource_path=/Users/Compass/Package/WebApp/${buildtype}/resource.zip
    resource_workpath=${workspace_path}/app/src/main/assets/resource.zip
    
    #拷贝resource到工程路径,强制替换
    cp ${resource_path} ${resource_workpath}
    
    

    1.4.编译之后,将app输出到指定目录:

    #需要输出的app的路径
    app_path=/Users/Compass/Package/app/$(date +%Y%m%d)
    
    #以下为自动编译过程
    #编译config名称
    configname=samplerelease
    
    #编译路径
    build_path=./app/build/outputs/apk/app-${hosttype}-${configname}.apk
    
    #apk名称
    apk_name=${buildtype}.apk
    
    # 进入要工作的文件夹
    cd ${workspace_path}
    
    # 清空
    ./gradlew clean
    
    # 编译
    ./gradlew assemble${hosttype}${configname}
    
    # 按照日期创建
    mkdir ${app_path}
    
    # 将编译出的结果拷贝到指定文件夹下
    mv ${build_path} ${app_path}/${apk_name}
    

    是不是很简单?这样就完成了,但是,你会发现编译不通过,因为graldle还没有配置,配置如下:

    2.工程里这么配置:

    2.1.工程里(gradle.properties),配置秘钥:

    RELEASE_STORE_FILE=/Users/Compass/android/Key/wrkey.jks
    RELEASE_STORE_PASSWORD=password
    RELEASE_KEY_ALIAS=alias
    RELEASE_KEY_PASSWORD=password
    

    2.2. 在Module app的build.gradle里添加配置:

     signingConfigs {
            release{
                storeFile file (RELEASE_STORE_FILE)
                storePassword RELEASE_STORE_PASSWORD
                keyAlias RELEASE_KEY_ALIAS
                keyPassword RELEASE_KEY_PASSWORD
            }
        }
     buildTypes {
            samplerelease {
                debuggable false
                jniDebuggable false
                signingConfig signingConfigs.release
                minifyEnabled false
                zipAlignEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    

    上面的samplerelease,就是脚本里对应的:

    ./gradlew assemble${hosttype}${configname}
    

    这句里的configname;其中hosttype是Flavors,如果不需要动态配置某些参数,可以不需要加。
    添加Flavors,编译的时候,可根据ol,nt切换HOST_URL_VALUE,这个值在

    productFlavors {
            ol {
                manifestPlaceholders = [HOST_URL_VALUE: "https://www.xxx.xxx"]
            }
            nt {
                manifestPlaceholders = [HOST_URL_VALUE: "http://172.xxx.xxx.xxx"]
            }
        }
    

    HOST_URL_VALUE需要在AndroidManifest.xml里添加:

     <meta-data
                android:name="HOST_URL"
                android:value="${HOST_URL_VALUE}" />
    

    在你的代码里,这么写就可以动态获取到在gradle里配置的值了:

      public static String getHost(Context context) {
            String hostURL = getAppMetaData(context, "HOST_URL");
            if (hostURL != null) {
                return hostURL;
            }
    
            return DEFUALT_HOST;
        }
    

    这样,gradle里也配置好了,脚本也写好了,打开控制台,运行一下,试试看:

    cd /Users/Compass/Work/Sample/Shell
    ./sample_hd_ol.sh
    

    是不是发现有这个问题:

    -bash: ./sample_hd_ol.sh: Permission denied
    
    

    这是权限问题,输入下面命令就可以了:

     chmod 777 sample_hd_ol.sh
    

    再次执行脚本,看看结果。
    如果成功了,在输出目录下,就能看到打包好的apk了,比如,我这里是/Users/Compass/Package/app/20170811目录下:

    image.png

    这样,基本一个自动打包脚本就写好了。如果你有多个apk打包,可以写多个脚本文件批处理。

    当我们的项目,从2个app,发展到现在需要编译8个app的时候,出现了新的问题:

    太慢了,竟然需要35分钟!

    平均一个app需要编译4分钟。找了一下原因,是因为我们工程里引用了很多公共库,编译器编译的时候都在线获取版本;以及每次Build都有一个新起一个JVM等原因。

    参考这位同学的文章《加快gradle的编译速度总结-亲身经历》:
    http://www.jianshu.com/p/200d55b4d40a

    3.优化:

    3.1开启守护进程

    将工程的gradle.propertis复制出来,里面贴如下内容,然后此目录下,全局可以使用,例如我的:/Users/Compass/.gradle/

      // 开启线程守护,第一次编译时开线程,之后就不会再开了
      org.gradle.daemon=true 
      // 配置编译时的虚拟机大小
      org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8  
      // 开启并行编译
      org.gradle.parallel=true 
      // 启用新的孵化模式
      org.gradle.configureondemand=true  
    
    

    加了这个配置之后,原先编译里的这个提示:

    To honour the JVM settings for this build a new JVM will be forked. 
    Please consider using the daemon: https://docs.gradle.org/2.14.1/userguide/gradle_daemon.html.
    

    就变成了:

    Parallel execution with configuration on demand is an incubating feature.
    

    3.2 Gradle离线配置

    我将gradle包放入/Users/Compass/.gradle/下,指定Gradle home即可。这个目录也可以使用Android studio的安装目录:
    /Applications/Android\ Studio.app/Contents/gradle/gradle-2.14.1
    这里的gradle-2.14.1是我as里的gradle版本,你需要换成你自己的版本。


    image.png

    这两处修改了之后,编译速度就快多了,一个app1分钟:

    image.png

    我如果去掉./gradlew clean,不清空的话,编译速度更快,大概10秒就能编完:

    image.png

    恩,对于我2012年的电脑,在清空的情况下,1分钟我觉得已经可以接受了。8个app,大概10分钟吧。

    这样,我就可以在分支N个版本的时候,打开一个脚本,能自动打包N个app了。

    一切都是因为懒。

    相关文章

      网友评论

          本文标题:一切都是因为懒—Android Studio自动打包

          本文链接:https://www.haomeiwen.com/subject/lzhrrxtx.html