Overview
In previous tutorial we learned how to use Java Native Access (JNA) library to call native method this native method is availabe in android prebuild shared library (libc). In this tutorial we will create our own C++ shared library and call with JNA library.
This post covers
- Creating Android Studio project
- Configuring JNA AAR library
- Creating C++ shared library
- Calling C++ shared library in Java
- Output
Requirements
- Android Studio 3.0 or higher
- Android NDK
Difficulty
- Intermediate
Guide
1. Creating Android Studio project
Create new android project and change Application name you can also change Company domain and Package name according to requirements, select Include C++ support and click next
Select minimum SDK version and click next
Select Empty Activity and click next
Change Activity Name and Layout Name according to requirements and click Next
Select C++ Standard as Toolchain Default and click Finish to create project
2. Configuring JNA AAR library
Download jna.aar and
create New Module and select Import JAR/AAR Package and click next
Select jna.aar file from file system and click Finish
jna module added to project, open build.gradle file and add jna module under dependencies
dependencies {
compile project(':jna')
....
....
}
3. Creating C++ shared library
In this section we will create very simple math library in C++ which will perform basic math operations such as add, subtract, multiply and divide. Open the file native-lib.cpp which is in cpp folder
at the time of writing contents of this file are
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring JNICALL
Java_com_faob_t2_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
As we can see for a very simple method which just returns string, a very complex code has been generated with long method name and complex arguments types. Replace this complex code with a very simple code which does exactly the same thing
extern "C" {
char* libName(){
return (char *) "My Math Shared Library";
}
}
As we can see code is very simple and readable and is easy to maintain. Return type of this method is pointer to char which is standard way to declare string in C++. We don't need complex JNI types and long method names this is one of the power JNA gives us. Lets add some more methods which performs basic math operations complete code is
extern "C" {
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int divide(int a, int b) {
return a / b;
}
int multiply(int a, int b) {
return a * b;
}
char* libName(){
return (char *) "My Math Shared Library";
}
}
Since we are using C++ we must wrap all methods in extern "C" block to avoid name mangling. First four methods returns basic math operations results and fifth method libName just returns string which is name of our library. As we can see this code is much simpler, easy to maintain and understand, equivalent JNI code for these methods will be complex and difficult to maintain this is one of many advantages JNA library gives us.
4. Calling C++ shared library in Java
Open MainActivity.java and replace old code with this new code
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.sun.jna.Native;
public class MainActivity extends AppCompatActivity {
//loading native library
static {
Native.register(MainActivity.class, "native-lib");
}
//native methods signatures
public native int add(int a, int b);
public native int subtract(int a, int b);
public native int divide(int a, int b);
public native int multiply(int a, int b);
public native String libName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//calling native methods
System.out.println("add: " + add(4, 2));
System.out.println("subtract: " + subtract(4, 2));
System.out.println("divide: " + divide(4, 2));
System.out.println("multiply: " + multiply(4, 2));
System.out.println(libName());
}
}
There are three steps
1. Loading shared library
static {
Native.register(MainActivity.class, "native-lib");
}
First argument to Native.register() method is the class in which we defined our native methods and 2nd argument is the name of native shared library. Name of shared library is native-lib we can change this default name in CMakeLists.txt file which is available in app folder. Loading should be done in static block which will load shared library during class loading time.
2. Declaring native methods signatures
native int add(int a, int b);
native int subtract(int a, int b);
native int divide(int a, int b);
native int multiply(int a, int b);
native String libName();
Mapping C++ functions in Java is very simple first four C++ methods are almost same in Java and fifth C++ method which return pointer to char which is String in java. we have to add native keyword which tells compiler that method is implemented in native code.
3. Calling native methods
System.out.println("add: " + add(4, 2));
System.out.println("subtract: " + subtract(4, 2));
System.out.println("divide: " + divide(4, 2));
System.out.println("multiply: " + multiply(4, 2));
System.out.println(libName());
Calling native methods is same as calling other java methods.
5. Output
Output can be seen in Logcat window.
Conclusion
With latest Android Studio versions it becomes very easy to add native code in android project and with JNA library it becomes super simple to call native code.
Code
Project is available on github. Clone repo and open project name T2.
Posted on Utopian.io - Rewarding Open Source Contributors
Thank you for the contribution. It has been approved.
You can contact us on Discord.
[utopian-moderator]
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Hey @kabooom I am @utopian-io. I have just upvoted you!
Achievements
Suggestions
Get Noticed!
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit