Gradle实现编译差异
今天开发组长问了这么一个问题,如何实现通过gradle编译动态设置代码里的一些值。可能这么说不太明白,下面说依稀具体需求。
开发中有两个服务器:一个用于测试版本、一个用于线上版本发布,这两个服务器地址不同。现在想通过在编译版本的时候,不去手动更改服务器地址,而是编译测试版本时,代码中使用的地址就是测试服务地址,编译线上版本时,使用线上服务地址。如何实现? 实现原理和多渠道打包是一样的。下面展示代码:
(1) 在App的AndroidManifest.xml文件中Application节点下添加:
<meta-data android:name="DATA_NAME" android:value="${DATA_NAME_VALUE}" />
(2)在App的build.gradle文件中添加:
defaultConfig {
applicationId "com.gradle.asdemo"
versionCode Integer.parseInt(project.VERSION_CODE)
versionName project.VERSION_NAME
minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK)
targetSdkVersion Integer.parseInt(project.ANDROID_TARGET_SDK_VERSION)
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
manifestPlaceholders = [DATA_NAME_VALUE: "http://www.mamami.com"] //设置默认的值
}
productFlavors {
ol {
manifestPlaceholders = [DATA_NAME_VALUE: "http://www.mamami.com"] //线上服务地址
}
test {
manifestPlaceholders = [DATA_NAME_VALUE: "http://192.168.58.38"] //测试服务地址
}
}
(3) 在代码中获取服务地址的值
public static String getAppMetaData(Context context, String meta_name) { try { ApplicationInfo appInfo = context.getPackageManager() .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); return appInfo.metaData.getString(meta_name); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } return null; } public static String getHost(Context context) { String hostURL = getAppMetaData(context, "DATA_NAME"); if (hostURL != null) { return hostURL; } return DEFUALT_HOST; }
这样在编译时通过选择不同的Flavor就可以动态改变服务地址。这里说一下,在我们平时开发debug开发编译获取到的地址并不是默认值,而是好像在按照Flavor中设置的name的字典顺序拿到的。
(4)可能遇到的问题:Error:(74, 13) Attribute meta-data#xxx@value at AndroidManifest.xml:74:13 requires a placeholder substitution but no value for <YOUMI_CHANNEL_VALUE> is provided
解决方案:(两处取证说明正确)——其实我遇到这个问题不是这个原因,这是意外收获。后续我会说明我的那种情况造成这个问题的原因
http://www.tuicool.com/articles/BRNfeiU
http://stackoverflow.com/questions/37368124/gradle-manifest-requires-a-placeholder-substitution-error-but-manifestplacehol
(5)拓展:
使用manifestPlaceholders的这种配置,同样适用于manifest的其他配置。比如你需要在不同渠道发布的apk里面,指定不同的启动Activity。比如在豌豆荚里面发布的,启动的Activity显示的是豌豆荚首发的界面,应用宝里面启动的是应用宝首发的界面,你就可以对你的activity的值使用${activity_name}的方式,然后在productFlavors里面配置这个${activity_name}的值。
(6)参考:
http://blog.csdn.net/mynameishuangshuai/article/details/51783303
http://blog.csdn.net/maosidiaoxian/article/details/42000913