What I've come up with: * I have *three* versions -- a dev version, and two release versions (free, pro). This helps keep things straight, and helps ensure that the release ones are built via a common transformation.
* The dev version is what is checked in, and is what I build and test via Eclipse. * The free/pro versions are produced via a master (project- independent) ant script. This script: ** Determines the build number from the highest Subversion version number in {project, common tools (including this build script), third- party (including the SDK)) ** Tags the release-to-be via an Subversion copy operation ** Checks out/cleans+updates, so I have a clean working copy of my new tag. (Doing a clean+copy is faster than a new checkout, but it's just an optimization). ** I export TWO copies of the working copy, one for FREE, one for PRO ** I perform the necessary transformations on each copy (see below) ** I then invoke the project's build script in each of these two copies ** I then copy the results to my build repository (both debug and release versions). The transformations I've found I need are: * Via an XSLT script, I change the package name in the manifest, replacing .dev with .free or .pro * I set android:debuggable="false" * I set the android:versionCode and android:versionName attributes * I set up my project so that I have three packages, each containing classes with the name named in the manifest: ** com.sfsmart.xxx.dev ** com.sfsmart.xxx.free ** com.sfsmart.xxx.pro These are mostsly trivial subclasses of a common abstract base class that provides the base functionality, but I put any code that's specific to another variant in these classes. Thus, when I switch the package in the manifest from, say, com.smfsmart.xxx.dev to com.sfsmart.xxx.pro, it switches classes, and I don't have to do anything complicated to implement the change. * I also make some changes to the metadata in the manifest -- changing somme IDs, etc. that I store there. I could also remove things that aren't used in one version. * I run another XSLT script over my resource .xml files. This one simply substititues the package name in the namespaces of certain elements. I don't know of any case that needs this except references to attributes defined in a declare-stylable. I don't know any way to pin those to a specific package. I thought that aapt's new --custom- package command-line argument would do it, but it didn't seem to. I may try that again, though; I may have had a bug in my XSTL script at the time. But it's only available in the 2.1 version of aapt. Finally, I have to make one change to my project build script. (I'm thinking of injecting this via the master!) The one major fly in the ointment, is that R.java changes packages. My ant script changes its package and moves it back to com.sfsmart.xxx.dev, where it is in the development builds. This could be avoided if --custom-package can be made to work; I plan to look into this further. The result is that the code doesn't have to change at all. The resources change very slightly, though I'm looking for a solution there. Each product runs the exact same .java (but not the same code paths). The differences are all driven by the manifest changes. I haven't done it yet, but I plan to make the .dev version launch either the .free or the .pro version, based on a dev-only setting. This way, I can easily develop both versions of the application. A final optimization would be to use Proguard to eliminate classes which aren't used by one version or the other. In my case, the differences are small. Similarly, the configure step could remove assets or resources which aren't used in one or the other version. Unlike using Proguard on classes, this wouldn't be based on direct dependency analysis (though you COULD do it!), so should be approached with a bit of caution. If you have a lot of graphic assets, though, it may be worth doing. Here's a sanitized version of the script I use to adjust the manifest: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:android='http://schemas.android.com/apk/res/android' > <xd:doc xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" scope="stylesheet"> <xd:desc> <xd:p><xd:b>Created on:</xd:b> Feb 24, 2010</xd:p> <xd:p><xd:b>Author:</xd:b> Bob Kerns</xd:p> <xd:p></xd:p> </xd:desc> </xd:doc> <xsl:param name="VERSION"/> <xsl:param name="VERSION_EXTRA" select="''"/> <xsl:param name="BUILDTYPE" select="'PRO'"/> <xsl:output indent="no"/> <xsl:template match="/"> <xsl:text> </xsl:text> <xsl:apply-templates select="@*|node()"/> </xsl:template> <!-- Set the version code to be the supplied version number (derived from the Subversion revision number). --> <xsl:template match="/manifest/@android:versionCode"> <xsl:attribute name="android:versionCode"><xsl:value-of select="$VERSION"/></xsl:attribute> </xsl:template> <!-- Generate the android:versionName attribute, using the existing value as a prototype but filling in the build number --> <xsl:template match="/manifest/@android:versionName"> <xsl:variable name="major"><xsl:value-of select="substring- before(., '.')"/></xsl:variable> <xsl:variable name="minorRest"><xsl:value-of select="substring- after(., concat($major, '.'))"/></xsl:variable> <xsl:variable name="minor"><xsl:value-of select="substring- before($minorRest, '.')"/></xsl:variable> <!-- $extra picks up the value of $VERSION_EXTRA, with a prepended space if that's not empty. --> <xsl:variable name="extra"> <xsl:if test="$VERSION_EXTRA"> <xsl:text> </xsl:text> </xsl:if> <xsl:value-of select="$VERSION_EXTRA"/> </xsl:variable> <!-- The final value for android:versionName --> <xsl:variable name="versionName"> <xsl:value-of select="concat($major, '.', $minor, '.', $VERSION, $extra)"/> </xsl:variable> <xsl:attribute name="android:versionName"><xsl:value-of select="$versionName"/></xsl:attribute> </xsl:template> <!-- Switch the package name --> <xsl:template match="/manifest/@package"> <xsl:attribute name="package"> <xsl:value-of select="substring(., 1, string-length(.)-3)"/ > <xsl:choose> <xsl:when test="$BUILDTYPE='PRO'">pro</xsl:when> <xsl:when test="$BUILDTYPE='FREE'">free</xsl:when> <xsl:otherwise><xsl:message>Incorrect build type: <xsl:value-of select="$BUILDTYPE"/></xsl:message><xsl:value-of select="$BUILDTYPE"/></xsl:otherwise> </xsl:choose> </xsl:attribute> </xsl:template> <!-- Always turn off android:debuggable in the product builds --> <xsl:template match="/manifest/application/@android:debuggable"> <xsl:attribute name="android:debuggable">false</xsl:attribute> </xsl:template> <!-- Get rid of the ADMOB_PUBLISH_ID if we're not the FREE version --> <xsl:template match="/manifest/application/meta- da...@android:name='ADMOB_PUBLISHER_ID']"> <xsl:if test="$BUILDTYPE = 'FREE'"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:if> </xsl:template> <!-- Add an additional meta-data element if we're the PRO version --> <xsl:template match="/manifest/application"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <xsl:if test="$BUILDTYPE = 'PRO'"> <meta-data android:value="true" android:name="paid"/> </xsl:if> </xsl:copy> </xsl:template> <!-- Identity transform - copy everything else verbatim! --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> (BTW, I recommend the <Oxygen/> XML for developing and testing stuff like this; it makes it very easy to do). On Feb 26, 9:39 am, Moto <medicalsou...@gmail.com> wrote: > I would like to make my life easier by having one common code base for > my service for both paid and free apps. I want to eliminate the > complex merging I find my self doing every time I need to release! > > As of now I had to change the service file name along with the Remote > service aidl calls. > > Please any advice would be helpful! > > -Moto! -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en