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?
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.
Including android.jar
within your library seems wrong — you can compile against it but shouldn't bundle it into your JAR.
When people use your library in their Android apps, it'll get compiled against the desired framework version that they've chosen.
Anyway, in Eclipse all you need to do is with a library JAR is add it to the build path. I don't see why NetBeans would be different. As you're building against it, it seems logical for it to be in the build path! :)
<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.
精彩评论