views:

2074

answers:

3

I need to create an Android library which I can include as a jar in any Android application. I use NetBeans 6.8, the nbandroid plugin, and the Android SDK.

The steps I took so far are:

1) Create the library project, with android.jar included to have access to Android classes (the library uses android.util.Log and other Android classes).

2) Compile the library as a jar.

3) Add the library's jar to the Android application (right-click on Libraries under the project node and add the jar).

4) Add <uses-library> to the Android manifest. (erroneous and unnecessary)

Step 3 at least allows me to reference the library's classes in the application's source code, but the classes don't seem to actually be included at compile time. When I run the application, I get the following error in the log.

I/dalvikvm(  349): Could not find method mylibrarypackage.MyClass.myMethod, referenced from method myapplicationpackage.HomeActivity.onCreate
W/dalvikvm(  349): VFY: unable to resolve static method 985: Lmylibrarypackage/MyClass;.myMethod ()V
D/dalvikvm(  349): VFY: replacing opcode 0x71 at 0x000a
D/dalvikvm(  349): Making a copy of Lmyapplicationpackage/HomeActivity;.onCreate code (160 bytes)
D/AndroidRuntime(  349): Shutting down VM
W/dalvikvm(  349): threadid=3: thread exiting with uncaught exception (group=0x4001b188)
E/AndroidRuntime(  349): Uncaught handler: thread main exiting due to uncaught exception
E/AndroidRuntime(  349): java.lang.NoClassDefFoundError: mylibrarypackage.MyClass
E/AndroidRuntime(  349):    at myapplicationpackage.HomeActivity.onCreate(HomeActivity.java:58)
E/AndroidRuntime(  349):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
E/AndroidRuntime(  349):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417)
E/AndroidRuntime(  349):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470)
E/AndroidRuntime(  349):    at android.app.ActivityThread.access$2200(ActivityThread.java:119)
E/AndroidRuntime(  349):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1821)
E/AndroidRuntime(  349):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(  349):    at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime(  349):    at android.app.ActivityThread.main(ActivityThread.java:4310)
E/AndroidRuntime(  349):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(  349):    at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime(  349):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
E/AndroidRuntime(  349):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
E/AndroidRuntime(  349):    at dalvik.system.NativeStart.main(Native Method)

Do I have to add the library to the build path somewhere else? Am I missing something?

A: 
Christopher
I don't see why it would be different either, but the error in the log seems to indicate otherwise, unless there's something else I'm missing.
Arcturus
Then I blame the NetBeans plugin! ;) Does it work if you compile it from the command line using ant? I think by default the Android ant script references a `libs` directory for included JARs.
Christopher
A: 
<uses-library android:name="com.mylibrarypackage" />

must not be included in your manifest, its usage is to include native shared libraries the application is linked against (i.e.: maps) not jars you are using in your project.

The other steps you mention are correct and work in Eclipse and should work in Netbeans unless there's a problem with the plugin.

dtmilano
+4  A: 

It appears I solved the problem.

I don't know if I missed a step when reading about how to use the nbandroid plugin, but the generated build-impl.xml doesn't seem to include any libraries I add with NetBeans when creating the APK.

This is the incriminating piece of ant script:

<target depends="init,compile,-pre-pre-jar,-pre-jar" name="-dex">
    <exec executable="${dx}" failonerror="true">
        <arg value="--dex"/>
        <arg value="--output=${basedir}/${intermediate.dex}"/>
        <arg value="--positions=lines"/>
        <arg path="${build.classes.dir}"/>
    </exec>
</target>

The library is included and the error mentioned in my question disappears if I add this last argument:

<arg path="${external.libs.dir}"/>

With external.libs.dir pointing to the directory containing the library's jar.

Thanks to Christopher for making me look at the build.xml generated by the Android command line tools (the script generated when creating an Android project in NetBeans with the nbandroid plugin is quite different).


Addendum: Since I'm talking about NetBeans, another way of doing this is by overriding the -pre-jar target in the project's build.xml, instead of the above change to build-impl.xml. This is done by adding the following to build.xml:

<target name="-pre-jar">
  <copy todir="${build.classes.dir}">
    <fileset dir="${external.libs.dir}" />
  </copy>
</target>

This way, the library's jar is present along with the built classes, and automatically included.

Arcturus