Amit,
The following are some notes I’ve thrown together regarding adding a native
C/C++ library into Android and making it available through a Java class.
I am unsure if this is Google’s recommended way of doing things, but have
tried to ensure that I don’t contaminate the core namespace of the
Platform.
In particular with respect to the right approach to developing using
Eclipse and the java library.
The Android example I found most useful to look at was that of libdrm. This
is located under frameworks/base/media/libdrm. The source to the C part of
the JNI code is located under that directory in:
frameworks/base/media/libdrm/mobile1/src/jni/drm1_jni.c.
The Java classes associated with the C code are located under:
frameworks/base/media/java/android/drm/mobile1/*.java
It is helpful to look at these files and consider the following key things
that are needed:
A java library that contains classes which a) have declarations for
native methods and b) calls System.loadLibrary(“MyLibrary”) upon
initialisation. The mechanism that bridges between the Java and C/C++
domains is that of JNI – there is plenty of documentation about this
on the web. Note that care is needed at this interface because java
components do not necessarily have a straight-forward translation to
the C world (for example java arrays need to be locked while
accessing them as their memory is movable etc).
A shared library (for example) libMyNativeLibrary.so which contains a)
the native methods (relating to those methods declared as native in
the java classes) and a special function JNI_OnLoad. This function
gets invoked when the VM loads the shared library. In it you need to
register the native methods associated with the classes in the java
library.
I also had to add a line into the file
build/core/prelink-linux-arm.map that included my shared library. I’m
not clear on what this does, but I get a complaint when building if I
don’t have it.
A ‘jar’ file that contains the definition of the classes that can be
used when developing with the java library. When your java library is
built you should find a related ‘classes.jar’ file (created in
out/target/common/obj/JAVA_LIBRARIES/mylib_intermediates). You can
reference this file from an android project as an external jar such
that classes and methods etc are resolved correctly.
NOTE: At the moment, it seems that the Android SDK is not set up to
handle referencing ‘system’ libraries in this way. This means that
currently when you go to run the application, a run-time check will
fail because it ends up that there are multiple copies of the classes
involved (I believe one in the application and one in the image).
This throws out an error like: ‘Class resolved by unexpected DEX’.
Suggestions have been made that it may be possible to use and to link
the java stuff to avoid this. There are probably other approaches
though (see round about line 116 in dalvik/vm/oo/Resolve.c) – I’ve
disabled this test while playing, but that’s not a viable solution.
The real solution has got to be some way of generating all this stuff
so that a jar file can be referenced from an Android project.
The Application that uses this library must declare that it uses the
library by having a <uses-library> clause in its manifest.xml file
(open it up in the eclipse project and add something like:
<uses-library android:name=”com.mycompany.mylibrary”>
into the applications clause. Without this uses-library clause it
won’t work.
In the permissions.xml file (under frameworks/base/data/etc), you need
to have a declaration that links the name of the library (as above),
with the jar file that gets generated when a build is done – look at
the other entries in the file.
When an Android platform is built (assuming you are trying things out on
the emulator) you need to create a run configuration that points to
where your image (with the shared library and classes is located). To
do this you need to add options for –kernel, -system and –skindir
into your run configuration. I also add a logcat option to get
tracing specific to my library to pop out onto the console window.
For example, something like:
-system /Android/out/target/product/generic/
-kernel /Android/prebuilt/android-arm/kernel/kernel-qemu
-skindir /Android/development/emulator/skins
-logcat Mytag:D,*S
Directories and Structure.
I haven’t found any documentation about where you are meant to place things
in the source tree, but have had endless hours of fun guessing. In the end,
I created a directory just under the root of Android and placed my java
classes and shared library underneath it in separate directories (maintain
the relationship between the directory names and the package).
Both the shared library and the java classes have an associated Android.mk
file and each has a definition of LOCAL_MODULE which defines the name of
the shared library and jar files generated.
Once built you should find that your image will include the shared library
and java library. (You can see them using ‘adb shell’ when the emulator is
running).
Amit
<singhalamit85@gm
ail.com> To
Sent by: android-platform
android-platform@ <
android-...@googlegroups.com>
googlegroups.com cc
Subject
02/12/2008 10:14 Re: How to integrate c code with
java code
Please respond to
android-platform@
googlegroups.com
ForwardSourceID:NT00004112