I've been developing a library to use in my project, and while it is working locally, I would like to share it and use it as an external dependency.
How do I wrap my library so that built AAR contains both *.so native library and generated *.java classes (generated by Kotlin compiler) ? Because there are two-way interactions in my library: Kotlin external functions defined in C++, and some C++ code calling Kotlin classes and methods.
So, my questions are:
How to correctly package Kotlin + JNI android library ?
How to upload said package to Bintray so users (and myself) could use it as a dependency ?
(Note: I've seen tutorials and examples, but they were either Kotlin/Android or Java/Jni/Android)
If you want to package .so with your application, note that you can always put it inside JAR file. Then, you can unpack it, and load it using System.load.
You can find sample here: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031
Note
Remember that packaging .so inside application is a risky thing. As you deal with native code, you have to be 100% sure that all native dependencies are there. You have to pay attention to architecture as well.
Related
We use Xamarin Forms and I have been tasked with integrating a 3rd party AAR library from a business partner and I don't have control over the library or its dependencies. This library itself is distributed using Maven, which works great in Android Studio but is a pain in Xamarin, and it has many dependencies on both libraries that are standard in Android as well as other proprietary libraries.
Since I only need to interact with a small portion of the public API of the main library, I've created an Android library (AAR) wrapper project in Android Studio that only exposes the functionality I need and does not use any types that do not already have bindings.
I have created an Android binding project against the AAR wrapper library, and it compiles in Visual Studio without any warnings or errors.
I've created bindings for other libraries in the past and have the Xamarin binding documentation multiple times and searched online, but the part I'm missing is how to include the required/reference JAR/AAR files in the compilation process and the final Android application. Most of the standard libraries that I need already have NuGet packages (Androidx, Google Play Services, etc)., but the binding library compiles without complaint - so how do I include the other required libraries?
Do I really have to create a binding project for each required AAR/JAR and add as a reference? I don't need to interact with the types or resources in these libraries directly from Xamarin since I only interact with the the types/methods exposed in the wrapper AAR (e.g. I don't think I really need a Xamarin binding). Is there a way to simply have Xamarin process the required AARs and JARs without creating a Xamarin binding project for every library that doesn't already have a NuGet package? There are many many dependencies which makes this theoretically possible, but not in practice. There must be an easier way...
I noticed there is an AndroidLibrary build action that the documentation says can be used to directly reference an AAR/JAR file in a Android application, but I can find no examples of how to use this in practice. What does this build action do? How is it supposed to be used? https://learn.microsoft.com/en-us/xamarin/android/deploy-test/building-apps/build-items#androidaarlibrary
Thanks in advance for any help or direction on the best way to do this.
I have read some sample codes, I find that many project use library module structure, you can see Image A.
Could you tell me the benefit to use library module in Android Studio ?
What code do I need to place it in library ?
And More, both app and lib module use the same namesapce in the sample code, I don't know if it's suitable, could you tell me ?
Image A
Library module gives you two options to create library Android and Java.
Android library module-> Android library compiles into an Android Archive (AAR) file that you can use as a dependency for an Android app module . It allows you to add android specific components like resources and manifest file, which allows you to bundle in shared resources like layouts and drawables in addition to Java classes and methods.
Java Library -> It builds a JAR file. JAR file is useful for many projects especially when you want to share code with other platforms. But it does not allow you to include Android resources or manifest files, which is very useful for code reuse in Android projects. So when you do not need any android specific resources in library you should create a java library.
Library modules are beneficial for projects :-
When you're building multiple apps that use some of the same components, such as activities, services, or UI layouts.
When you're building an app that exists in multiple APK variations, such as a free and paid version and you need the same core components in both.
Quoted from developer.android.com
Other than that same namespace is not problematic unless you have same package name inside App and libraries . You should use a different namespace for libraries.
PS-> If you are familiar with Clean Architecture, The idea behind most of the software design pattern is Separation of concern . In Clean architecture a project is divided into multiple modules. When you implement clean architecture in android you'll see that some of the module you can create as Java library like domain module. Creating module is really useful to follow re-usability and SOLID principles and Inversion of control.
Firstly, don't look into the package name declared in the java directory. Look into the manifest file. You can see that these modules have different package name. It means that all modules in a project must have different package name.
Regarding to your question, what are the benefit of naming library module as lib?
There's no benefit at all. Some people are comfort with lib name, so they can differentiate the demo and library module easily. However, using lib as library's module name requires you to add additional configuration in the lib/build.gradle, i.e. archiveBaseName. This Gradle attribute will rename the JAR/AAR from lib.aar to work-runtime.aar, so people can use it like this:
implementation "androidx.work:work-runtime:$work_version"
If archiveBaseName is not set, people will use it like this:
implementation "androidx.work:lib:$work_version"
In real case, let's take my open source library as the example, MaterialPreference. I used to use lib name on this project, but now I think lib is not a good module name. Using materialpreference as module name will remove additional configuration archiveBaseName. So I feel it is more simple.
I am trying to use SQLCipher within Android. They made it very easy to integrate by adding the dependency:
implementation 'net.zetetic:android-database-sqlcipher:4.2.0#aar'
They have nice and simple examples of then using this in Java, but my application is c++ and I am using the NDK. SQLCipher is primarily C code so I know that this is linking against some compiled C code. Are the headers available for use? Where are these dependencies being installed. I am an iOS developer new to Android so I feel like this should simple but I am just missing something.
There's currently no support for consuming C/C++ dependencies from an AAR. We're working on this here: https://github.com/android-ndk/ndk/issues/916
But I should note that even when that is complete, sqlcipher does need to choose to expose that library. The AAR would not currently contain includes, and it may not be a stable API so they may choose not to expose it.
For a library to be usable directly by ndk, you'd need a .so version of it to link against. If you're including the library like this, you'd use JNI to access it via Java.
I'd recommend against hacking something up to access their .so files directly. Its quite possible their Java code has business logic that prevents errors or initialized things that are not set up properly if you go right against their .so file.
I am currently working on an android project that requires me to make use of functions included in a shared library (.so). I also only have header (.h) files for the library provided to me.
Is it possible to work with just these two files? Or do I need to create my own implemenations via c++ codes?
I am using Android Studio intend to use CMake.
Regards,
Philip
Most Android apps are written in Java. Google has released the Native Developer Kit (NDK) in order to allow developers to write libraries in C++. However, these libraries are usually very low level and called from the Java code which defines the UI and higher-level app logic. Most likely you will need to write a wrapper for the library so that you can call it from Java code. Looks like this blog is a good place to start.
I'm trying to integrate this specific library to my Android project, and the library is written in C/C++. I've miraculously gotten ndk-build to give me the needed .so file.
However, looking at it, there's a sample in the project, and they use a mysterious .jar with the API bindings of the .c/c++ files.
How do i either
create this special .jar file that has the API, based on the .so?
OR
directly add a method to the main c++ file and then call it from Java?
I've tried to re-wrap things using JNI, but it definitely doesn't seem to work. i keep getting UnsatisfiedLinkError.
A lot of the documentation online uses jni as the tutorial. i'm happy with just a few links to tutorials on JNA.
JNA provides a stub native library, libjnidispatch.so for a variety of platforms. You can build this library yourself, or extract one of the pre-built binaries from the project's lib/native/<platform>.jar packages.
You include libjnidispatch.so in your Android project the way you would any other JNI library. This is required; you cannot rely on JNA to dynamically unpack and use its native library automatically like on other platforms. The JNA project includes details for doing so (as well as instructions for building libjnidispatch.so yourself).
You then use jna.jar as you would any other Java jar file, and write your own (Java) mappings to match the native library you're trying to access. There's also a jna-min.jar which omits all the native platform libraries that are normally bundled in jna.jar.
Do go to project properties and build paths and remove JNA 4.0 and related classes.
This will work!