Kevin Su bio photo

Kevin Su

patience, persevere, and enjoy

Email Github Stackoverflow

问题1:
今天忘记了使用正式keystore签名,但是忘了把高德地图的key切换过来,到时测试的时候,地图用不了,为了能够做到,用正式keystore签名就自动用高德的正式key,测试keystore签名就高德的测试key.查阅资料后,做了如下改动.

在app的gradle文件中,设置buildTypes中的manifestPlaceholders参数,

manifestPlaceholders = [channel_value: "1", amap_key: "7b5f2bf1db1e3a0568ec77b3b5b60dec", git_code: "code:" + revision()]

其中channel_value:是渠道号,amap_key:是高德地图的key,git_code:是版本号.然后在release和debug中各自设置对应的manifestPlaceholders.

buildTypes {
        //正式(正式服,正式签名),TODO 发布正式包,通过productFlavors来设置
        release {
            signingConfig signingConfigs.releaseConfig
            //是否混淆
            minifyEnabled false
            //是否Align
            zipAlignEnabled true
            //混淆的proguard文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //是否输出LOG信息
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //服务器类型,1为测试服,2为正式服;@NetConfig
            buildConfigField "int", "SERVER_TYPE", "2"
        }
        //开发(测试服,正式签名)
        develop {
            signingConfig signingConfigs.releaseConfig
            manifestPlaceholders = [channel_value: "1", amap_key: "7b5f2bf1db1e3a0568ec77b3b5b60dec", git_code: "code:" + revision()]
            zipAlignEnabled true
            buildConfigField "boolean", "LOG_DEBUG", "true"
            buildConfigField "int", "SERVER_TYPE", "1"
        }
        //测试(测试服,测试签名)
        debug {
            manifestPlaceholders = [channel_value: "1", amap_key: "6c6adfbcfb7aa7a15d7610d5b4a9c9d3", git_code: "code:" + revision()]
            zipAlignEnabled true
            buildConfigField "boolean", "LOG_DEBUG", "true"
            buildConfigField "int", "SERVER_TYPE", "1"
        }
    }
 ```
 通过这个方法,就可以在用正式签名的时候,设置的是正式的高德key,而不用每次用不同的签名,就去改一次,减少错误的机率.
 
*****
 
问题2:  
打正式包的时候,会要输入keystore的密码,别名还有别名密码等信息,但是这种重要的信息,又不能被推送到git上,以防泄露,那么就不能直接在build.gradle中显示.

signingConfigs { releaseConfig { storeFile file(STORE_FILE) storePassword STORE_PASSWORD keyAlias KEY_ALIAS keyPassword KEY_PASSWORD } } ```

然后把STORE_FILE, STORE_PASSWORD, KEY_ALIAS, KEY_PASSWORD等信息记录到gradle.properties文件当中.同时,请保证gradle.properties文件不会被上传的git上.

gradle.properties:

//签名信息
STORE_FILE=/xxx/xxx/xxx/xxx.keystore
STORE_PASSWORD=password
KEY_ALIAS=alias
KEY_PASSWORD=password

注意,没有双引号….

问题3:
改着改着,发现每次都要输入这个git的版本号,也是挺麻烦的,就想着能不能把这个也自动获取.然后就从一片文章中看到以下代码..

//获取git的版本号
def revision() {
    def code = new ByteArrayOutputStream()
    exec {
        commandLine 'git', 'rev-parse', '--short', 'HEAD'
        standardOutput = code
    }
    return code.toString().trim()
}

groovy通过命令行,调用git的命令,获取6位的版本号.
参考

问题4:
对于输出的文件名称的修改!!!每次都去修改名称也是蛮烦的一件事,一个不小心,名字就改错了.

在android标签中加入

//修改生成的最终文件名
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                File outputDirectory = new File(outputFile.parent);
                def fileName
                if (variant.buildType.name == "release") {
                    //输出:bnj_s_2015.12.12_4886faf_c360.apk
                    String channelName = "homepage";
                    if(variant.productFlavors[0] != null){
                        channelName = variant.productFlavors[0].name;
                    }
                    fileName = "bnj_s_${packageTime()}_${revision()}_${channelName}.apk"
                } else if (variant.buildType.name == "develop") {
                    //输出:bnj_s_2015.12.12_4886faf.apk
                    fileName = "bnj_s_${packageTime()}_${revision()}.apk"
                } else {
                    //输出:bnj_s_2015.12.12_4886faf_debug.apk
                    fileName = "bnj_s_${packageTime()}_${revision()}_debug.apk"
                }
                output.outputFile = new File(outputDirectory, fileName)
            }
        }
    }

通过上面的代码,我们可以知道,我们可以通过output这个输出流获取到输出的文件名字,通过variant这个变量获取打包的类型等等信息..

问题4:
同样类似于问题1,我在Global中定义了2个变量,一个叫DEBUG(判断是否debug模式,用来打印log的),一个叫SERVER_TYPE(用来连接测试服or正式服),每次打包都要去设置.

buildConfigField这个方法是gradle用来定义变量,最后会生成BuildConfig的一个类,如下:

/**
 * Automatically generated file. DO NOT MODIFY
 */
package cn.bangnijiao.student;

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "cn.bangnijiao.student";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "";
  public static final int VERSION_CODE = 7;
  public static final String VERSION_NAME = "1.1.0";
  // Fields from build type: debug
  public static final boolean LOG_DEBUG = true;
  public static final int SERVER_TYPE = 1;
}

只要在gradle文件的buildTypes标签中加入:
buildConfigField “boolean”, “LOG_DEBUG”, “true”
buildConfigField “int”, “SERVER_TYPE”, “1”
就会对应生成以下变量:
public static final boolean LOG_DEBUG = true;
public static final int SERVER_TYPE = 1;

通过这些问题,又更深的了解gradle的强大之处…. 参考1 参考2 参考3