NDK在Android中的进阶操作
一、创建一个项目名字叫做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
推荐阅读
-
Android在高jar包版本的工程中修改方法
-
在Python程序中操作MySQL的基本方法
-
Android 在子线程中更新UI的几种方法示例
-
在ASP.NET 2.0中操作数据之六:编程设置ObjectDataSource的参数值
-
在ASP.NET 2.0中操作数据之十:使用 GridView和DetailView实现的主/从报表
-
在ASP.NET 2.0中操作数据之十一:基于数据的自定义格式化
-
在ASP.NET 2.0中操作数据之十七:研究插入、更新和删除的关联事件
-
在ASP.NET 2.0中操作数据之十八:在ASP.NET页面中处理BLL/DAL层的异常
-
在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息
-
在ASP.NET 2.0中操作数据之十四:使用FormView 的模板