Question

I've been asked to automate the process of building a 'secondary dex' that can be loaded by a DexClassLoader. The idea is that instead of manually exporting to a .jar file and then running the dx script to add classes.dex to a new .jar in the main project's assets directory, normal compilation of the secondary project would automatically copy a dynamically loadable .jar to the main project.

It does look like I can do this by marking the secondary project as an Android Library (so that it compiles to a .jar) and adding an Eclipse Builder that calls the dx script. I've got a bash script and a .launch wrapper for it that passes ${project_loc}/bin/${resource_name}.jar to the script; if I place the bash script in the main project's root directory, %0 tells me where to copy the loadable .jar.

Of course, dx is not on the path. I figured I'd do a `which adb` and then use find ... but adb is not on the path, either!

So, my question: Is there an Eclipse string variable that contains the location of the Android SDK?

Was it helpful?

Solution 2

Fwiw, I never did find "an Eclipse string variable that contains the location of the Android SDK". Instead, what I did was

  1. Read the dx script and notice that it just passed arguments to dx.jar.
  2. Add the most recent available dx.jar to my Builder project, and simply call it directly, from my Java code. The source was not hard to find. It turned out that the main main(String[]) simply dispatched to one of several internal main(String[]) methods, so I just called the right one directly.
  3. Split my Builder into two pieces: a) a 'stand-alone dexxer' which is just a jar file that can be called from an ant action, and which calls into dx.jar; and b) an Eclipse Builder which contains the build control logic and a bit of Eclipse console code, and which calls into the stand-alone dexxer.

This worked fine. We figured that if Google ever released a dx.jar that somehow offered significantly better dexification, we could just rebuild the Builder with the new jar; this hasn't been an issue, yet.

OTHER TIPS

A coworker pointed out that ${project_classpath} contains a path to annotations.jar in the SDK directory. That let me write this script:

#!/bin/bash

#####
##### Get the directory this script is running in.
##### We will write our output to ${client}/assets
#####

client=${0%/*} 

#####
##### Get the input parameter; calculate the output
#####

input=$1
output=${client}/assets/${input##*/} 

#####
##### Use the classpath parameter to find the latest dx script:
#####

# Turn : into \n
classpath=${2//:/\\n}

# Find the line that refers to annotations.jar
annotations=`echo -e $classpath | grep annotations`

# Strip the filename
path=${annotations%/*}

# There may be multiple copies. We get access time and path.
# We output : instead of \n because bash "Word Splitting" is complicated.
jars=`find $path -name dx.jar -printf "%A@ %p:"`
until [ "$jars" ]
do
  path=${path}/..
  jars=`find $path -name dx.jar -printf "%A@ %p:"`
done

# Turn : into \n
jars=${jars//:/\\n}

# We want the last accessed jar
sorted=`echo -e "$jars" | sort -nrk 1,2`

# Get the jar filename
last_used=`echo -e "$sorted" | grep -om 1 "/.*$"`

# Strip the filename
last_path=${last_used%/*}

# Find the dx script
dx=`find $last_path -name dx`
until [ "$dx" ]
do
  last_path=${last_path}/..
  dx=`find $last_path -name dx`
done

#####
##### Add classes.dex to input jar
#####

$dx --dex --keep-classes --output $output $input

Here's it's .launch file, with the project name and path redacted:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.core.ATTR_REFRESH_RECURSIVE" value="false"/>
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/MAIN_PROJECT_NAME/assets&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${project_loc}/../MAIN_PROJECT_DIRECTORY/secondary-dexxer"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto,"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="${project_loc}/bin/${resource_name}.jar&#10;${project_classpath}"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
</launchConfiguration>

Not exactly optimal, and definitely not something I can add to the source tree (we have people who use Windows for some reason) but a start: painful though some of the bash "Word Splitting" issues were, they presumably do pale next to the learning curve that will be involved in turning this into a 'proper' Eclipse plugin, in Java.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top