欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

NDK在Android中的进阶操作

程序员文章站 2022-06-06 17:51:09
...

一、创建一个项目名字叫做JNIDemo,在项目中创建一个类名字叫做JNIDemo,我们编写如下代码:

public class JNIDemo {

    //创建一个方法名字叫做sayHello
    public  native  void sayHello();

}

二、我们要生成JNIDemo类的头文件,输入命令是javah 类的全类名
,具体操作如下图:

NDK在Android中的进阶操作

这样,已经生成头文件,我们来查看头文件的位置.

NDK在Android中的进阶操作

我们来查看一下生成的头文件内容:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xgkj_jnidemo_JNIDemo */

#ifndef _Included_com_xgkj_jnidemo_JNIDemo
#define _Included_com_xgkj_jnidemo_JNIDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_xgkj_jnidemo_JNIDemo
 * Method:    sayHello
 * Signature: ()V;
 */
JNIEXPORT void JNICALL Java_com_xgkj_jnidemo_JNIDemo_sayHello
  (JNIEnv **, jobject);

#ifdef __cplusplus
}
#endif
#endif

在生成头文件的时候我们常遇见的问题进行总结:

(1)第一个错误,我们进行到 app/build/intermediates/classes中我们进行把类的全类名拷贝出来。app/build/intermediates/classes/debug/com/xgkj/jnidemo/JNIDemo.class

在上面标红的内容中存在两个错误,第一个错误,我们不能带.class后缀,当我们把.class后缀去掉后去执行命令,会报错如下图:
NDK在Android中的进阶操作

(2)第二个错误,有许多人在 app/src/包名 这个里面进行生成头文件,报错如下图:

NDK在Android中的进阶操作

同时,在src中生成也是如上错误。

三、我们在main下面来进行创建一个jni文件夹,里面创建一个文件,名字叫做jnidemo.cpp

在这步我们要进行引入头文件和使用的c库。具体代码如下

// jnidemo.cpp : Defines the entry point for the DLL application.
//

#include "../../../src/main/jni/com_xgkj_jnidemo_JNIDemo.h"
#include <stdlib.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>

#define  LOG_TAG    "native-dev"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

JNIEXPORT void JNICALL Java_com_xgkj_jnidemo_JNIDemo_sayHello
        (JNIEnv ** env, jobject obj){
    LOGE("Hello World");
}

(1)在引入头文件的时候我们常范的错误

no implementation found for native应用包名 ()v

会报上述类型的错误,意思就是说在没有实现该方法的签名。那这个问题如何解决呢?

我们检查一下我们实现生成的头文件方法与生成的头文件方法一样,务必要保证实现的方法与生成的方法一样。

四、我们要安装一下CMake和 LLDB插件

NDK在Android中的进阶操作

我们按照如图的三步操作,就可以把这两个插件生成出来了呢?

(1)那为什么要安装这两个插件呢?

在Android Studio中2.3版本以后我们要引用 .cpp 文件需要创建一个CMakeLists.txt 文件;
LLDB插件是主要我们在创建项目的时候可以让系统帮助我们生成CMakeLists.txt并配置好的操作。

(2)我们来介绍一下LLDB在项目创建的时候进行自动给我们生成CMakeLists.txt等相关的配置操作

步骤一:我new project ,具体的操作我们看下图
NDK在Android中的进阶操作

通过这三步操作,编译器就会给我们自动生成CmakeLists.txt等相关的配置。

五、我们在app的目录下面进行创建一个CMakeLists.txt文件,中文注释的地方可以替换自己的库名字,并编写如下内容:

# 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.
             sayHello #本地库的名字,即使你即将编译出来的.so库名字

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/jni/jnidemo.cpp ) #C/C++在项目中的位置

# 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  #这个是添加的log输出库,可以进行log输出

              # 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.
                       sayHello #输出的目标库

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

六、在app/build.gradle进行相关的配置

(1)app/build.gradle中进行配置,在defaultConfig中添加如下代码:

       ndk {
            moduleName "sayHello"
            ldLibs "log"
            abiFilters "armeabi","armeabi-v7a","x86"
        }

        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }

(2)在app/build.gradle中进行配置,在android中添加如下代码:

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

(3)进行如下图操作:

NDK在Android中的进阶操作

(4)编辑成功我们会在下图看见,如下cmake文件并在intermediates

NDK在Android中的进阶操作

七、在MainActivity中加载.so文件,我们可以看一下MainActivity的代码:

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("sayHello");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        try{
            JNIDemo jniDemo = new JNIDemo();
            jniDemo.sayHello();
        }catch (Exception e){
            Log.e("JNIDemo", "onCreate: "+e.toString() );
        }

    }
}

运行成功我们可以看一下打印结果:

NDK在Android中的进阶操作

到此,Android中NDK操作进阶操作介绍完成。

下载Demo请点击此处文字:JNIDemo

相关标签: ndk