Hacking by Walkingice: 2013/05

2013/05/29

Exclude dependency jar file from apk when using Ant for Android

To put it simply, Android ant packages each jar files under directory libs to the destination apk file, but I don't wanna it. This is just workaround. (I am using Android SDK Tools 22.0.1)

I am writing a simple Bluetooth 4.0 application which base on Samsung series mobile phone. Android is going to support Bluetooth 4.0 but it does not happen so far. That means I still need using Samsung BLE SDK to use Bluetooth 4.0, that's ok.

When I started learning Samsung BLE SDK via attached samples, it works well. It is build-able under Eclipse, it works. When I used Ant to build the apk (yes, I used to use command-line tool to do developing.), it failed.

I got a run-time error:  <A Class> had used a different <B class>; during pre-verification

W/dalvikvm(22070): Class resolved by unexpected DEX: Lcom/samsung/ble/pxpmonitor/ProximityService$3;(0x430e85d0):0x40086000 ref [Lcom/samsung/android/sdk/bt/gatt/BluetoothGattCallback;] Lcom/samsung/android/sdk/bt/gatt/BluetoothGattCallback;(0x430e85d0):0x40038000
W/dalvikvm(22070): (Lcom/samsung/ble/pxpmonitor/ProximityService$3; had used a different Lcom/samsung/android/sdk/bt/gatt/BluetoothGattCallback; during pre-verification)
W/dalvikvm(22070): Unable to resolve superclass of Lcom/samsung/ble/pxpmonitor/ProximityService$3; (60)
W/dalvikvm(22070): Link of class 'Lcom/samsung/ble/pxpmonitor/ProximityService$3;' failed
D/AndroidRuntime(22070): Shutting down VM
W/dalvikvm(22070): threadid=1: thread exiting with uncaught exception (group=0x41f83930)
E/AndroidRuntime(22070): FATAL EXCEPTION: main
E/AndroidRuntime(22070): java.lang.NoClassDefFoundError: com/samsung/ble/pxpmonitor/ProximityService$3
E/AndroidRuntime(22070):        at com.samsung.ble.pxpmonitor.ProximityService.(ProximityService.java:195)
E/AndroidRuntime(22070):        at java.lang.Class.newInstanceImpl(Native Method)
.....(skip)
E/AndroidRuntime(22070):        at java.lang.ClassLoader.loadClass(ClassLoader.java:461) 

Because the apk file I built contains ble_sdk.jar, and Samsung Galaxy S4 has the same (at least, the same name) implementation under /system/framework.

The problem is that I have to build some classes which depend on ble_sdk.jar, but I cannot package the ble_sdk.jar into apk file since it makes duplication.

In general, we put dependency libraries to directory libs, but the dex-helper macro in Android Ant build system merges EVERY JAR FILES INTO classes.dex. Cool, that bites me.


To put the ble_sdk.jar outside directory libs and asks ant-building-system refer to it? it doesn't work, we even cannot override the property jar.libs.dir. (issue #33194)

I tried to figure it out but quit with no luck. If you know a good way match my requirement, please tell me. This is my workaround. (workaround means --- Someday I will bite myself.)

Workaround: Do not package each jar under libs unless I ask you to do that.

Add a custom_rules.xml to your project with these statements.

<project>
<target name="-post-compile">
        <path id="project.all.jars.path">
                <!-- un-comment below line if you want it-->
                <!-- <pathelement path="libs/please_package_this.jar"> -->
        </path>
        <echo level="info">To be packaged jar: ${toString:project.all.jars.path}
</project>


It cleans project.all.jars.path that defines Android ant-building-system's merge targets. I don't like this idea but it basically works.