41

I am creating a widget that we will provide to developer end users and it consists of a .jar and a native library (.so) built using the NDK. The JAR has a JNI interface to the dynamic library.

It's very clear on how to include an external .jar in a project but not how to include a dependent dynamic library.

  1. How do I package up and build the .jar and .so? What are the best practices here?

  2. I can create the JAR file using the JDK's jar command. Do I need to run dx.bat on the jar to convert to Dalvik bytecode?

  3. I need to create a sample project showing the widget in action. How do I include this .jar and .so in a sample project that demonstrates how to use the widget?

pevik
  • 4,523
  • 3
  • 33
  • 44
The Sarge
  • 411
  • 1
  • 4
  • 3

4 Answers4

23

I spent some time on this, and i just can't understand why isn't this written on wikitude documentation.... anyway follow this changes!

  • go to windows/preferences/android/build
  • uncheck the first and the second option
  • extract files from wikitudesdk.jar with winrar as if it is an archive, search libarchitect.so and copy it in /libs/libs/armeabi/
  • add wikitudesdk.jar to your build path

enter image description here

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Alessandro Annini
  • 1,531
  • 2
  • 17
  • 32
10

You should use the standard build tools included with the SDK for this. If you include the .jar files you need in the /lib directory of your project, the ant build process will convert the included class files to Dalvik bytecode format and include them in your classes.dex file for the app. Add a build.properties file to your project root as well, with one line:

external.libs.dir=lib

Depending on the version of your SDK and configuration of it, you may need to place the jar in libs rather than lib.

As for the .so, I presume that it's properly compiled using the Android NDK, or using a build script that uses the proper compiler and compiler flags that are required to successfully link the shared object on Android. If this is the case, you can include the .so file in libs/armeabi and they will be added in the jar as well. Furthermore, the dynamic library loader will know to look in this location in the .jar when you actually try to load the library from Java code.

Jason LeBrun
  • 13,037
  • 3
  • 46
  • 42
  • This kind of worked. I did need to use the LIBS folder for my JAR but I was getting compile errors on missing types. Eclipse wanted me to "fix the project" by adding the library project to my sample project. What else can I try? – The Sarge Feb 03 '11 at 16:54
  • If you're referencing the jar from your sample project, then you do indeed need to add the jar to the sample project, so it knows where to find the definitions of the types. You can either add a line to your .classpath file directly that looks like `` or go to the **Java Build Path** section of your project's properties, under the **Libraries** tab, and add it using the **Add JARs...** button. – Jason LeBrun Feb 03 '11 at 17:56
  • I am trying to include a .so in my JAR and am finding that the client project will no longer build. `The library 'foo.jar' contains native libraries that will not run on the device. The following libraries were found: libs/armeabi/libfoo.so` According to the Android SDK Tech Lead Xavier Ducrohet, who weighs in on [this thread on the NDK Google Group](http://groups.google.com/group/android-ndk/browse_thread/thread/bb5bfae006a9c8a2/6aeb6c655b9a4bbd?#6aeb6c655b9a4bbd) they've added a check for native code in included JARs – Kevin Jun 16 '11 at 22:00
  • 4
    @Kevin, you can disable this check in Eclipse using `Window -> Preferences -> Android -> Build -> Force error when external jars contain native libraries` – Gili Jul 06 '12 at 22:48
  • I am having an issue with ant built (appt) finding my .so .a native libs and packing them too. The folder mentioned here /libs/armeabi doesn't that imply 32 bit? I compiled all my native libs with arm64-v8a abi. – Sixjac Mar 11 '22 at 13:24
8

Using ADT 12, I accomplished this by doing the following:

1) Export JAR from your library with the SO file using Eclipse. Make sure you exclude AndroidManifest.xml. This will include source code and other data, so if you are distributing, you'll want to strip these unnecessary bits out using any ZIP utility.

2) Create a directory in your App's source tree (I use "lib" directory) and copy your library JAR to it.

3) Right-click project in Eclipse and select "Configure Build Path". Add JAR and point it to JAR inside your App source tree.

4) In your Eclipse preferences, select Android/Build section and uncheck "Automatically refresh Resources and Assets folder on build". You will notice an option below that says "Force error when external jars contain native libraries." There is an ADT bug, which will supposedly be fixed in R17, which uses the wrong setting. Once it is fixed, you will use the "Force error" one (make sure it unchecked).

5) Once you build your app APK, you will have a libs/armeabi/libXXXX.so file. This will not be automatically unpacked on install. You will need to write code to extract it from your APK file into your data directory, then use System.load on the .so file in your data directory.

I have bidirectional JNI calls going from the dynamically loaded file, and even use dlopen() on it to do my custom plugin registration stuff.

n8n8baby
  • 493
  • 5
  • 16
  • How to writecode to extract so file from the apk file. I have already add the so file to the jar. Thanks a lot for your help. – rodent_la Mar 24 '16 at 09:07
  • Unfortunately, I no longer have access to this code, and it has been so long that I forgot most of the details. But since an APK is a ZIP file, any ZIP library should be able to handle this for you. Good luck. – n8n8baby Mar 24 '16 at 21:39
1

Add the below lines to android.mk.

include $(BUILD_PACKAGE)

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := alias:libs/your.jar

include $(BUILD_MULTI_PREBUILT)
Ry-
  • 218,210
  • 55
  • 464
  • 476
aganpro
  • 11
  • 1