我希望优化同一Android应用的稍微不同的APK生成,唯一的区别是它正在使用的http API服务器(dev / staging / prod)。
理想情况下,我只想让我的Eclipse构建2个APK,一个使用prod服务器,另一个使用dev服务器。
我有2个运行配置即可,但我无法弄清楚如何将参数传递给应用程序并从代码中读取它们。
我想定位1.5,BTW,我想使用Eclipse自动构建工具,所以我正在寻找最通用的解决方案。
谢谢。
答案 0 :(得分:9)
我认为使用ant build脚本是最简单的解决方案。 Eclipse支持ant build,因此您可以在eclipse中运行ant命令。
你可以像这样解决你的问题。
xml会是这样的:
资源#1:
<resources>
<string name="target">dev</string>
</resources>
资源#2:
<resources>
<string name="target">staging</string>
</resources>
和ant脚本会是这样的:
<project>
<target name="build_all">
<copy file="res1.xml" to="res/values/target.xml"/>
<ant antfile="build.xml" target="debug"/>
<copy file="res2.xml" to="res/values/target.xml"/>
<ant antfile="build.xml" target="debug"/>
</target>
</project>
答案 1 :(得分:4)
将所有代码移到库项目中查看 http://developer.android.com/guide/developing/projects/projects-eclipse.html#SettingUpLibraryProject
然后在eclipse中为测试和生产创建单独的项目,每个项目都有一个唯一的包名。然后,您可以使用包名称来区分版本。
类似的东西:
public static boolean isProductionVersion(){
return context.getPackageName().toLowerCase().contains("production");
}
这对于管理不同的http端点似乎有些过分,但它会使代码更易于管理。您还可以执行以下有用的操作:
这可以在不使用第三方工具的情况下在eclipse中完成。
答案 2 :(得分:1)
它不是你想要的:
private static Boolean isSignedWithDebugKey = null;
protected boolean signedWithDebug() {
if(isSignedWithDebugKey == null) {
PackageManager pm = getPackageManager();
try {
PackageInfo pi = pm.getPackageInfo(getPackageName(), 0);
isSignedWithDebugKey = (pi.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}
catch(NameNotFoundException nnfe) {
nnfe.printStackTrace();
isSignedWithDebugKey = false;
}
}
return isSignedWithDebugKey;
}
如果应用程序使用调试密钥签名,并且使用发布证书生成,则可以访问dev / staging服务器。
答案 3 :(得分:0)
对于传递参数,您总是可以在android的目录系统中创建一个文件,并让您的代码从中读取它。
答案 4 :(得分:0)
在我的情况下,我只是想在不同版本之间更改strings.xml
中的一些值。
首先我必须加载ant-contrib
库,以定义for
循环任务:
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="lib/ant-contrib-1.0b5-SNAPSHOT.jar" />
</classpath>
</taskdef>
我将配置列表config.names
放在properties
文件中:
config.url.root=http://projectserver.aptivate.org/
config.names=student-production, teacher-production, student-testing, teacher-testing
定义一个build-all
目标,该目标循环遍历config.names
:
<target name="build-all">
<for param="config.name" trim="true" list="${config.names}">
<sequential>
为每个目录定义自定义resources
目录,将目录名保存在config.resources
属性中:
<var name="config.resources" unset="true" />
<property name="config.resources" value="bin/res-generated/@{config.name}" />
删除它,并将全局资源从res
复制到其中:
<delete dir="${config.resources}" />
<copy todir="${config.resources}">
<fileset dir="res"/>
</copy>
在配置名称中将-
更改为/
,使其成为URL参数中的路径:
<var name="config.path" unset="true" />
<propertyregex property="config.path"
input="@{config.name}" regexp="-"
replace="/" casesensitive="true" />
运行XSLT转换以修改strings.xml
文件:
<xslt in="res/values/strings.xml"
out="${config.resources}/values/strings.xml"
style="ant/create_xml_configs.xslt"
force="true">
<param name="config.url.root" expression="${config.url.root}" />
<param name="config.name" expression="@{config.name}" />
<param name="config.path" expression="${config.path}" />
</xslt>
这是我使用的XSLT样式表:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="config.url.root" />
<xsl:param name="config.name" />
<xsl:param name="config.path" />
<!-- http://my.safaribooksonline.com/book/xml/9780596527211/creating-output/xslt-id-4.6 -->
<xsl:template match="/">
<!--
This file is automatically generated from res/values/strings.xml
by ant/custom_rules.xml using ant/create_xml_configs.xslt.
Do not modify it by hand; your changes will be overwritten.
-->
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:for-each select="@*">
<xsl:copy/>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<!-- the value of update_server_url must end with a slash! -->
<xsl:template match="string[@name='update_server_url']/text()">
<xsl:value-of select="$config.url.root" /><xsl:value-of select="$config.path" />/
</xsl:template>
<xsl:template match="string[@name='app_version']/text()">
<xsl:value-of select="." />-<xsl:value-of select="$config.name" />
</xsl:template>
</xsl:stylesheet>
然后返回custom_rules.xml
,然后我从原始(未修改)app_version
中提取res/values/strings.xml
:
<xpath input="res/values/strings.xml"
expression="/resources/string[@name='app_version']"
output="resources.strings.app_version" />
并使用antcall
任务调用debug
版本:
<antcall target="debug">
<param name="resource.absolute.dir" value="${config.resources}" />
<param name="out.final.file" value="${out.absolute.dir}/${ant.project.name}-${resources.strings.app_version}-@{config.name}.apk" />
</antcall>
有两个更改的属性值:
resource.absolute.dir
告诉debug
目标使用我在res
属性中定义的修改后的config.resources
目录; out.final.file
告诉它生成一个名称不同的APK,包括配置名称(例如student-testing
)和从strings.xml
中提取的版本号。然后,最后,我可以从命令行运行ant build-all
并构建所有四个目标。在build-all
目标结束之前,稍微多一点的脚本将已编译的APK文件列在一起以供参考:
<echo message="Output packages:" />
<for param="config.name" trim="true" list="${config.names}">
<sequential>
<echo message="${out.absolute.dir}/${ant.project.name}-${resources.strings.app_version}-@{config.name}.apk" />
</sequential>
</for>