1.1 the JNI (Java Native Interface)

JNI describes a technique that provides a solution for Java bytecode calls to C/C++

1.2 the NDK (Native Development Kit)

The Android NDK is a set of tools that allow you to embed C or C++ (” native code “) into Android applications. The NDK describes the toolset. Being able to use native code in an Android application is especially useful for developers who want to do one or more of the following:

  • Porting its applications across platforms.
  • Reuse existing libraries, or provide their own libraries for reuse.
  • Improve performance in some cases, especially in computation-intensive applications like games.

1.3 the JNI registered

1.3.1 Environment Configuration

There are already articles here that quote others, which are very careful about JNI environment configuration

1.3.2 Static Registration

When the Java layer calls a Navtie function, it looks up the corresponding JNI function in the JNI library based on the function name. If it is not found, an error will be reported. If it is found, the association between the native function and the JNI function will be established. In fact, the function pointer to the JNI function will be saved. The next time you call a native function, you can use the function pointer directly.

JNI function name format (package name “. Java_ + package name (com_example_auto_jnitest) + class name (_MainActivity) + function name (_stringFromJNI)

Disadvantages of static registration:

  • JNI function names must follow the naming format of the JNI specification.
  • Long, error-prone names;
  • The first call will search the corresponding function in JNI according to the function name, which will affect the execution efficiency.
  • All Java classes that declare native functions need to be compiled, with each generated class file generated using the Javah tool to generate a header file;

Static Registration example

Class JNITest package name: com.hqk.jNITestone

package com.hqk.jnitestone;

public class JNITest {

static {
    System.loadLibrary("native-lib");
}

    public static native String sayHello();
} 
Copy the code

For the c++ code, the CPP class is named: native-lib.cpp

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_hqk_jnitestone_JNITest_sayHello(JNIEnv *env, jclass clazz) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
} 
Copy the code

Note:

  • If the CPP class name is native-lib. CPP, add the corresponding Java interaction class to the CPP class
 static {
        System.loadLibrary("native-lib");
    } 
Copy the code
  • If the package name of the Java interaction class is com.hqk.jnitestone, the CPP corresponding method needs to convert the corresponding [.] into [_]. (Refer to above format)

1.3.2 Dynamic Registration

By providing a function mapping table that is registered with the JVM virtual machine, the JVM can use the function mapping table to call the corresponding function without having to look up the function to call by its name.

Java and JNI use the structure of JNINativeMethod to create a function mapping table, which is defined in the jni.h header file. The structure is as follows:

typedef struct { const char* name; Const char* signature; // Const char* signature; Void * fnPtr; // Void * fnPtr; // The pointer function corresponding to the interactive CPP method (pointing to the corresponding function)} JNINativeMethod;Copy the code

1. After creating the mapping table, call the RegisterNatives function to register the mapping table with the JVM; When the Java layer loads the JNI library through system. loadLibrary, it looks up the JNI_OnLoad function in the library. You can think of JNI_OnLoad as an entry function to the JNI library, where you need to do all the function mapping and dynamic registration, as well as some other initialization.

So that’s the concept. Let’s do it

JAVA class JNITest package name: com.hqk.jnitestone

package com.hqk.jnitestone;

public class JNITest {
    static {
        System.loadLibrary("native-lib");
    }

    public static native String sayHello();

    public static native String sayHello2();
} 
Copy the code

Note: There is an additional sayHello2 method that returns: String

CPP Class name Native-lib. CPP code

#include <jni.h> #include <string> #include <android/log.h> extern "C" JNIEXPORT jstring JNICALL Java_com_hqk_jnitestone_JNITest_sayHello(JNIEnv *env, jclass clazz) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); } // CPP interactivity method jString sayHello2(JNIEnv *env, jobject thiz) {STD ::string hello = "Hello, I was dynamically registered!" ; return env->NewStringUTF(hello.c_str()); } static const JNINativeMethod gMethods[] = {{"sayHello2", "()Ljava/lang/String;" (jString *) sayHello2 (jstring *) sayHello2 (jstring *) sayHello2 (jstring *) sayHello2 JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { __android_log_print(ANDROID_LOG_INFO, "native", "Jni_OnLoad"); JNIEnv *env = NULL; if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) ! = JNI_OK) // Get JNIEnv from JavaVM. / / note: here FindClass must package name corresponding and interactive classes, and for [/] symbols jclass clazz = env - > FindClass (" com/HQK jnitestone/JNITest "); if (! clazz) { __android_log_print(ANDROID_LOG_INFO, "native", "cannot get class: com/hqk/jnitestone/JNITest"); return -1; } if (env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) { __android_log_print(ANDROID_LOG_INFO, "native", "register native method failed! \n"); return -1; } return JNI_VERSION_1_4; }Copy the code

As you can see from the above code

CPP class creates JNI_OnLoad — this method is executed at the time of initialization, similar to the activity onCreate, the core code, is to Find the corresponding Java class, Finally, RegisterNatives was provided to realize dynamic registration. 2. JNINativeMethod structure array was added in the CPP class; SayHello2 has been added to the CPP class

1.4 Data type conversion

1.4.1 Basic data conversion

1.4.2 Reference data type conversion

The data types of all Java objects, except arrays of Class, String, Throwable, and basic data types, are represented in JNI as Jobject. String in Java is also a reference type, but it is used so frequently that a separate jString type is created in JNI.

  • Reference types cannot be directly used in the Native layer. They can be used only after they are converted according to JNI functions.
    • Multidimensional arrays (including two-dimensional arrays) are all reference types and need to use the jobjectArray type to access their values.

For example, a two-dimensional integer array is an array that points to a one-bit array.

Jclass intArrayClass = env->FindClass("[I] "); // Construct an array of objects that point to a one-dimensional array of jintArray with an initial size of length, Type: jSIZE jobjectArray obejctIntArray = env->NewObjectArray(Length,intArrayClass, NULL);Copy the code

1.4.3 JNI Function signature

Since Java supports function overloading, there is no way to find the corresponding JNI function based on its name alone. To solve this problem, JNI uses the parameter type and return value type as the signature information for the function.

  • Function signature information format defined by the JNI specification:

(Parameter 1 type character…) Return value type character

  • Example function signature:

3.JNI common data types and corresponding characters:

1.4.4 JNIEnv is introduced

  • JNIEnv concept: The JNIEnv is a thread-dependent structure that represents the runtime environment for Java in this thread. JNIEnv allows you to call a series of JNI system functions.
  • JNIEnv thread dependency: Each thread has a JNIEnv pointer. The JNIEnv is only valid for the thread it is in; it cannot be passed between threads.

Note: to get JNIEnv from a child thread created in C++, call JavaVM’s AttachCurrentThread function. When the child thread exits, the DetachCurrentThread function of JavaVM is called to free the corresponding resource, otherwise an error occurs.

JNIEnv:

  • Access Java member variables and member methods;
  • Calling Java constructors to create Java objects, and so on.

1.5 compile JNI

1.5.1 Cmake compilation

CMake is a cross-platform compilation tool. Instead of compiling objects directly, cmakelists.txt generates the corresponding makefile or project file, and then invokes the underlying compilation. Cmake compilation is supported after Android Studio 2.2.

Cmake_minimum_required (VERSION 3.4.1) add_library(native-lib SHARED Native-lib.cpp) find_library(log-lib log) target_link_libraries( native-lib ${log-lib})Copy the code

1.5.1.1 add_library instruction

Grammar: add_library (libname SHARED | STATIC | MODULE [source])

Compile a set of source files into a library file and save it as libname.so (the lib prefix is automatically added by CMake when the file is generated). There are three library file types, which default to STATIC if not written.

  • SHARED: represents a dynamic library that can be dynamically invoked in (Java) code using System.loadLibrary(name);
  • STATIC: STATIC libraries that are integrated into code and called at compile time
  • MODULE: only if dyId is used. If dyId is not supported, it is treated as SHARED;
  • EXCLUDE_FROM_ALL: indicates that this library is not built by default unless other components depend on it or build it manually.
Add_library (compress SHARED compress. C)Copy the code

1.5.1.2 target_link_libraries command

Grammar: target_link_libraries (target library < the debug | optimized > library2…).

This directive can be used to add the shared library that the target needs to link to. It can also be used to add a shared library link to a shared library that you have written. Such as:

# Compress libjpeg ${log-lib}; # compress libjpeg ${log-lib}Copy the code

1.5.1.3 find_library instruction

Syntax: find_library(name1 path1 path2…)

The VAR variable represents the full path to the library found, including the library file name. Such as:

Find_library (libX X11 /usr/lib) find_library(log-lib logCopy the code

1.5.1.4 More details

References: More on the detailed use of Cmake

1.5.2 Abi architecture

Application Binary Interface (ABI) Application binary interface. Each combination of different cpus and instruction sets has a defined ABI (application binary interface), and a program can only run on that CPU if it follows this interface specification, so the same program code needs to build different libraries for the different ABI in order to be compatible with multiple cpus. Of course, different architectures do not necessarily mean that cpus are incompatible.

  • Armeabi devices are only compatible with ArmeABI;
  • Armeabi-v7a is compatible with ARMEABI-V7A and ArMEABI;
  • Arm64-v8a equipment compatible with ARM64-V8A, ARmeabi-V7A, ArmeABI;
  • X86 devices are compatible with X86 and ArmeABI;
  • X86_64 Devices are compatible with X86_64, X86, and ArmeABI.
  • Mips64 device compatible with MIPS64, MIPS;
  • MIPS only compatible with MIPS;

According to the above compatibility summary, we can also get some rules:

  • Armeabi’s SO file is basically a panacea. It can run on devices other than MIPS and MIPS64, but performance suffers on non-Armeabi devices.
  • 64-bit CPU architectures are always backward compatible with their corresponding 32-bit instruction sets. For example, x86_64 is compatible with X86, ARM64-V8A is compatible with Armeabi-V7A, miPS64 is compatible with MIPS.

So that’s the NDK/JNI introduction, so how do you get to the next level? Here comes the high energy! Lucky to get from a bytedance god there he himself vomiting blood to sort out the “582 pages of Android NDK seven modules learning scriptures”, from the principle to the actual combat, complete!

If it’s good, it’s good to share, so let’s see if this 582 page Android NDK 7 module learning guide can help you get twice the result with half the effort. This treasure book mainly involves the following aspects:

  • NDK module development
  • JNI module
  • Native development tools
  • Linux programming
  • Underlying image processing
  • Audio and video development
  • Machine learning

First, NDK module development

Main contents:

  • Summary of C++ and C# data types
  • C and C++ memory structure and management
  • Preprocessing commands in C and C++ and using typedefs to name existing types
  • C and C++ structure, common body
  • C and C++ Pointers
  • C/C++ multithreading mechanism
  • C/C++ function and initialization list

Two, JNI module

Main contents:

  • Static registration and dynamic registration of JNI development

Static registration, dynamic registration, JNINativeMethod, data type mapping, jNI function default parameters

  • JNI developed method signature to communicate with Java

Android NDK developed JNI type signature and method signature, JNI implementation Java and C/C ++ mutual communication

  • Local references, global references, and weak global references developed by JNI

3. Native development tools

Main contents:

  • Compilers, packaging tools, and profilers

Top 10 most popular React Native application development editor, React-Native packaging process

  • Static libraries versus dynamic libraries

  • CPU architecture and Precautions

ABI management, processing OF CPU functions, NEON support

  • Build scripts and build tools

Environment setup, NDK project, Cmake, Makefile

  • Cross-compile migration

FFmpeg compilation, FFmpeg+LIBX264+FACC cross compilation to achieve 264 streaming recording, porting FFmpeg in arm cross compilation encountered problems, FFmpeg cross compilation, X264 FAAC cross compilation, solve all porting problems

  • AS builds NDK projects

Configure the NDK environment, establish app project, generate. H header file, create C file, implement native method, jni.h file

4. Linux Programming

  • Linux environment setup, system management, permission system and tool use (vim, etc.)

Setting up the Linux environment and managing the Linux system (25 commands)

  • Shell scripting

Shell script, write simple Shell script, process control statement, plan task service program

Five, the bottom picture processing

  • PNG/JPEG/WEBP image processing and compression

Four image formats, recommended several image processing sites, squoosh online lossless image compression tool, JPG/webP/PNG/ intertransfer

  • Wechat picture compression

The original width and height were calculated, the approximate width and height were calculated, the target image was obtained at the first sampling, and the size of the target was approximated circularly

  • Principle and implementation of GIF synthesis

GIF image parsing, GIF image synthesis (sequence image synthesis GIF image)

Vi. Audio and video development

  • Multimedia system

Camera and mobile phone screen capture, image raw data format YUV420(NV21 and YV12, etc.), audio capture and playback system, codec MediaCodec, MediaMuxer reuse and MediaExtractor

  • FFmpeg

Ffmpeg module, audio and video decoding, audio and video synchronization, I frame,B frame,P frame decoding principle, X264 video coding and FAAC audio coding, OpenGL drawing and NativeWindow drawing

  • Streaming protocol

RTMP protocol, P2P WebRtc for audio and video calls

  • OpenGL ES filter developed beauty effects

Gaussian blur, high contrast retention, strong light processing, fusion

  • Analysis and realization of douyin video effect

Process list, video shooting, video editing, and video export

  • Audio and video transmission principle

Variable speed entrance analysis, audio speed, video speed

Machine learning

  • Opencv

  • Image preprocessing

Grayscale and binarization, corrosion and expansion, face detection, ID identification

This material has been open source, need friends to goGitHubDownload.

The last

Due to space restrictions, the detailed information of the document is too comprehensive, too much detail content, so only part of the knowledge point screenshots out a rough introduction, each small node inside there are more detailed content!

In addition to the above, I have compiled the following series of advanced learning materials:

Notes on The Core Knowledge of the Seven Modules of Android Development

2246 Pages Of the Latest Android factory high-frequency interview Questions

This material has been open source, need friends to goGitHubDownload.