NDK Setup on Android/Flutter Android Project
For this article, we will see the setup for the NDK on Android and Android Flutter project, otherwise, how we call function(s)/functionalities from the C/C++ file(s) to the native Android application with five simple steps.
First of all, we have to install from the Android Studio SDK Manager (SDK Tools Tab) the latest version of NDK and CMake.
Second, Create the cpp package under the main directory of the project and add the CMake (.txt) and C/C++ (.cpp) file as the screenshot below.
CMake file
Add the follow code inside the CMake file, keep in mind that there are some name files that you have to change based on your .cpp file name. In our case the name of the .cpp file is the messageFromC.cpp.
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
message-from-c # based on .cpp file name
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
message-from-c.cpp) # based on .cpp file name
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
message-from-c # based on .cpp file name
# Links the target library to the log library
# included in the NDK.
${log-lib})
C/C++ file
The C/C++ name function is based on the package that you initialized it, in our case I loaded and initialized the function inside the Main Activity. So, the name of the function is starting with the package, included the activity name and underscore instead of dots, Java_com_nicos_flutterprojectandndk_MainActivity (check the screenshot below). The message is the function name (check the snipped code below for a completed example).
Tip: If you have more than one C/C++ functions or files then you can create a singleton/helper/generic class, load the C/C++ file and initialize all the functions inside, then you have one package for multiple functions.
Java_com_nicos_flutterprojectandndk_MainActivity_message(JNIEnv *env, jobject object) {
string message = "Communicate Android Project with C file";
LOGV("The value is %s", message.c_str());
return env->NewStringUTF(message.c_str());
Third, add the follow code inside the Gradle file, under the android section.
android {
//Other Gradle Code Here...
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.30.5"
}
}
ndkVersion = "27.1.12297006"
//Other Gradle Code Here...
}
Forth, Load the C/C++ file inside the companion object, for our case, it loaded in Main Activity.
companion object {
init {
System.loadLibrary("message-from-c")
}
}
Fifth and the last step is the initialization of the external function in Main Activity. Clean and rebuild the project. Now, you can call the function in your Kotlin code.
Note: If you have any issue with c function then you can try the Refresh Linked C++ Projects where it is under the Build in Android Studio
private external fun message(): String
Check my projects with Kotlin and Flutter in my GitHub account to the follow links:
Note: The Flutter project for the communication with the Android Native side is using a channel. If you need an extra example about the channel check the example project in my GitHub account.
I hope you find the article and sample project useful. Let me know your opinion under the comments, feel free to report any issue. I will appreciate it if you let a clap, so, if I have your support to continue writing.
References: