What is the difference between jni and cpp packages in a project with Android NDK? It seems that .cpp, .h, Android.mk and other files for work with native code can be located in both packages? .. Or am I wrong? What then is their difference?
They are really just folders, so it's up to you how you organize your native code as long as you specify the correct path to your source and include files in the build system (i.e. your CMakeLists.txt or Android.mk file). That being said, Android Studio 3.1 seems to put all native code to the cpp/ folder by default, so it'd be logical to use the jni/ folder for jni headers only or not use it at all.
Related
Anytime I clear build folder in flutter (either with flutter clean or manually), my jni folder rebuilds (~40 mins). Is that possible to compile library to some binary, and use it from android without breaking any interfaces and functionality?
P.S. My library consists of many folders and contains .mk, .c, .cpp, .h files.
Is that possible to compile library to some binary, and use it from android without breaking any interfaces and functionality?
Of course yes. Build you libraries like shared .so or static .a and use them like prebuilts. Here the example how to use native prebuilt libraries: How to link .a to .so and create new .so for android
Moreover, you can also put them together with the used SDK, NDK, AS, and other thirdparties in Docker image and work with your project from Docker.
I have an Android Eclipse library project "Lib" that contains both Java and C code built with the NDK. I have another project "App", which is dependant on Lib. App also contains both Java and C. My goal is to have multiple Eclipse App-like projects which each use the Lib project.
A Java routine in App calls a Java routine in Lib which calls C code in Lib. This compiles, links, and runs perfectly on the device.
Now I want to add a call from the C code in App to the C code in Lib. My First problem is header files. I need to include a header file, jni/lib-jni,h, from the Lib project:
#include "lib-jni.h"
in a .c file in App. For this #include to work I believe I need to add Lib's jni/ directory to LOCAL_C_INCLUDES in App's jni/Android.mk. I do not want to hard-code this path, I would like to get it from Eclipse if possible. After all, I've told Eclipse that the App project depends on the Lib project and Eclipse knows how to connect Java calls between the two.
I temporarily kludged around the first problem by copying lib-jni.h from Lib's jni/ directory to App's jni/ directory. Now App's C code compiles, but it won't link; it gets an undefined. In App's Android.mk I need to tell the C linker to link against libLib.so. I tried putting -lLib on LOCAL_LDLIBS, but that didn't work. libLib.so is in the Lib project in Lib/libs/armeabi/libLib.so. Eclipse knows to incorporate this .so into the .apk file it builds for App.
Is there a way to cleanly solve these two problems?
Add Lib's jni/ directory to App's LOCAL_C_INCLUDES
Add a reference to libLIb.so to App's LOCAL_LDLIBS
I phrased these problems in terms of possible solutions. I'm open to any solution. For example, if using LOCAL_LDLIBS the wrong way to go, what is the right way?
Note: Because App and Lib are two separate Eclipse projects built at separate times I am pretty sure I can not use LOCAL_EXPORT_C_INCLUDES in Lib's Android.mk to make Lib's jni/ directory available to App's Anroid.mk - I tried it didn't work. But I'm prepared to be educated.
I always set the LOCAL_C_INCLUDES to the original lib, so I think that is not that bad idea. An other solution is to include the external library as a static library in your libs folder, but I'm not sure if it will work.
I'm making a Unity3d plugin for this c++ library for Android. Ive gotten it to work in windows by opening the visual studio project the library makers provided, adding a new .cpp file to it with my API code and building to a dll.
I'm wondering now how I can add this new .cpp file to the library and build it for Android.
So far I have installed the Android sdk and ndk on a machine with ubuntu and successfully built the original library using ndk-build (as per these instructions)
I'm guessing it is not as simple as copying my .cpp file into the folder and building as there are AndroidManifest.xml files and so on.
The AndroidManifest.xml file is not pertinent for an NDK build.
You will need to find the appropriate Android.mk file. You may need to add the file name into the LOCAL_SRC_FILES in that make file, although they may have it set up to compile all the .cpp files in the directory or something more intelligent along those lines. It is, after all, a regular make file.
See here for info on the Android.mk file specifics.
Edit:
I suppose I should add that it would be the LOCAL_SRC_FILES preceding the relevant include $(BUILD_SHARED_LIBRARY) for the library you intend to build. Each make file may contain an arbitrary number of targets, although in the simplest case it's usually one make file to build a library.
I have been trying to implement the API for the serial port found the the below web page. I am a beginner in all this and I am sure about what I am looking at:
http://code.google.com/p/android-serialport-api/source/browse/#svn%2Ftrunk%2Fandroid-serialport-api%2Fproject%2Fjni
Questions:
1) The .c files are built how? Do I need to download the NDK? I assume the .c file is run directly by the virtual machine, or what? Or is the executable for the .c the file in the libs directory? If so, how do I utilize the libserial_por.so file?
Thanks!
The .c files are built into a library by running ndk-build in the project directory. You need the NDK.
The .c files are not run directly by the virtual machine, but rather a library is created in the libs directory, which is then loaded along with the SerialPort class.
To use the library, just use the SerialPort class which already has bindings to the library.
C files will be compiled to an ARM binary library with the extension .so by the NDK. Take a look at the NDK Documentation, section "Getting Started with the NDK", to find out how to use it.
Basically, you place your .c files in the jni directory, change Android.mk to specify how to compile them, then run ndk-build to build the library. The resulting lib<name>.so will be placed in the lib directory. You then use your library in the Java project with System.loadLibrary('<name>').
This of course means the library must have a JNI interface for you to be able to use with the Java application, since Android doesn't support JNA yet.
I see though that the code you pointed out is an Android project. To run it, simply run ndk-build in the project directory to build the library, then run the project in an emulator.
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.
How do I package up and build the .jar and .so? What are the best practices here?
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?
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?
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
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.
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.
Add the below lines to android.mk.
include $(BUILD_PACKAGE)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := alias:libs/your.jar
include $(BUILD_MULTI_PREBUILT)