jni初试

Jni(java nativeinterface)是java与本地c/c++相互调用的一种方式,称之为java本地调用,由于java是夸平台的,所以在windows与linux以及其他不同的平台,即使是相同的jni函数,他们调用底层c/c++接口也存在差异,但是他们都是先将c/c++代码变成具体平台的动态链接库,供java调用,至于java是怎样去调用动态链接库的,我也不明白,以后研究。这里就先总结一下android工程中java调用linux平台的c/c++代码的一个HelloWorld例子,大体的步骤如下:

1、编写含有native方法的java文件

2、将这个文件生成对应的.class文件,进而生成.h文件

3、将.h文件改写成.c或.cpp文件并且完成jni函数的编写,这里需要的就是从java-->c/c++本地调用的函数的形式以及与.h文件的关联。

4、编写生成动态链接库的mk文件

5、在android工程中新建一个目录如jni,将.c或.cpp和.h和.mk文件放进去

6、编写完整的android工程

7、编写整个android工程的mk文件

8、将整个工程放在源码编译环境下

9、首先进入工程的jni目录执行mk文件,然后返回工程目录执行工程的mk文件

 

编写含有native方法的java文件

这里编写一个类Myjni.java

packagecom.example.jnitest;

public class Myjni {

    public native String getStr();

}

 

将这个文件生成对应的.class文件,进而生成.h文件

将这个文件拷贝到D盘,用命令行的方式生成.h文件。

这里我们的java文件是带包的,所以我们在编译的时候需要带-d参数,如果没有包名则直接javac

Javac  -d  .  Myjni.java

 

将生成的.class文件转变成.h文件

由于java文件是带包名的,所有这里需要在class文件前添加包名,才能找到具体的class文件

就在当前目录执行:Javah  -classpath  . com.example.jnitest.Myjni

《这个是之后加的图,对于包名为com.dxd.test的ABC.java源文件的生成.h文件的过程》

 

当然,如果想自己给生成的.h文件重新一个命名的话,可以指定-o参数

.h文件改写成.c.cpp文件并且完成jni函数的编写,这里需要的就是从java-->c/c++本地调用的函数的形式以及与.h文件的关联

生成的com_example_jnitest_Myjni.h头文件的内容如下

/*DO NOT EDIT THIS FILE - it is machine generated */

#include<jni.h>

/*Header for class com_example_jnitest_Myjni */

 

#ifndef_Included_com_example_jnitest_Myjni

#define_Included_com_example_jnitest_Myjni

#ifdef__cplusplus

extern "C" {

#endif

/*

 * Class:    com_example_jnitest_Myjni

 * Method:   getStr

 * Signature: ()Ljava/lang/String;

 */

JNIEXPORT jstring JNICALL Java_com_example_jnitest_Myjni_getStr

  (JNIEnv *, jobject);

 

#ifdef__cplusplus

}

#endif

#endif

 

我们可以看出,我们需要完善的函数,就是java_com_example_jnitest_Myjni_getStr,那么我们复制一份.h文件,改名为com_example_jnitest_Myjni.c,这里对这个文件稍做修改,这是c方面的知识了,这里就不多说。

#include "com_example_jnitest_Myjni.h"  

JNIEXPORT jstring JNICALL Java_com_example_jnitest_Myjni_getStr

(JNIEnv* env, jobject obj)  

{  

return(*env)->NewStringUTF(env, (char *)"JNITest Native String");  

}  

 

编写生成动态链接库的mk文件

当这里,jni方面的事情就做的差不多了,再需要一个Android.mk文件,我们就可以在linux源码编译环境下生成.so动态链接库了。编写一个Android.mk文件,内容如下。

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES:= \

        $(JNI_H_INCLUDE)

LOCAL_SRC_FILES:= \

    com_example_jnitest_Myjni.c

LOCAL_MODULE_TAGS:= optional

LOCAL_MODULE    := libjni_dxd

include $(BUILD_SHARED_LIBRARY)

 

android工程中新建一个目录如jni,将.c.cpp.h.mk文件放进去

将刚编写好的Android.mk文件和com_example_jnitest_Myjni.h和com_example_jnitest_Myjni.c文件放置于jni目录下

编写完整的android工程

这只是个例子,所有这里就只需要调用一下我们的native方法即可。

Log.e("jnitestgetStr = ", new Myjni().getStr());

 

编写整个android工程的mk文件

这里需要的是在源码环境下编译整个工程的Android.mk文件,内容如下

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS:= optional

LOCAL_SRC_FILES:= $(call all-subdir-java-files)

LOCAL_PACKAGE_NAME:= JNITest

LOCAL_JNI_SHARED_LIBRARIES:= libjni_dxd

include $(BUILD_PACKAGE)

将这个Android.mk文件放置于android工程的目录之下。

 

将整个工程放在源码编译环境下

拷贝整个工程到packages/apps/目录下,去掉工程中的gen、bin、libs目录。

 

首先进入工程的jni目录执行mk文件,然后返回工程目录执行工程的mk文件

首先进入jni目录mm编译jni的mk文件以便生成libjni_dxd.so动态库。

然后返回到工程目录下,mm编码整个android工程,如果成功了的话,就会生成对应的apk文件 。这里必须要先生成动态库,应该编译整个工程时需要这个动态库,如果不事先编译好,整个工程是不能编译通过的,会报找不到动态库的错误。

 

总结:将jni相关的文件放置于工程的jni目录中,在源码下编译工程时是非常方便的!当然这依赖于NDK环境的配置。这里我只做了在linux平台上的jni例子,如果再windows平台的话,需要安装一个在windows平台上模拟linux平台环境的软件cygwin。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值