0 foreword

The origin of NDK technology started 3 years ago, when I used so file, I learned about NDK technology, and C language has always been a strong point, so I started NDK development. In the age when AndroidStduio has not been promoted, building NDK development environment based on Eclipse requires safe dependence on development tools, and it is difficult to debug. AndroidStudio also supports nkd-build and cmake development using NDK.

See previous blog posts:

So library development using NDK under Eclipse

AndroidStudio configures the NDK development environment

1 Preparations

1.1 download the NDK

The current NDK stable version has been released to R15C. Attached is the download address of each platform:

  1. android-ndk-r15c-windows-x86

  2. android-ndk-r15c-windows-x86_64

  3. android-ndk-r15c-darwin-x86_64

  4. android-ndk-r15c-linux-x86_64

1.2 Adding NDK dependencies

Unpack the downloaded files locally and specify the NDK path in the AndroidStudio project configuration (note not the AndroidStudio tool configuration).

Or specify the NDK path in the local.properties file.

1.3 Adding cmake support

In the AndroidStudio tool configuration, choose Android SDK -> SDK Tools, check CMake and install.

2 New Supports the NDk project

AndroidStduio now supports a minimalist way to integrate NDK development support by checking include C++ support in the figure below. Then select the C++ standard. Such as c + + 11. Set the Default ToolChain Default.


Then normal run can generate THE C language part of the SO file and package into the APK file.

3 Add NDK support to the project

The above approach is suitable for adding NDK support to new projects. How to add NDK support to existing projects, now provide cmake and ndK-build two ways.

Since both Cmake and NDK-build are supported to compile so files in the same project, the C source code is placed separately in the cpp-src directory. Cmake and NDK-build are divided into different modules for compilation.

3.1 cmake

This is by far the most popular method of integration and is used by AndroidStduio to add NDK support by default when creating new projects. However, adding NDK support to an existing project requires manual configuration.

Create cmake Module and add three files.

  1. Cmakelists. TXT cmake compiles configuration files
Cmake_minimum_required (VERSION 3.4.1) add_library(hello-jni # so libhello-jni.so SHARED Point to the public cpp-src directory.. /.. /.. /.. / cpl-src /hello-jni.c) find_library(log-lib # set path variable name log # specify NDK library to be loaded by CMake)
#Link to the library that the Hello-jni library depends on, and note the configuration of the variable name below
target_link_libraries(hello-jni
        ${log-lib}
)
Copy the code
  1. Androidmanifest.xml Mandatory configuration file for each module, specifying packageName.
<?xml version="1.0" encoding="UTF-8" ? >
<manifest package="com.flueky.cmake">

</manifest>
Copy the code
  1. Build.gradle Mandatory configuration files for each module used to Build projects.
apply plugin: 'com.android.library'

android {
    compileSdkVersion 28

    defaultConfig{
        externalNativeBuild {
            cmake {
                / / specify configuration parameters, more parameter Settings see https://developer.android.google.cn/ndk/guides/cmake
                arguments "-DCMAKE_BUILD_TYPE=DEBUG"
                // Add the CPP standard
// cppFlags "-std=c++11"
            }
        }
    }

    externalNativeBuild {
        cmake {
            // Specify the path to the CMake compilation configuration file
            path "src/main/cpp/CMakeLists.txt"}}}Copy the code

For more information on how to set CMake build parameters, see the official documentation.

Eagle-eyed friends have noticed that externalNativeBuild has been configured in two places. The second externalNativeBuild configuration is to generate a Gradle Task without running the project, and directly find the four Tasks related to compiling the so file in NDK -cmake -> Tasks -> other.


Double-click the exeternalNativeBuildDebug mission, as shown in figure:

Follow the path to find the generated SO file.

3.2 the NDK build

This is the most traditional NDK compilation. With proper configuration, you can compile and export the so file without opening AndroidStudio.

Create an ndK-build Module and add 4 files.

  1. Android.mk
#To be honest, I don't understand this parameter. Copied from the official demo. Used when specifying source files
abspath_wa = $(join $(filter %:,$(subst :,: ,$1)),$(abspath $(filter-out %:,$(subst :,: ,$1))))

#Specify the current path
LOCAL_PATH := $(call my-dir)

#Specify the source file pathJNI_SRC_PATH := $(call abspath_wa, $(LOCAL_PATH)/.. /.. /.. /.. /cpp-src)
#Declare the clear variable
include $(CLEAR_VARS)

#Specify the name of the so library libhello-jni.so
LOCAL_MODULE    := hello-jni
#Specify the C source file
LOCAL_SRC_FILES := $(JNI_SRC_PATH)/hello-jni.c
#Add the NDK libraries that you need to depend on
LOCAL_LDLIBS := -llog -landroid
#Specify as a shared library
include $(BUILD_SHARED_LIBRARY)
Copy the code

For more information on setting the Android. Mk build parameters, read the official documentation

  1. Application.mk
#Specifies the compiled version of SO
APP_ABI := all
#Specify the APP platform version. A warning is generated when the value is larger than android:minSdkVersion
APP_PLATFORM := android-28
Copy the code

For more information on how to set the application. mk build parameters, read the official documentation

  1. AndroidManifext.xml
<?xml version="1.0" encoding="UTF-8" ? >
<manifest package="com.flueky.ndk">

</manifest>
Copy the code
  1. build.gradle
apply plugin: 'com.android.library'

android {
    compileSdkVersion 28
    externalNativeBuild {
        ndkBuild {
            // Specify the mk file path
            path 'src/main/jni/Android.mk'
        }
    }
    defaultConfig {
    }
}
Copy the code

ExternalNativeBuild is the same as CMake and is used to compile the so file. But the ndk-build also supports compiling so files using the command ndk-build. The NDK path needs to be added to the environment variable.

You need to run this command in the jni directory:

The path of so file generated at last is shown in the figure.

4 practice

4.1 Generating header Files

Add native methods to MainActivity in the main Module. Compile early files using Javah. Use the -d argument to specify the output directory for the header file.

public class MainActivity extends Activity {

    static {
        // Load the JNI library
        System.loadLibrary("hello-jni"); }...// Declare Native methods
    private native String hello(a);
}
Copy the code

Run the javah command in app/ SRC /main/ Java

4.2 Writing C source code

Reference the generated header file in the Hello-jni. c file and write the test code.

#include <string.h>
#include <jni.h>
#include "com_flueky_demo_MainActivity.h"
#include "util/log.h"

/ * * * JNI example, demonstrate the native method returns a string, see * * the NDK sample Java source code/app/SRC/main/Java/com/flueky/demo/MainActivity. Java * /
JNIEXPORT jstring JNICALL
Java_com_flueky_demo_MainActivity_hello( JNIEnv* env, jobject thiz )
{
#if defined(__arm__)
    #if defined(__ARM_ARCH_7A__)
        #if defined(__ARM_NEON__)
            #if defined(__ARM_PCS_VFP)
                #define ABI "armeabi-v7a/NEON (hard-float)"
            #else
                #define ABI "armeabi-v7a/NEON"
            #endif
        #else
            #if defined(__ARM_PCS_VFP)
                #define ABI "armeabi-v7a (hard-float)"
            #else
                #define ABI "armeabi-v7a"
            #endif
        #endif
    #else
        #define ABI "armeabi"
    #endif
#elif defined(__i386__)
    #define ABI "x86"
#elif defined(__x86_64__)
    #define ABI "x86_64"
#elif defined(__mips64)  /* mips64el-* toolchain defines __mips__ too */
    #define ABI "mips64"
#elif defined(__mips__)
    #define ABI "mips"
#elif defined(__aarch64__)
    #define ABI "arm64-v8a"
#else
    #define ABI "unknown"
#endif

    LOGD("Sample log Output");

    return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");
}
Copy the code

4.3 Running Screenshot

Page screenshot:

Log screenshot:

5 Obtaining Source Code

Project source code has been opened on GitHub, download address. If you have extra CSDN credits, you can download them here. You can write C source code directly and debug and generate so files.

Google’s official profile can only be read by climbing the wall. To learn how to climb the wall, click SSR.

Think it works? I’ll give you a bonus.I’d like to make a reward

Here’s the AD: Flueky’s tech site