Archive for August 2010

Solving the Android R.java problem

R.java is one of the most annoying things I’ve come across recently. If you want to create and deploy multiple android apps from the same source, it must be done with each app having a unique package name, and there in lies the rub. A unique package name means a unique R.java with the same package name for each instance, but your source want’s to use a single R.java, and you certainly don’t want to be changing all your source to update the package name every time you release a different version of your app, for example a free trial vs. the paid version.

So the solution is to create two R.java files, one with your internal package name and the other with the package name of the release which comes from AndroidManifest.xml, at this point I would point out that you should probably generate your AndroidManifest.xml.

To generate the required R.java files, you must customize the Google Ant build scripts,  copy android_rules.xml from the SDK into your project. The second exec stanza generates the internal R.java which you specify with the property “package.internal”

<!-- Generates the R.java file for this project's resources. -->
 <target name="-resource-src" depends="-dirs">
 <echo>Generating R.java / Manifest.java from the resources for ${package.destination}</echo>
 <exec executable="${aapt}" failonerror="true">
 <arg value="package" />
 <arg line="${v.option}" />
 <arg value="-m" />
 <arg value="-J" />
 <arg path="${gen.absolute.dir}" />
 <arg value="-M" />
 <arg path="AndroidManifest.xml" />
 <arg value="-S" />
 <arg path="${resource.absolute.dir}" />
 <arg value="-I" />
 <arg path="${android.jar}" />
 <arg value="--custom-package" />
 <arg value="${package.destination}" />
 </exec>

 <echo>Generating R.java / Manifest.java from the resources for ${package.internal}</echo>
 <exec executable="${aapt}" failonerror="true">
 <arg value="package" />
 <arg line="${v.option}" />
 <arg value="-m" />
 <arg value="-J" />
 <arg path="${gen.absolute.dir}" />
 <arg value="-M" />
 <arg path="AndroidManifest.xml" />
 <arg value="-S" />
 <arg path="${resource.absolute.dir}" />
 <arg value="-I" />
 <arg path="${android.jar}" />
 <arg value="--custom-package" />
 <arg value="${package.internal}" />
 </exec>        
 </target>

In your build file, tweak the android setup as follows

<setup import="false" />
<import file="${basedir}/build/android_rules.xml"/>

import false says don’t use the standard android_rules and the following import references your custom rules.

A good reference, but didn’t go far enough: http://java.dzone.com/articles/building-two-versions-same?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed:+javalobby/frontpage+(Javalobby+/+Java+Zone)