使用NDK进行JNI编程
2017-06-16 10:55
113 查看
jni编程是进阶必不可少的技能,今天就一起来探讨一下具体的编程步骤:
1.下载配置NDK
具体怎么配置我就不啰嗦了,提供一个下载地址:http://pan.baidu.com/s/1mhMX70O
2.声明native方法
新建一个类,声明navite方法:
/** * 声明native方法 */
public
classJniTest {
static {
System.loadLibrary("jni-test");
}
public
staticvoid
main(String args[]) {
JniTest jniTest = new JniTest();
System.out.print(jniTest.getFromJni());
jniTest.setIntoJni("hello world");
}
publicnative String
getFromJni();
publicnative
voidsetIntoJni(String info);
}
3.编译源文件得到.class文件.导出.h头文件
先看看工程目录:D:/as/UIdemo/JniDemo/jni_lib/src/main/Java/com/example/jniTest.java
通过cmd 进入到合适的目录位置,为什么会说合适的位置呢,因为如果不在合适的位置的话 后面的javah命令可能会报一些错,这里我们进入到D:/as/UIdemo/JniDemo/jni_lib/src/main/java这个目录就可以了,然后进行编译:
这样就得到了.class文件和.h头文件:
看看.h文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lin_jnidemo_JniTest */
#ifndef _Included_com_lin_jnidemo_JniTest
#define _Included_com_lin_jnidemo_JniTest
#ifdef __cplusplusextern"C"{
#endif
/* * Class: com_lin_jnidemo_JniTest
* Method: getFromJni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALLJava_com_lin_jnidemo_JniTest_getFromJni
(JNIEnv *, jobject);
/*
* Class: com_lin_jnidemo_JniTest
* Method: setIntoJni
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALLJava_com_lin_jnidemo_JniTest_setIntoJni
(JNIEnv *, jobject, jstring);#ifdef __cplusplus
}
#endif
#endif
在.h头文件中函数名格式是Java_包名类名方法名;
JNIEnv *表示一个指向JNI环境的指针,通过它可以访问JNI接口提供的方法;
jobject:表示Java中的this;
JNIEXPORT 和 JNICALL:JNI中所定义的宏;
extern “C”:表示内部的函数采用c语言的命名风格来编译
4.实现声明的native方法,配置Android.mk和Application.mk文件
在工程的主目录下创建一个子目录,然后将.h头文件复制到此目录中,接着创建test.c、android.mk和Application.mk文件;
test.c如下:
/*#include是编译预处理指令,就是在编译前将stdio.h这个文件里的函数都添加到你写的cpp文件中,然后参与编译,生成.obj文件。如果没有这个指令,你用到的一些方法时编辑器就会报错:*/
#include <jni.h>
#include <stdio.h>
jstring Java_com_lin_jnidemo_JniTest_getFromJni
(JNIEnv *env, jobject thiz){
printf("getFromJni is load")
return
(*env)->NewStringUTF(env,"i am from jni ");
};
void Java_com_lin_jnidemo_JniTest_setIntoJni
(JNIEnv *env, jobject thiz, jstring string){
printf("setIntoJni is load")
(*env)->ReleaseStringUTFChars(env, string,"setintojni");
};
Android.mk
LOCAL_PATH:=$(call my-dir)
#清除之前的一些系统变量
include$(CLEAR_VARS)
# 编译的源文件
LOCAL_SRC_FILES:=test.c
# 编译生成的目标对象 用来给java调用的模块名,
LOCAL_MODULE:= jni-test
#指明要编译成动态库
include$(BUILD_SHARED_LIBRARY)
Application.mk:
#默认情况下NDK会编译产生各个CPU平台的so库
#指定so库的CPU平台的类型 all标识编译所有平台
APP_ABI := all
APP_ABI 可以指定so库的CPU平台的类型,常见的架构平台有armeabi,x86和mips,编译的时候尽量这三种都编译,以免在不同cpu平台报出UnsatisfiedLinkError
错误;
5.通过ndk-build命令编译产生so库文件
准备工作已经差不多了,接下来通过ndk-build命令编译产生so库文件:
这个时候在主目录会自动生成libs目录和obj目录,里面装的就是生成的so库文件:
到此一个基本的通过NDK进行JNI编程就完成了,看一下运行效果:
有不足之处,请多多指教,本来新手.
1.下载配置NDK
具体怎么配置我就不啰嗦了,提供一个下载地址:http://pan.baidu.com/s/1mhMX70O
2.声明native方法
新建一个类,声明navite方法:
/** * 声明native方法 */
public
classJniTest {
static {
System.loadLibrary("jni-test");
}
public
staticvoid
main(String args[]) {
JniTest jniTest = new JniTest();
System.out.print(jniTest.getFromJni());
jniTest.setIntoJni("hello world");
}
publicnative String
getFromJni();
publicnative
voidsetIntoJni(String info);
}
3.编译源文件得到.class文件.导出.h头文件
先看看工程目录:D:/as/UIdemo/JniDemo/jni_lib/src/main/Java/com/example/jniTest.java
通过cmd 进入到合适的目录位置,为什么会说合适的位置呢,因为如果不在合适的位置的话 后面的javah命令可能会报一些错,这里我们进入到D:/as/UIdemo/JniDemo/jni_lib/src/main/java这个目录就可以了,然后进行编译:
这样就得到了.class文件和.h头文件:
看看.h文件:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lin_jnidemo_JniTest */
#ifndef _Included_com_lin_jnidemo_JniTest
#define _Included_com_lin_jnidemo_JniTest
#ifdef __cplusplusextern"C"{
#endif
/* * Class: com_lin_jnidemo_JniTest
* Method: getFromJni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALLJava_com_lin_jnidemo_JniTest_getFromJni
(JNIEnv *, jobject);
/*
* Class: com_lin_jnidemo_JniTest
* Method: setIntoJni
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALLJava_com_lin_jnidemo_JniTest_setIntoJni
(JNIEnv *, jobject, jstring);#ifdef __cplusplus
}
#endif
#endif
在.h头文件中函数名格式是Java_包名类名方法名;
JNIEnv *表示一个指向JNI环境的指针,通过它可以访问JNI接口提供的方法;
jobject:表示Java中的this;
JNIEXPORT 和 JNICALL:JNI中所定义的宏;
extern “C”:表示内部的函数采用c语言的命名风格来编译
4.实现声明的native方法,配置Android.mk和Application.mk文件
在工程的主目录下创建一个子目录,然后将.h头文件复制到此目录中,接着创建test.c、android.mk和Application.mk文件;
test.c如下:
/*#include是编译预处理指令,就是在编译前将stdio.h这个文件里的函数都添加到你写的cpp文件中,然后参与编译,生成.obj文件。如果没有这个指令,你用到的一些方法时编辑器就会报错:*/
#include <jni.h>
#include <stdio.h>
jstring Java_com_lin_jnidemo_JniTest_getFromJni
(JNIEnv *env, jobject thiz){
printf("getFromJni is load")
return
(*env)->NewStringUTF(env,"i am from jni ");
};
void Java_com_lin_jnidemo_JniTest_setIntoJni
(JNIEnv *env, jobject thiz, jstring string){
printf("setIntoJni is load")
(*env)->ReleaseStringUTFChars(env, string,"setintojni");
};
Android.mk
LOCAL_PATH:=$(call my-dir)
#清除之前的一些系统变量
include$(CLEAR_VARS)
# 编译的源文件
LOCAL_SRC_FILES:=test.c
# 编译生成的目标对象 用来给java调用的模块名,
LOCAL_MODULE:= jni-test
#指明要编译成动态库
include$(BUILD_SHARED_LIBRARY)
Application.mk:
#默认情况下NDK会编译产生各个CPU平台的so库
#指定so库的CPU平台的类型 all标识编译所有平台
APP_ABI := all
APP_ABI 可以指定so库的CPU平台的类型,常见的架构平台有armeabi,x86和mips,编译的时候尽量这三种都编译,以免在不同cpu平台报出UnsatisfiedLinkError
错误;
5.通过ndk-build命令编译产生so库文件
准备工作已经差不多了,接下来通过ndk-build命令编译产生so库文件:
这个时候在主目录会自动生成libs目录和obj目录,里面装的就是生成的so库文件:
到此一个基本的通过NDK进行JNI编程就完成了,看一下运行效果:
有不足之处,请多多指教,本来新手.
相关文章推荐
- 安卓复习之旅—使用NDK进行JNI编程
- 无需cygwin,使用NDK进行开发
- 使用系统libsqlite.so 进行ndk 开发
- 使用Android Studio 1.3 版本进行NDK开发
- 使用最新版AndroidStudio2.0进行NDK开发并且链接第三方so库
- 使用Android Studio进行NDK开发
- 使用系统libsqlite.so 进行ndk 开发
- 使用Android Studio 进行NDK开发和Debug
- 使用Android Studio进行NDK开发
- Android 使用Android Studio进行NDK-JNI开发
- 使用Android Studio 1.3 版本进行NDK开发 编译运行hello-jni项目及分析
- 使用 Android Studio 进行 NDK 开发
- 【Android Native Code开发系列】七 使用NDK进行交叉编译 & 编译ACE for android
- android 使用NDK进行图像处理(openCV)时的图像转换问题(灰度图显示)
- 使用NDK进行网络文件传输
- Android:Native C源码(NDK)如何使用sqlite3进行编程?
- 无需cygwin,使用NDK进行开发
- 使用系统libsqlite.so 进行ndk 开发
- 使用O-LLVM和NDK对Android应用进行混淆
- 使用Android Studio 进行NDK开发和调试