Android JNI de 0 a 1 Tutorial de introducción (2)

Después de la introducción del anterior " Tutorial de introducción a Android JNI de 0 a 1 (1) ", tenemos una comprensión preliminar de JNI. A continuación, presentaré cómo crear bibliotecas nativas a partir del método ndk-build y el método cmake:

Este artículo utiliza el entorno de desarrollo:

Estudio Android 4.0+

compilar SDK 33

gradle 7.2.1

1. compilación de ndk

ndk-build depende del archivo de configuración Android.mk, y la ubicación donde se almacena el código suele ser el directorio jni

1. Crear una nueva clase de prueba de Java

package com.example.jni;

public class JNIDemo {

    static {
        //这个库名必须跟Android.mk的LOCAL_MODULE对应
        System.loadLibrary("JniDemo");
    }

    public static native String test();
}

2. Crea el directorio jni

3. Generar archivo .h

Abra la línea de comando, cambie al directorio java del proyecto y use el siguiente comando para generar el archivo de encabezado .h. (Si no hay un comando javah, primero configure la variable de entorno jdk)

javah -d ../jni com.example.jni.JNIDemo

Los archivos generados aparecerán en el directorio jni

 4. Implementar funciones específicas de C++

Cree un nuevo archivo .cpp en el directorio jni con el siguiente contenido

#include "com_example_jni_JNIDemo.h" //引入刚刚生成的头文件

extern "C"
//实现test函数实际功能
JNIEXPORT jstring JNICALL Java_com_example_jni_JNIDemo_test(JNIEnv * env, jclass clz){
    return env->NewStringUTF("hello world");
}

 5. Configurar Android.mk y Application.mk

Cree estos dos archivos en el directorio jni.El contenido de los archivos es el siguiente:

Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#定义要构建生成的本地库的名称,以下示例会生成名为 libJniDemo.so 的库。
LOCAL_MODULE := JniDemo

#指定源代码文件
LOCAL_SRC_FILES := \
JNITest.cpp \

include $(BUILD_SHARED_LIBRARY)

 Aplicación.mk

#指定用于此应用的 C++ 标准库,默认情况下使用 system STL。其他选项包括 c++_shared、c++_static 和 none
APP_STL := c++_shared
APP_CPPFLAGS := -frtti -fexceptions
# APP_ABI:指定生成哪些cpu类型的so, all代表全部 常用的有:armeabi-v7a,arm64-v8a,x86,x86_64
APP_ABI := armeabi-v7a arm64-v8a
#APP_PLATFORM 会声明构建此应用所面向的 Android API 级别,并对应于应用的 minSdkVersion
APP_PLATFORM := android-21

Nota : Gradle  externalNativeBuild lo ignorará  APP_ABI. Utilice  bloques o fragmentos dentro de  bloques ndk  (consulte la configuración a continuación).abiFiltersabi

6. Generar archivo .so

Puede usar directamente el comando ndk-build para compilar o puede configurar un acceso directo en AndroidStudio. (Este ejemplo usa la versión 21.4.7075529 de ndk)

(1) Compilación con el comando de compilación
Cambie la consola al directorio jni, es decir, el directorio que contiene Android.mk y Application.mk, ejecute el comando ndk-build y podrá encontrarlo en la carpeta libs después del éxito. (Si no hay un comando ndk-build, primero debe configurar la variable de entorno ndk)

(2) Configurar herramientas de acceso directo

Abra Archivo-Configuración-Herramientas-Herramientas externas, agregue una nueva herramienta, asígnele el nombre ndk-build (nómbrelo a voluntad) y seleccione ndk-build.cmd en el directorio donde se encuentra su ndk en la configuración del programa, que generalmente es instalado en su AndroidStudio El directorio ndk debajo del directorio, el directorio de trabajo llena el directorio jni del proyecto

Haga clic para ejecutar ndk-build para generar el archivo .so

 7. Usa métodos nativos en el código

public class MainActivity extends AppCompatActivity {

    private TextView tvMsg;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvMsg = findViewById(R.id.tv_msg);
        //调用native方法
        String msg = JNIDemo.test();
        tvMsg.setText(msg);
    }
}

Si está utilizando una versión anterior de Gradle, debe agregar la siguiente configuración en build.gradle del módulo de la aplicación para vincular la biblioteca so (la biblioteca generada debe colocarse en el directorio libs):

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
   
    //...其他省略

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

dependencies {

    //...其他省略
}

 2. CHacer

Lo anterior describe ndk-build, ahora hablemos sobre cómo configurar CMake

1. Agregue el archivo CMakeLists.txt

Cree un nuevo archivo CMakeLists.txt en el directorio raíz del módulo de la aplicación del proyecto y complete el siguiente contenido:

#指定CMake的最低版本要求
cmake_minimum_required(VERSION 3.18.1)

# 定义本地库的名称
set(my_lib_name JniDemo)

#添加库配置,如果有多个库,可以添加多个add_library方法
add_library( # 指定生成库的名称,使用上面定义的变量
        ${my_lib_name}
        # 标识是静态库还是动态库 STATIC:静态库 SHARED:动态库
        SHARED
        # C/C++源代码文件路径
        src/main/cpp/JNITest.cpp)

#指定.h头文件的目录
include_directories(src/main/cpp/)

# 指定构建输出路径
set_target_properties(${my_lib_name} PROPERTIES
        LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}")

# 链接外部静态库(如果你的静态库或动态库依赖于其他库或依赖项)
target_link_libraries(MyStaticLibrary PRIVATE MyExternalStaticLibrary)

Las funciones en los ejemplos add_libraryse usan para especificar la biblioteca nativa para compilar y sus archivos de código fuente. target_link_librariesLa función se usa para especificar la biblioteca del sistema que se vinculará, como logla biblioteca, que se usa para usar la función de registro de Android en código nativo.

Finalmente, a través de set_target_propertiesla función, puede especificar la ruta de salida de la biblioteca compartida generada y colocarla en libs/${ANDROID_ABI}el directorio, que ${ANDROID_ABI}es una variable de CMake que representa la ABI (interfaz binaria de la aplicación) de la plataforma de destino actual.

Para obtener más elementos de configuración de CMakeLists.txt, consulte Configuración de Cmake

2. Agregue la configuración externalNativeBuild y ndk en build.gradle en el módulo de la aplicación

android {
    compileSdk 33

    defaultConfig {
        applicationId "com.example.jni"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        ndk {
            //指定编译的ABI平台
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
        }
    }

    externalNativeBuild {
        cmake {
            //指定CMakeLists文件所在位置
            path "CMakeLists.txt"
        }
    }
  //...省略
}

3. Agregar archivos C++

CMake generalmente usa el directorio cpp en lugar del directorio jni, así que cree un nuevo directorio cpp en el directorio src/main y luego coloque los archivos .h y .cpp en él.

 4. Generar archivo .so

Utilice Rebuild Project of AS para compilar el proyecto, es decir, el archivo SO correspondiente se puede generar en el directorio libs.

 Bueno, hasta ahora se ha terminado la introducción de los dos métodos.

Para obtener más información sobre la configuración, consulte la documentación oficial de Google.

posdata

En el proceso anterior, involucramos dos conceptos: biblioteca dinámica y biblioteca estática.

Durante el proceso de compilación del NDK, estos son dos métodos diferentes de generación de archivos de biblioteca.

1. Biblioteca dinámica (Biblioteca dinámica):

  • Una biblioteca dinámica es un archivo de biblioteca que se carga y vincula a una aplicación en tiempo de ejecución. En Android NDK, la extensión de archivo de la biblioteca dinámica suele ser  .so(Objeto compartido).
  • Las bibliotecas dinámicas pueden ser compartidas por múltiples aplicaciones o módulos para reducir el espacio en disco y el uso de memoria. Múltiples aplicaciones pueden cargar y usar la misma biblioteca dinámica al mismo tiempo.
  • La carga y vinculación de la biblioteca dinámica se lleva a cabo en tiempo de ejecución, lo que significa que los archivos de la biblioteca pueden cargarse y reemplazarse dinámicamente durante la ejecución de la aplicación, lo que permite la conveniencia de la actualización y el mantenimiento.
  • En el NDK de Android, las bibliotecas dinámicas se generan mediante compiladores de C/C++ y  ndk-build se compilan y compilan mediante herramientas de compilación como CMake o CMake.

2. Biblioteca estática:

  • Una biblioteca estática es un archivo de biblioteca que está vinculado a una aplicación en tiempo de compilación. En el NDK de Android, la extensión de archivo de la biblioteca estática suele ser  .a(Archivo).
  • Las bibliotecas estáticas se copian en el ejecutable cuando se compila la aplicación, y cada aplicación que usa una biblioteca estática incluye una copia completa de la biblioteca.
  • La ventaja de las bibliotecas estáticas es que pueden proporcionar archivos ejecutables independientes sin depender de archivos de bibliotecas externas. Puede ser un poco mejor que una biblioteca dinámica en rendimiento, porque la función de llamada de la biblioteca estática es directa, sin el proceso de enlace dinámico.
  • En el NDK de Android, las bibliotecas estáticas también se generan mediante compiladores de C/C++ y  ndk-build se compilan y compilan mediante herramientas de compilación como CMake o CMake.

En el desarrollo de Android NDK, puede elegir usar bibliotecas dinámicas o bibliotecas estáticas según sus necesidades. Las bibliotecas dinámicas son adecuadas para escenarios en los que varias aplicaciones comparten archivos de biblioteca para facilitar la actualización y el mantenimiento, mientras que las bibliotecas estáticas son adecuadas para escenarios que requieren archivos ejecutables independientes, optimización del rendimiento y no necesitan depender de bibliotecas externas.

Supongo que te gusta

Origin blog.csdn.net/gs12software/article/details/131636204
Recomendado
Clasificación