2010-10-21 98 views
22

我正在寻找优化同一Android应用程序的稍微不同的APK的生成,唯一的区别是它使用的http API服务器(dev/staging/prod) 。在Eclipse中构建多个Android APK的版本

理想情况下,我只想让我的Eclipse构建2个APK,其中一个带有prod服务器,另一个带有dev设备。

我甚至可以拥有2个运行配置,但我一直无法弄清楚如何将参数传递给应用程序并从代码中读取它们。

我想定位1.5,顺便说一句,我想使用Eclipse自动生成工具,所以我正在寻找最通用的解决方案。

谢谢。

+0

的可能重复[Android的 - 同一应用程序的多个定制版(HTTP://计算器问题/ 1222302/android - 多个定制版本的同一应用程序) – EboMike 2010-10-21 00:57:01

+0

就我所知,没有任何解决方案与Eclipse很好地集成。对于为什么这样一个简单的任务似乎如此复杂,我其实很难过。不要开始火焰战争,但我已经看过了我们的iPhone开发者的iPhone开发环境,从外部传递params到你的应用程序是非常简单的。这让我难过。 – 2010-10-21 01:07:10

+0

我知道如何用maven-android-plugin来做到这一点,其实很简单。然而,它需要将你的应用程序与maven绑定,此外,在maven-android-plugin/m2e-android中似乎与最新的Android SDK(r14和r15)有一些不兼容,可能不是你想要的。 – yorkw 2011-11-02 09:01:02

回答

0

对于传递参数,你总是可以在android的目录系统中创建一个文件并让你的代码读取它。

+1

但是,您如何将文件名参数传递给代码?如果我可以传递一个文件名,我也可以传递一个服务器URL - 问题是如何。 – 2011-11-03 05:52:50

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; 
    } 

然后,您可以打一个开发/分期服务器,如果应用程序与调试的关键,并与释放证明的生产签署。

+0

这仍然生成1个文件 - 我希望Eclipse能够构建2(或N)个文件并创建多个配置,以便轻松构建分段,开发等。 – 2011-11-03 05:54:48

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上做无需使用第三方工具。

+0

这听起来像是我对版本控制的噩梦,每个文件的顶部。我错了吗? – 2011-11-03 05:56:34

+0

版本控制没有问题。软件包名称在清单中设置一次,所有代码保留在库项目中。 – railwayparade 2011-11-03 07:42:25

+0

在我的代码中,包名称出现在每个Java文件中。 – 2011-11-03 20:03:08

9

我认为使用ant构建脚本将是最简单的解决方案。 Eclipse支持ant构建,所以你可以在eclipse中运行ant命令。

你可以像这样解决你的问题。

  1. 准备两个xml的android资源文件。
  2. 建立与资源#封装1
  3. 重写资源#1的资源#2
  4. 构建另一个包

xml内容会是这样:

资源#1:

<resources> 
    <string name="target">dev</string> 
</resources> 

res乌尔斯河#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> 
+0

现在看起来我们正在某处。您可以请进一步说明如何在Eclipse中进行设置? – 2011-11-04 16:45:57

+0

看到这个:[Ant support](http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.user%2Fconcepts%2Fconcepts-antsupport.htm) - 1. create新的ant构建文件/ 2.在eclipse中打开ant视图/ 3.将你的ant构建添加到视图(拖放)/ 4.运行它。 – kingori 2011-11-05 03:24:57

+0

小心:android需要ant 1.8或更高版本。 eclipse内置了ant,但它的版本是1.7。您应该手动安装ant,然后在eclipse属性中将您的ant二进制文件设置为默认的ant二进制文件。 – kingori 2011-11-05 03:26:38

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}[email protected]{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}[email protected]{config.name}.apk" /> 
    </sequential> 
</for>