aapt basename attribute - android

I upgraded my SDK to 2.3 and my build scripts start to fail. I am getting this error:
build.xml:363: aaptexec doesn't support the "basename" attribute
For the following line in my build script:
<aapt executable="${aapt}" command="package" manifest="AndroidManifest.xml" resources="${resource.absolute.dir}" assets="${asset.absolute.dir}" androidjar="${android.jar}" outfolder="${out.absolute.dir}" basename="${ant.project.name}" />
I do not know what changed in aapt but apparently basename is not there any more. Can you tell me what should I use instead?

I had similar problems when upgrading from 2.1 to 2.3 with symbolic names changing in the built in 'rules' xmls. 2.1 seemed to use ant_rules_3.xml, now SDK 2.3 uses main_rules.xml as its starting point. If, like me, you had customised your build.xml based on the targets in the rules file, you will probably find it easier to start again by creating a sample project as described in : link text
then adapting you build.xml to override some or all of the targets that are listed in main_rules.xml. (This is in the sdk\tools\ant folder). I found this process to be reasonably quick, and for simple projects the generated files worked 'out of the box' with Ant. (I did have to change the build.xml a lot for a project which contained a second source folder containing .aidl files, as the main_rules.xml couldn't cope with it)
There are two targets which refer to aapt in the main_rules.xml, it's probably this one that you need to mimic:
<target name="-package-resources">
<echo>Packaging resources</echo>
<aapt executable="${aapt}"
command="package"
versioncode="${version.code}"
debug="${build.packaging.debug}"
manifest="AndroidManifest.xml"
assets="${asset.absolute.dir}"
androidjar="${android.jar}"
apkfolder="${out.absolute.dir}"
resourcefilename="${resource.package.file.name}"
resourcefilter="${aapt.resource.filter}">
<res path="${resource.absolute.dir}" />
<!-- <nocompress /> forces no compression on any files in assets or res/raw -->
<!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
</aapt>
</target>
I think the resourcefilename is the name of the generated apk. My build scripts generate the apks and put them in the bin directory OK, without my naming the resourcefilename explicitly.
My build.properties looks like:
#-----------------------------------------------
# The ONLY reference to the project's main base
#
projectname=MapProject1.2
#
#-----------------------------------------------
workspace.dir=/dev/projects/EclipseHelios/AndroidWorkspace
ant.project.name=${projectname}
outbasebase.dir=/dev/projects/AntBuilds
base.dir=${workspace.dir}/${projectname}
common_src=/dev/projects/CommonSource121210/GridSeviceAndUseGridService
source.dir=${base.dir}/src
outbase.dir=${outbasebase.dir}/${projectname}
out.dir=${outbase.dir}/bin
key.store=c:/users/me/my-release-key.keystore
key.alias=release_alias
key.store.password=*************
key.alias.password=*************
layout.dir=${base.dir}/res/layout
(Apart from the passwords of course!)
I did comment out the projectname in the buid.xml, so that it would pick it up from the build.properties.

Related

Generating android code coverage though changes in build.xml and ant.properties

I have been trying to generate android code coverage for my android test project which tests a android project which includes a external jar. When I run command
ant emma install debug test
it shows coverage of only the android project but does not include the package and functions of the external jar included.
As per my researches I have found that some changes should be done in ant.properties file and emma report tag in build.xml.
Any suggestions are most welcome.
[Edit]
On furthur study, I went through a blog which says enter the variable
tested.android.library.source.dir="path to external jars" in ant.properties
and same variable should be added in report sourcepath as
<emma>
<report sourcepath="${tested.project.source.absolute.dir}:${tested.project.lib.source.path.value}:${tested.android.library.source.dir}" verbosity="${verbosity}">
<!-- TODO: report.dir or something like should be introduced if necessary -->
<infileset file="${out.absolute.dir}/coverage.ec" />
<infileset file="${tested.project.out.absolute.dir}/coverage.em" />
<!-- TODO: reports in other, indicated by user formats -->
<html outfile="${out.absolute.dir}/coverage.html" />
</report>
</emma>
But still the coverage is not showing functions and package of External jar.
I wanted to know that my jars are not in the android test project but in the android project which is tested. So how to give path to those external jars in ant.properties of the test project.
I am also working on the same from quite some time.
Refer to code coverage reports for library projects
External jars coverage support is in ADT-r20.
I can only point to the direction I am working.
I am working on modifying build.xml inside ant :
<!-- This is macro that enable passing variable list of external jar files to ApkBuilder
Example of use:
<package-helper>
<extra-jars>
<jarfolder path="my_jars" />
<jarfile path="foo/bar.jar" />
<jarfolder path="your_jars" />
</extra-jars>
</package-helper> -->
<macrodef name="package-helper">
<element name="extra-jars" optional="yes" />
<sequential>
<apkbuilder
outfolder="${out.absolute.dir}"
resourcefile="${resource.package.file.name}"
apkfilepath="${out.packaged.file}"
debugpackaging="${build.is.packaging.debug}"
debugsigning="${build.is.signing.debug}"
verbose="${verbose}"
hascode="${manifest.hasCode}"
previousBuildType="${build.last.is.packaging.debug}/${build.last.is.signing.debug}"
buildType="${build.is.packaging.debug}/${build.is.signing.debug}">
<dex path="${intermediate.dex.file}"/>
<sourcefolder path="${source.absolute.dir}"/>
<jarfile refid="project.all.jars.path" />
<nativefolder path="${native.libs.absolute.dir}" />
<nativefolder refid="project.library.native.folder.path" />
<extra-jars/>
</apkbuilder>
</sequential>
</macrodef>
I have no luck till yet.
After lots of searching and trying , finally got the package of my External jar in my Main project.
Just entered tested.android.library.source.dir in ant.properties and build.xml
ant.properties: tested.android.library.source.dir="Path to libs folder of main project where jars are present"
Build.xml : Under emma tag in report tag add this variable seperated by colon.
Now go to command prompt and run
In Main Project :android update project -p .
In Test Project: android update test-project -m "Path of main project" -p .
Now copy test target from build.xml (sdk/tools/ant/build.xml) and paste it in build.xml of test project above the line
<import file="${sdk.dir}/tools/ant/build.xml" />
Dont Forget to Change Version Tag to
Now Again open command prompt and run:
In Main Project: ant emma debug install
In Test Project: ant emma debug install test
Your Code coverage report generated will contain the package of the external jar
I struggled with this for 2 days and eventually figured it out. The code snippet in the first post only generates instrument report from emma metadatafile and runtime coverage file but does not perform instrumentation on jar. To instrument the code you will have to manipulate the byte code, like how android ant build.xml target does it. Take a look at the element nested in <-compile> and you will see comment like it is only instrumenting class files. To instrument the jars add a classpath like element to the jars along with path to class.
Emma Documentation: http://emma.sourceforge.net/reference/ch02s03s02.html
<emma enabled="${emma.enabled}" >
<instr mode="fullcopy"
outdir="${out.instr.dir}"
merge="no"
filter="${emma.filter}">
<instrpath>
<fileset dir="${out.dir}" includes="**/*.jar" />
</instrpath>
</instr>
</emma>
In Android's build.xml. One just have to delete instrpath attribute and make it look like the example above.
756 <emma enabled="true">
757 <instr verbosity="${verbosity}"
758 mode="overwrite"
759 instrpath="${out.absolute.dir}/classes"
760 outdir="${out.absolute.dir}/classes"
761 metadatafile="${emma.coverage.absolute.file}">
762 <filter excludes="${emma.default.filter}" />
763 <filter value="${emma.filter}" />
764 </instr>
765 </emma>
So something like this: (pardon the line#s)
756 <emma enabled="true">
757 <instr verbosity="${verbosity}"
758 mode="overwrite"
760 outdir="${out.absolute.dir}/classes"
761 metadatafile="${emma.coverage.absolute.file}">
759 <instrpath>
759 <pathelement path="${out.absolute.dir}/classes"/>
759 <fileset dir="${you-class-path}"/>
759 <include name="**/*.jar"/>
759 </fileset>
759 </instrpath>
762 <filter excludes="${emma.default.filter}" />
763 <filter value="${emma.filter}" />
764 </instr>
765 </emma>

How to Automatically Modify versionName in Manifest during Build?

So far I have been focusing on my application's programming and paid little attention to making the build process smarter. Thus I have been doing things pretty much manually (the "dumb way"), including updating by hand android:versionCode and android:versionName in AndroidManifest.xml.
I would like now to automatically (i.e. upon Build or upon Export):
Fetch from git the latest tag/branch containing build and version codes.
Parse them so that I can assign them to the respective fields in AndroidManifest.xml.
Modify AndroidManifest.xml accordingly.
Proceed with the normal build process (Eclipse+ADT, no Ant whatsoever), as if I did 1-2-3 by hand...
I found a few clues about a "pre-build step", builders and build.xml, but I have no idea where to find those and where to start.
Any tips or pointers on where I could find more information on the subject? (a step-by-step tutorial would be ideal)
Update 1: I found this thread to be suggesting that I:
Right-click on the project, Properties > Builders
Add a builder that points to the project's Ant build file.
Order that builder to be invoked before the Java builder
Fine, but where is the project's Ant build file? Where do I find it?
Update 2: Apparently, it's possible to export the entire project into an Ant file. But I am not sure that's I want. Must a pre-build step always include an Ant build file?
Update 3: Is building an Ant file, only for the pre-build step, the right approach?
Here's what I use to dynamically assign a versionCode and versionName to AndroidManifest.xml. It works only when building with ant, so you'll have to install it first. Then go to the project directory in your command line and execute "android update project -p .", which will create the necessary files for building with ant, like local.properties and build.xml.
Then open build.xml and place this inside:
<target name="-pre-build" depends="-custom-git-version,-custom-manifest-version">
</target>
<!-- Packages the application. -->
<target name="-post-build">
<antcall target="-custom-restore-manifest"/>
<property name="suffix" value="${git.commits}-${git.version}.apk" />
<exec executable="sed" inputstring="${out.final.file}" outputproperty="out.final.renamedfile">
<arg value="s/\.apk/-${suffix}/" />
</exec>
<copy file="${out.final.file}" tofile="${out.final.renamedfile}" />
<echo>Final file copied to: ${out.final.renamedfile}</echo>
</target>
<!-- Custom targets -->
<target name="-custom-git-version">
<exec executable="sh" outputproperty="git.commits">
<arg value="-c" />
<arg value="git log --pretty=format:'' | wc -l" />
</exec>
<echo>git.commits: ${git.commits}</echo>
<exec executable="git" outputproperty="git.version">
<arg value="describe" />
<arg value="--tags" />
<arg value="--long" />
</exec>
<echo>git.version: ${git.version}</echo>
</target>
<target name="-custom-manifest-version">
<echo>Creating backup of AndroidManifest.xml</echo>
<copy file="AndroidManifest.xml" tofile="AndroidManifest.xml.antbak" preservelastmodified="true" />
<replaceregexp
file="AndroidManifest.xml"
match='android:versionCode="(\d+)"'
replace='android:versionCode="${git.commits}"' />
<replaceregexp
file="AndroidManifest.xml"
match='android:versionName="(\d+\.\d+)\.\d+"'
replace='android:versionName="\1.${git.commits}"' />
</target>
<target name="-custom-restore-manifest">
<echo>Restoring backup of AndroidManifest.xml</echo>
<move file="AndroidManifest.xml.antbak"
tofile="AndroidManifest.xml"
preservelastmodified="true"
overwrite="true" />
</target>
The output of this is not exactly what you want, but it is a start - feel free to modify it :) The result is something like "yourapp--.apk
Using this you'll build your application with executing "ant clean debug", or "ant clean release", depending on what you want. You can also create "ant.properties" file with this content:
key.store=keystore_file
key.store.password=some_password
key.alias=some_alias
key.alias.password=some_other_password
to enable automatic signing of your app.
You should also read this: http://developer.android.com/tools/building/building-cmdline.html
You are on the right track with setting up a pre-build step, but the ant build file is something you'll create yourself from scratch. Eclipse has some ant scripts that it uses externally that handle the automated compilation, packaging and stuff, but you want to create a separate one that just does these extra steps you want.
So, you're going to have to learn a bit about ant scripting to get this done. Some of those links you found give you the basic idea of how to create a simple ant file. To add to that, some of the ant tasks you will probably need to use are:
Exec - You will need this to execute your git command that gets your version info. It has an argument called resultProperty you can use to store the output of the command into a property that ant can access. (or you can just have the command output to a file and ant can access that.)
ReplaceRegExp - You will need this to replace tokens (maybe #VERSIONCODE# and #VERSIONNAME# ) you place in your AndroidManifest.xml where the values should eventually go, with the values returned by the exec.
You will probably also want to execute an exec task at the beginning to restore your AndroidManifest.xml file to it's original state (with the tokens in place) so it's repeatable without manual cleanup. I would provide more info on the git commands you need to run within these exec tasks, but I'm afraid all my experience is with Subversion, so you'll have to fill in the gaps there.
You should consider building with maven-android. Once you have your project building cleanly, use the version-update plugin to automatically increment your version number.
Writing a build script with maven-android can't be described as easy - but the payoff is worth the effort and you should consider this avenue.
Also, this tutorial might come in handy (I use a variant of the technique described here for my own builds)
EDIT (2014):
Consider migrating to Android Studio and using Gradle. See: How to autoincrement versionCode in Android Gradle
The way I managed to achieve this: build > execute shell (we needed some php code to receive some info from a db) and the string replacement happens in php:
#!/usr/bin/php
<?php
$filename = $WORKSPACE."/src/com/me/myapp/MyActivity.java";
$file = #file_get_contents($filename);
if($file) {
$repl = preg_replace("OriginalString", "NewString", $file);
file_put_contents($filename, $repl);
echo "\n\nReplaced some stuff in $filename";
}
?>

jar-Binding of ActionBarSherlock for Mono for Android

I'like to bind the jar-library of ActionBarSherlock in my Mono For Android project. I am reverencing to this documentation: http://docs.xamarin.com/android/tutorials/Binding_a_Java_Library_(.jar)
I have successfully bound android-support-v4.jar which is needed by ActionBarSherlock. But when I try to compile actionbarsherlock.jar, it gives me the following error message:
Target ResolveLibraryProjects:
Skipping target "ResolveLibraryProjects" because it has no inputs.
Target _ResolveMonoAndroidSdks:
MonoAndroid Tools: C:\Program Files (x86)\MSBuild\Novell\
MonoAndroid Framework: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v2.2\;C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v1.0\
Android SDK: C:\Program Files (x86)\Android\android-sdk\
Java SDK: C:\Program Files (x86)\Java\jdk1.6.0_31\
Target ExportJarToXml:
SourceJars:
Jars\actionbarsherlock.jar
ReferenceJars:
Jars\android-support-v4.jar
C:\Program Files (x86)\Java\jdk1.6.0_31\bin\java.exe -jar "C:\Program Files (x86)\MSBuild\Novell\jar2xml.jar" --jar=C:\Users\assrock\Documents\JavaBind\JavaBind\Jars\actionbarsherlock.jar --ref="C:\Program Files (x86)\Android\android-sdk\platforms\android-8\android.jar" --out=C:\Users\assrock\Documents\JavaBind\JavaBind\obj\Release\api.xml --ref=C:\Users\assrock\Documents\JavaBind\JavaBind\Jars\android-support-v4.jar
Couldn't load class com/actionbarsherlock/internal/ActionBarSherlockNative$ActionModeCallbackWrapper
Couldn't load class com/actionbarsherlock/internal/app/ActionBarWrapper$TabWrapper
Couldn't load class com/actionbarsherlock/internal/app/ActionBarWrapper
Couldn't load class com/actionbarsherlock/internal/view/ActionProviderWrapper
Couldn't load class com/actionbarsherlock/internal/view/menu/MenuItemWrapper$1
Exception in thread "main" java.lang.NoClassDefFoundError: com/actionbarsherlock/R
at java.lang.Class.getDeclaringClass(Native Method)
at jar2xml.JavaClass.getConstructorParameterOffset(JavaClass.java:149)
at jar2xml.JavaClass.appendCtor(JavaClass.java:138)
at jar2xml.JavaClass.appendToDocument(JavaClass.java:462)
at jar2xml.JavaPackage.appendToDocument(JavaPackage.java:66)
at jar2xml.Start.main(Start.java:157)
Caused by: java.lang.ClassNotFoundException: com.actionbarsherlock.R
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
... 6 more
C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets(170,5): error MSB6006: "java.exe" exited with code 1.
Task "JarToXml" execution -- FAILED
Done building target "ExportJarToXml" in project "C:\Users\assrock\Documents\JavaBind\JavaBind\JavaBind.csproj".-- FAILED
Done building project "C:\Users\assrock\Documents\JavaBind\JavaBind\JavaBind.csproj".-- FAILED
Build FAILED.
Warnings:
C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets(40,11): warning MSB4011: There is a circular reference involving the import of file "c:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.Targets". This file may have been imported more than once, or you may have attempted to import the main project file. All except the first instance of this file will be ignored.
Errors:
C:\Users\assrock\Documents\JavaBind\JavaBind\JavaBind.csproj (Build) ->
C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets (ExportJarToXml target) ->
C:\Program Files (x86)\MSBuild\Novell\Xamarin.Android.Bindings.targets(170,5): error MSB6006: "java.exe" exited with code 1.
1 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.4730270
--------------------- Fertig ---------------------
Build: 1 Fehler, 0 Warnungen
For the android-support-v4.jar I found these xml-files and put them in the Transforms directory:
EnumFields.xml
<enum-field-mappings>
<mapping jni-class="android/support/v4/app/FragmentActivity$FragmentTag" clr-enum-type="Android.Support.V4.App.FragmentTagType">
<field jni-name="Fragment_id" clr-name="Id" value="1" />
<field jni-name="Fragment_name" clr-name="Name" value="0" />
<field jni-name="Fragment_tag" clr-name="Tag" value="2" />
</mapping>
</enum-field-mappings>
EnumMethods.xml
<enum-method-mappings>
<mapping jni-class="android/support/v4/app/Fragment$SavedState">
<method jni-name="writeToParcel" parameter="p1" clr-enum-type="Android.OS.ParcelableWriteFlags" />
<method jni-name="writeToParcel" parameter="flags" clr-enum-type="Android.OS.ParcelableWriteFlags" />
</mapping>
</enum-method-mappings>
Metadata.xml
<metadata>
<remove-node path="/api/package[#name='android.support.v4.app']/class[#name='BackStackState']" />
<remove-node path="/api/package[#name='android.support.v4.app']/class[#name='FragmentState']" />
<remove-node path="/api/package[#name='android.support.v4.app']/class[#name='FragmentManagerState']" />
<remove-node path="/api/package[#name='android.support.v4.widget']/class[#name='CursorAdapter']/implements[#name='android.support.v4.widget.CursorFilter.CursorFilterClient']" />
<remove-node path="/api/package[#name='android.support.v4.widget']/class[#name='CursorAdapter']/field[#name='mCursorFilter']" />
<remove-node path="/api/package[#name='android.support.v4.content']/class[#name='AsyncTaskLoader.LoadTask']" />
<!-- FIXME:
This method is an override of another method in the base types.
The base method expects JLO, but this method returns Cursor.
So we somehow have to fill the gap between them.
-->
<remove-node path="/api/package[#name='android.support.v4.content']/class[#name='CursorLoader']/method[#name='loadInBackground']" />
<remove-node path="/api/package[#name='android.support.v4.view.accessibility']/class[#name='AccessibilityNodeInfoCompat.AccessibilityNodeInfoIcsImpl']" />
<remove-node path="/api/package[#name='android.support.v4.widget']/class[#name='CursorAdapter.ChangeObserver']" />
<remove-node path="/api/package[#name='android.support.v4.view.accessibility']/class[#name='AccessibilityNodeInfoCompat.AccessibilityNodeInfoIcsImpl']" />
<remove-node path="/api/package[#name='android.support.v4.view.accessibility']/class[#name='AccessibilityNodeInfoCompat.AccessibilityNodeInfoStubImpl']" />
<remove-node path="/api/package[#name='android.support.v4.view']/interface[#name='ViewPager.OnAdapterChangeListener']" />
<attr path="/api/package[#name='android.support.v4.app']/class[#name='LoaderManager']/method[#name='initLoader']/parameter[#name='p2']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
<attr path="/api/package[#name='android.support.v4.app']/class[#name='LoaderManager']/method[#name='initLoader']/parameter[#name='callback']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
<attr path="/api/package[#name='android.support.v4.app']/class[#name='LoaderManager']/method[#name='initLoader']" name="return">android.support.v4.content.Loader</attr>
<attr path="/api/package[#name='android.support.v4.app']/class[#name='LoaderManager']/method[#name='restartLoader']/parameter[#name='p2']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
<attr path="/api/package[#name='android.support.v4.app']/class[#name='LoaderManager']/method[#name='restartLoader']/parameter[#name='callback']" name="type">android.support.v4.app.LoaderManager.LoaderCallbacks</attr>
<attr path="/api/package[#name='android.support.v4.app']/class[#name='LoaderManager']/method[#name='restartLoader']" name="return">android.support.v4.content.Loader</attr>
</metadata>
ActionBarSherlock includes UI elements, styles, and other things that can't be compiled into a JAR file. There is a note about this on the ActionBarSherlock FAQ.
Q: Why is ActionBarSherlock a library project whereas the original compatibility library is only a .jar?
A: The custom action bar implementation within ActionBarSherlock relies on styles, themes, layouts, and drawables in order to display properly. Due to the limitations of Android and .jar files, this currently can not be accomplished any other way.
Edit: There is some additional information about trying to share resources across library projects in Mono for Android at this link: http://mono-for-android.1047100.n5.nabble.com/Resources-from-a-Library-Project-td4657828.html. Short answer is it doesn't look possible at the moment.
I believe I have successfully bound ActionBarSherlock in Mono for Android.
You need to package the java files as a JAR file but without the resources and without the R java class files. Before you package the files make sure that you check the box in Android settings that says "Is Library" so that the resource IDs are not created as constants and inlined in your compiled java classes.
Once you have done this you can use the latest version of Mono for Android to bind the JAR file.
Resources need to be copied separately from the JAR file and placed directly in the main android application project. Unfortunately, at the present time there is no way to isolate the resources in a separate library project when using Mono for Android, but I expect that will change soon.
Finally, you need to edit your C-Sharp project file so that it automatically creates a new version of the com.actionbarsherlock.R java class file each time you rebuild. This is required to keep all your resource IDs in sync.
I may have missed a step or two but those are the most important ones.
Please see my blog post for more information and a download link with source code:
http://www.craigsprogramming.com/2012/07/actionbarsherlock-with-mono-for-android.html
This may seem like a sledgehammer approach, but will likely solve your problem...
I would suggest building using Maven, which handles these dependencies much better. You will be able to reference the ActionBarSherlock project in your POM, and MVN will manage the dependancies for you.
I can confirm the original answer as correct as well - there is a limitation to including JAR files that contain layout resources.
Looks like Xamarin solved ActionBarSherlock bound issue
https://bugzilla.xamarin.com/show_bug.cgi?id=6186
This fix has included in 4.2.5 which is available on alpha channel now.

Android - How do I dynamically set the package name at build time for an Open-source project?

I'm working on an Open-source project. As it is intended that anyone can download the source and build it themselves, I do not want to hard-code the package name anywhere - including the directory structure.
I use ant for building. Apparently I can modify build.xml, but I believe this is overwritten by android update. Whatever is used will be committed to the Git repo, and it should not be too complicated.
Currently the process to build the code straight from the Git repo is fairly simple. Here's an excerpt from the README file:
$ cd ~/src/isokeys/IsoKeys
$ android list targets # I build against API level 10.
$ android update project --name IsoKeys --target 1 --path ./ # Only needed first time.
$ ant debug && adb -d install -r bin/IsoKeys-debug.apk
To me, it makes sense to put the package name in local.properties, because this is .gitignore'd. As the package name won't be anywhere else, the build will fail without doing this. So there needs to be at least 1 extra step in the README, but I want to keep it to a minimum.
Edit: Of course, another requirement is that diffs make sense - which they don't if you manually rename the package name.
I did something similar (but not for this reason) which required updating the manifest at build time. The way I accomplished this was by making a second AndroidManifest and putting it under a directory named config.
So in config/AndroidManifest you could have something like this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="#CONFIG.APP_PACKAGE_NAME#"
android:versionCode="#CONFIG.APP_VERSION_CODE#"
android:versionName="#CONFIG.APP_VERSION#">
<!-- EVERYTHING ELSE GOES HERE -->
</manifest>
Then you can use the regular bare bones build.xml ant script with just a few modifications (no need to copy the whole script from the android build system as they added some hooks for you to use without reinventing the wheel).
The build script should be reading local.properties by default, but if not add (or uncomment) a line like this:
<property file="local.properties" />
In your build script you should see a task called "-pre-build", change it like this:
<target name="-pre-build">
<copy file="config/AndroidManifest.xml" todir="." overwrite="true" encoding="utf-8">
<filterset>
<filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" />
<filter token="CONFIG.APP_VERSION" value="${app.version}" />
<filter token="CONFIG.APP_VERSION_CODE" value="${app.versioncode}" />
</filterset>
</copy>
</target>
Then your local.properties file you would put the package name, version name/code like so:
app.version=1.0
app.versioncode=1
app.packagename=com.mypackage.name
Now you just need to make sure in your manifest that you fully qualify all of your activities/services/broadcast listeners etc.. That means you always specify the full package of your source code. If you want the package for your own source code to be dynamic you could replace out each of the prefixes to each class.. But that seems kind of silly.. It is easy enough to package your code up under your own package name and they can use it from any project by simply including the source or a jar in their project.
-- UPDATE --
Oh and one other thing you can do to notify the user that they must define a package name is use the fail tag in your build xml like this:
<fail message="app.packagename is missing. This must be defined in your local.properties file" unless="app.packagename" />
Put this after the line which reads the local.properties file
With thanks to Matt Wolfe for his help, I'm posting a partial answer with my efforts so far.
I noticed that the default barebones build.xml would also import custom_rules.xml:
<import file="custom_rules.xml" optional="true" />
So I created this file and started tinkering. This is what I have come up with so far:
<?xml version="1.0" encoding="UTF-8"?>
<project name="custom_rules" default="debug">
<target name="-pre-build">
<fail message="Please define app.packagename in your local.properties file." unless="app.packagename" />
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/ant-contrib.jar"/>
</classpath>
</taskdef>
<!-- How do I check for propertyregex?
<fail message="Depends on ant-contrib's propertyregex for app.packagename.path." unless="propertyregex" />
-->
<propertyregex property="app.packagename.path"
input="${app.packagename}/"
regexp="\."
replace="/"
global="true"
/>
<copy todir="build/" overwrite="true" encoding="utf-8">
<fileset dir="./">
<include name="AndroidManifest.xml" />
<include name="res/**" />
<include name="lib/**" />
</fileset>
<filterset>
<filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" />
</filterset>
</copy>
<copy todir="build/src/${app.packagename.path}" overwrite="true" encoding="utf-8">
<fileset dir="./src/isokeys/">
<include name="**" />
</fileset>
<filterset>
<filter token="CONFIG.APP_PACKAGE_NAME" value="${app.packagename}" />
</filterset>
</copy>
</target>
<target name="-pre-clean" description="Removes output files created by -pre-build.">
<delete file="build/AndroidManifest.xml" verbose="${verbose}" />
<delete dir="build/res/" verbose="${verbose}" />
<delete dir="build/lib/" verbose="${verbose}" />
<delete dir="build/src/" verbose="${verbose}" />
</target>
<!-- NOW CHANGE DIRECTORY TO build/ BEFORE HANDING BACK OVER TO build.xml!!! -->
</project>
This sets everything up in build/ (which has the added bonus of keeping things neat and tidy), now the intention is for the sdk tools build.xml to run from this build/ directory. However, I can't find any way of cd'ing.
Easiest way might be replace the package name as late as possible. This way, you don't even have to touch your code. There is a nice article named Renaming the Android Manifest package(http://www.piwai.info/renaming-android-manifest-package/). Summary:
You can use aapt --rename-manifest-package to modify the package name
Alternatively, if you want package name replacement to be a part of the ant build process, you can override the -package-resources target:
copy the -package-resources target from SDK's build.xml
add manifestpackage parameter

Error with build.xml for unrecognized directories in res/

I am trying to port an existing C++ app to android using JNI. However, after generating the Build.xml file from the AndroidManifest.xml and attempting to build with it, I get the following (relevant) output:
[aapt] Generating resource IDs...
[aapt] invalid resource directory name: /{Project Directory}/res/audio
[aapt] invalid resource directory name: /{Project Directory}/res/img
BUILD FAILED
/{Android SDK Dir}/tools/ant/build.xml:560: The following error occurred while executing this line:
/{Android SDK Dir}/tools/ant/build.xml:589: null returned: 1
These are existing directories in a directory already named "res" by coincidence, not meant to have a semantic meaning for Java. If I remove those from res/ then it builds just fine. So my question is-- what is the best way to organize this (or tell ant to ignore unrecognized directories)? Res is already a very large directory structure with mainly .png .mp3 and text files.
If renaming them is out of the question for whatever reason, you could override -package-resources in the build.xml and customize aapt, specifying a new location for res/ along with various other options to handle issues that might come up (Then aapt would be the part to research).
You can inspect android-sdk/tools/ant/build.xml for what that target already does, but essentially you would simply paste in the following to your own build.xml
<target name="-package-resources">
<echo>Packaging resources</echo>
<aapt executable="${aapt}"
command="package"
verbose="${verbose}"
versioncode="${version.code}"
manifest="AndroidManifest.xml"
assets="${asset.absolute.dir}"
androidjar="${android.jar}"
apkfolder="${out.absolute.dir}"
resourcefilename="${resource.package.file.name}"
projectLibrariesResName="${project.libraries.res}"
projectLibrariesPackageName="${project.libraries.package}"
resourcefilter="${aapt.resource.filter}">
<res path="${resource.absolute.dir}"/>
</aapt>
</target>
and customize to your needs.
Also notice that it pulls the res path from resource.absolute.dir, so if thats all you really need to do, then you could set that in ant.properties or whatever the default properties file is in the sdk tools are that you're using. Just inspect the build.xml to see or add a new loadproperties line pointing to your own. IIRC, resource.absolute.dir gets set based on resource.dir, so you might have to try each but in the properties file you would just set
resource.dir=new/path/to/res
audio goes in {Project Directory}/res/raw and images go in {Project Directory}/res/drawable
This page may be of some use to you:
http://developer.android.com/guide/topics/resources/index.html

Categories

Resources