NDK在Android中的进阶操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liu_jing_hui/article/details/79122943

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

public class JNIDemo {

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

}

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

这里写图片描述

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

这里写图片描述

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

/* 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后缀去掉后去执行命令,会报错如下图:
这里写图片描述

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

这里写图片描述

同时,在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插件

这里写图片描述

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

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

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

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

步骤一:我new project ,具体的操作我们看下图
这里写图片描述

通过这三步操作,编译器就会给我们自动生成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)进行如下图操作:

这里写图片描述

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

这里写图片描述

七、在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() );
        }

    }
}

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

这里写图片描述

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

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

猜你喜欢

转载自blog.csdn.net/liu_jing_hui/article/details/79122943