初识gradle打包apk

现在大多数开发都使用android studio开发app,那么我们就要学会使用gradle脚本打包apk(抛砖引玉^-^)

翻译自 链接http://blog.csdn.net/u012124438/article/details/72835893,感觉这篇文章写的不错,我这里摘取了gradle的打包技巧。

第一步:

你需要去下载安卓gradle(这里附上下载链接http://www.androiddevtools.cn/),个人感觉这个网站挺好用的。

第二步:

你需要去环境变量path目录下配置下gradle(gradle所在目录\bin)就可以了,来测试下是否配置成功

出现以上图片的显示信息,说明你的配置没有问题.

第三步:

接下来进入正题

替换AndroidManifest下的相关字段

把配置中的${app_label}替换为@string/app_name

 

android{
    defaultConfig{
        manifestPlaceholders = [app_label:"@string/app_name"]
    }
}

如果只想替换debug版本:

 

android{
    buildTypes {
        debug {
            manifestPlaceholders = [app_label:"@string/app_name_debug"]
        }
        release {
        }
    }
}

更多的需求是替换渠道编号:

 

 

android{
    productFlavors {
        // 把dev产品型号的apk的AndroidManifest中的channel替换dev
        "dev"{
            manifestPlaceholders = [channel:"dev"]
        }
    }
}

独立配置签名信息

对于签名相关的信息,直接写在gradle当然不好,特别是一些开源项目,可以添加到gradle.properties:

RELEASE_KEY_PASSWORD=xxxx 
RELEASE_KEY_ALIAS=xxx
RELEASE_STORE_PASSWORD=xxx
RELEASE_STORE_FILE=G\:\\..\\XX.jks

这里要注意jks文件的目录要使用\\

然后在build.gradle中引用即可,上面相当于定义全局的配置信息:

android {
    signingConfigs {
        release {
            storeFile file(RELEASE_STORE_FILE)
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
        }
    }
}

如果不想提交到版本库,可以添加到local.properties中,然后在build.gradle中读取。

多渠道打包

多渠道打包的关键之处在于,定义不同的product flavor, 并把AndroiManifest中的channel渠道编号替换为对应的flavor标识:

android {
    productFlavors {
        dev{
            manifestPlaceholders = [channel:"dev"]
        }
        official{
            manifestPlaceholders = [channel:"official"]
        }
        // ... ...
        wandoujia{
            manifestPlaceholders = [channel:"wandoujia"]
        }
        xiaomi{
            manifestPlaceholders = [channel:"xiaomi"]
        }
        "360"{
            manifestPlaceholders = [channel:"360"]
        }
}

注意一点,这里的flavor名如果是数字开头,必须用引号引起来。 

自定义Build Type

前面说到默认的build type有两种debug和release,区别如下:

// release版本生成的BuildConfig特性信息
public final class BuildConfig {
  public static final boolean DEBUG = false;
  public static final String BUILD_TYPE = "release";
}
// debug版本生成的BuildConfig特性信息
public final class BuildConfig {
  public static final boolean DEBUG = true;
  public static final String BUILD_TYPE = "debug";
}

现在有一种需求,增加一种build type,介于debug和release之间,就是和release版本一样,但是要保留debug状态(如果做过rom开发的话,类似于user debug版本),我们称为preview版本吧。 
其实很简单:

android {
    signingConfigs {
        debug {
            storeFile file(RELEASE_STORE_FILE)
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
        }
        preview {
            storeFile file(RELEASE_STORE_FILE)
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
        }
        release {
            storeFile file(RELEASE_STORE_FILE)
            storePassword RELEASE_STORE_PASSWORD
            keyAlias RELEASE_KEY_ALIAS
            keyPassword RELEASE_KEY_PASSWORD
        }
    }
    buildTypes {
        debug {
            manifestPlaceholders = [app_label:"@string/app_name_debug"]
        }
        release {
            manifestPlaceholders = [app_label:"@string/app_name"]
        }
        preview{
            manifestPlaceholders = [app_label:"@string/app_name_preview"]
        }
    }
}


另外,build type还有一个好处,如果想要一次性生成所有的preview版本,执行assemblePreview即可,debug和releae版本同理。如果想生成所有的apk直接执行gradle assemble即可

build type中的定制参数

上面我们在不同的build type替换${app_label}为不同的字符串,这样安装到手机上就能明显的区分出不同build type的版本。 
除此之外,可能还可以配置一些参数,列几个在工作中用到的:

android {
        debug {
            manifestPlaceholders = [app_label:"@string/app_name_debug"]
            applicationIdSuffix ".debug"
            minifyEnabled false
            signingConfig signingConfigs.debug
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        release {
            manifestPlaceholders = [app_label:"@string/app_name"]
            minifyEnabled true
            shrinkResources true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        preview{
            manifestPlaceholders = [app_label:"@string/app_name_preview"]
            applicationIdSuffix ".preview"
            debuggable true // 保留debug信息
            minifyEnabled true
            shrinkResources true
            signingConfig signingConfigs.preview
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

这里解释一下相关配置说明:

// minifyEnabled 混淆处理
// shrinkResources 去除无用资源
// signingConfig 签名
// proguardFiles 混淆配置
// applicationIdSuffix 增加APP ID的后缀
// debuggable 是否保留调试信息

当升级sdk、build tool、target sdk等,几个module都要更改,非常的麻烦。最重要的是,很容易忘记,最终导致app module之间的差异不统一,也不可控。 
强大的gradle插件在1.1.0支持全局变量设定,一举解决了这个问题。 
先在project的根目录下的build.gradle定义ext全局变量:

ext {
    compileSdkVersion = 22
    buildToolsVersion = "23.0.1"
    minSdkVersion = 10
    targetSdkVersion = 22
    versionCode = 34
    versionName = "v2.6.1"
}

然后在各module的build.gradle中引用如下:

Android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion
    defaultConfig {
        applicationId "com.xxx.xxx"
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.versionCode
        versionName rootProject.ext.versionName
    }
}

然后每次修改project级别的build.gradle即可实现全局统一配置。

自定义导出的APK名称

默认android studio生成的apk名称为app-debug.apk或者app-release.apk,当有多个渠道的时候,需要同时编出50个渠道包的时候,就麻烦了,不知道谁是谁了。 
这个时候,就需要自定义导出的APK名称了,不同的渠道编出的APK的文件名应该是不一样的。这里的导出目录是默认的工程下的outputs目录

android {
    // rename the apk with the version name
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent,
                    "lol-${variant.buildType.name}-${variant.versionName}-${variant.productFlavors[0].name}.apk".toLowerCase())
        }
    }
}

当apk太多时,如果能把apk按debug,release,preview分一下类就更好了(事实上,对于我这样经常发版的人,一编往往就要编四五十个版本的人,debug和release版本全混在一起没法看,必须分类),简单:

android {
    // rename the apk with the version name
    // add output file sub folder by build type
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    output.outputFile.parent + "/${variant.buildType.name}",
                    "lol-${variant.buildType.name}-${variant.versionName}-${variant.productFlavors[0].name}.apk".toLowerCase())
        }
    }
}

现在生成了类似于lol-dev-preview-v2.4.0.0.apk这样格式的包了,preview的包自然就放在preview的文件夹下,清晰明了。我们也可以指定目录保存生成的apk,直接保存到g盘下apk目录。

applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    "F:\\ddz",
                    "lz-${variant.buildType.name}-${variant.versionName}-${variant.productFlavors[0].name}.apk".toLowerCase())
        }
    }

接下来最后一步查看apk是否签名成功,解压apk在inf文件下输入keystore命令keytool -printcert -file META-INF/CERT.RSA,显示所有者,有效日期...信息,即签名成功。

(0920插入)最经遇到过打包时,会导致一些配置错误,现在把他放到了res/values/string.xml下了。只需要在android打包的版本控制中加入以下代码

resValue("string", "test_str", "lztest") //在res/value/string下插入test_str字段

(0924插入)gradle中获取时间的方法+在BuildConfig.java文件中插入全局常量

//获取时间戳
def getDate() {
    def date = new Date()
    def formattedDate = date.format('yyyy-MM-dd HH-mm')
    return formattedDate
}
//第一个int表示内型,可以是(int,boolean,String),第二个是字段名,第三个是字段的值
buildConfigField "int", "lz_test",  "1"
//Tips:如果是String内型,值必须是  ‘“值”’ 这样紫的。代码中直接用就好,列:BuildConfig.lz_test

gradle之打jar包的方法

//修改jar名字+指定jar生成的地方
task makeJar(type:Copy){
    //删除存在的jar
    delete 'build/outputs/test.jar'
    //设置拷贝的文件
    from('build/intermediates/bundles/release/')
    //打完jar包后的文件目录
    into('libs/')
    //只关心classes.jar
    include('classes.jar')
    rename('classes.jar','test.jar')
}

makeJar.dependsOn(build)

Tips:有一点大家需要注意build/intermediates/bundles/release/可能没有,这时候你需要去build.gradle的android下去配置publishNonDefault = true属性就ok了。

Tips:(0924加),最近使用gradle3.0.1发现build/intermediates/bundles这个路径不存在了,3.0.1以后路径发生了变换新的jar路径:build/intermediates/packaged-classes/release/

 

打完收工,感谢前面博客的博主

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值