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.
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.
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.
I have an requirement which i have to build .so file using NDK build in Android and I have to call some of the methods from the .so file in my other Android application.
What I have tried so far.
I have taken the .so file from the lib folder of my Android project and put in my other application libs folder where I should call that .so file. I have used the below code:
Note: I am using ECLIPSE
static {
System.loadLibrary("NativeCode");
}
and also tried with full path of library
static {
System.loadLibrary("fullpath\NativeCode");
}
both the cases its giving unsatisfiedLinkError that mean it's not getting the path of my .so file.
You need to have your libNativeCode.so in the jni folder of your root, and not in the libs or lib folder
Here is a nice tutorial : http://www3.ntu.edu.sg/home/ehchua/programming/android/android_ndk.html
Alternatively, you can use following commands:
adb shell
$echo $PATH
What it will do is display a path like this :
/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin
You can have your .so in any of these folders like /system, /system/bin, /system/sbin. (Remember, but you would need to manually copy it, and it is not a good idea to do so for an app)
Edit :
You can not call any JNI function in your app, because the signature. You need to have a JNI wrapper (a .so JNI lib that in turn uses the .h header file to call the JNI function of the other library). This is because JNI is very sensitive to signatures. So, as I recommended earlier, follow the tutorial !
In order to get your .so library to be loaded using loadLibrary() you'll have to copy the libNativeCode.so lib into the jniLibs/architecture folder.
The folder should be located under src/main/jniLibs/armeabi-v7a of your Android Application module (assuming you're using Android Studio).
After you copy the libraries, add the following line to your build.gradle located at the app module folder:
assert file("./src/main/jniLibs/armeabi-v7a/libNativeCode.so").exists()
After you'll complete the above steps it should load the lib properly.
If the libNativeCode.so is located at the wrong path, the Gradle build will fail.
Good luck,
I've made an android library project that uses some native libraries.
I've made the jni wrapper and put the native libs (.so) in the libs// folders. The native libs are compiled using cmake, for armeabi, armeabi-v7a, x86 and mips.
I export this project to a jar and put this jar into a "normal" android project. I then export this project to an apk and can see that my libs are bundles into it.
However, when i install the apk, the libs corresponding to the device are not copied into /data/data/com.my.app/lib and obviously, running the app complains about not finding the libs (UnsatisfiedLinkError).
I've search through SO and everywhere i can but found no answer that solved my case.
i'm using Eclipse, btw
Thanks for your help
UPDATE
OK, i've read the doc in the ndk and seen the examples, and unfortunately, i can't see the solution.
The ndk build the c code into shared libs and places them into the appropriated location in the project. But it doesn't generate anything that says that the libs must be installed with the apk.
My goal is to provide an android library (so a jar), that can be included within an android application. I don't see the real difference between what i'm doing (compile the c libs using cmake and package the jni and java compiled classes into a jar) and what is done with android.mk
If you see what i'm missing, feel free to tell me (even if its obvious).
thanks
UPDATE
i've made a dirty hack: in the libs folder of my application, i've put the jar file containing my classes and my native libs and a copy of the .so files for each arch. Suprise, the libs are no installed in /data/data/com.me.myapp/lib
It seems to confirm that it's a packaging problem.
I export this project to a jar and put this jar into a "normal"
android project. I then export this project to an apk and can see that
my libs are bundles into it.
The issue is that the Android packaging system doesn't handle with binary assets in JARs. For your application project to find and include the generated .so files, you need it to reference the library project as an 'Android library project':
Did you call ndk-build command?
See description below for details.
http://developer.android.com/tools/sdk/ndk/index.html
You can build the shared libraries for the sample apps by going into /samples// then calling the ndk-build command. The generated shared libraries will be located under /samples//libs/armeabi/ for (ARMv5TE machine code) and/or /samples//libs/armeabi-v7a/ for (ARMv7 machine code).
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)