首页 > 代码库 > Android JNI
Android JNI
Android APP中时常用到JNI(java本地调用),如果接触过反编译方面的知识,肯定会觉得Android APP是如此地透明。
本文主要总结Android APP用JNI的两种方式,第一种就是在源码下编译源文件生成.so文件 ;第二种是Eclipse配置NDK,不管是哪种方式都有以下的步骤:
1、编写包含native方法的java文件,native关键字申明的方法即是JNI方法。
2、将此java文件通过javac和javah命令转成.h文件
3、通过.h文件来编写.c文件
4、编写Android.mk文件
5、编译生成.so文件
不同的在于生成.so文件的方式,如果Eclipse中配置了NDK的话,每次刷新或者是clean都会自动去执行Android.mk文件生成.so文件,如果是在源码下编译的话,需要你有linux环境,在linux环境下编译源文件生成.so库。
这里说一下详细的步骤,方便以后查阅:
1、编写java文件SignUtil
package com.dxd.jnidemo; public class SignUtil { protected static native String getMD5(String str) ; }2、通过java文件生成.h文件
将java文件拷贝至你喜欢的目录,这里我拷贝到了桌面的jni目录,执行如下命令生成.h文件
3、通过.h文件来编写.c文件
我这里的.h文件名为com_dxd_jnidemo_SignUtil.h从这个名字可以看出SignUtil.java文件所属的包名,这个头文件的内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_dxd_jnidemo_SignUtil */ #ifndef _Included_com_dxd_jnidemo_SignUtil #define _Included_com_dxd_jnidemo_SignUtil #ifdef __cplusplus extern "C" { #endif /* * Class: com_dxd_jnidemo_SignUtil * Method: getMD5 * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_dxd_jnidemo_SignUtil_getMD5 (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif我们可以看到有一个方法的声明为JNIEXPORT jstring JNICALL Java_com_dxd_jnidemo_SignUtil_getMD5(JNIEnv *, jclass ,jstring) ;
是的,他就是jni方法。现在来实现这个接口,创建一个名叫com_dxd_jnidemo_SignUtil.c的c文件,内容如下:
#include <jni.h> JNIEXPORT jstring JNICALL Java_com_dxd_jnidemo_SignUtil_getMD5 (JNIEnv *env, jclass jcls, jstring jstr){ return(*env)->NewStringUTF(env, (char *)"Just a Demo!"); }4、编写Android.mk文件,名字就叫Android.mk。
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_C_INCLUDES:= $(JNI_H_INCLUDE) LOCAL_SRC_FILES:= com_dxd_jnidemo_SignUtil.c LOCAL_MODULE_TAGS:= optional LOCAL_MODULE:= libsign_dxd include $(BUILD_SHARED_LIBRARY)
5A、Android源码下编译
将.h文件.c文件和Android.mk文件一起拷贝到android源码环境的某个目录,然后进入到该目录mm命令进行编译即可,将生产的libsign_dxd.so文件拷贝至Android工程libs/armeabi目录下。在java代码static块中加载该.so库时,只需要写成System.loadLibrary("sign_dxd") ;即可。前面的lib和后缀名可以省略。然后调用native方法就可以了。
5B、Eclipse中配置了NDK坏境
在Android主目录下新建一个目录叫jni,建议取这个名字,方便理解,然后将.h文件.c文件和Android.mk文件拷贝至其中。
在Android工程的libs目录下新建一个目录armeabi,好!如果NDK环境是配置成功的,那么当你刷新工程或是clean工程之后,就会在libs/armeabi下生成libsign_dxd.so文件,当我run工程的时候,.so文件就自动编译到apk中了。关于Eclipse中NDK的配置网上教程很多,我现在用的是Eclipse(内置CDT) + NDK r7b,别忘了,当不能生成.so文件时,要去查看是否为该android工程指定了NDK环境。
关于NDK的配置,我抄了某网友的博文,大体如下:
1、下载NDK 后在你喜欢的目录解压它。
2、打开Eclipse,新建一个android工程我这里是TestNdk,并在这个工程主目录下新建一个jni目录,该目录时用来存放.h .c 和Android.mk文件的
3、在弹出的【Edit Configuration】对话框中,配置选项卡【Main】。
在“Name“中输入新builders的名称(我取名为Ndk_Builder)。
在“Location”中输入nkd-build.cmd的路径。
(我的是D:\AndroidDev\android-ndk-r7b\ndk-build.cmd,根据各自的ndk路径设置,也可以点击“Browser File System…”来选取这个路径)。
在“Working Diretcoty”中输入${workspace_loc:/TestNdk}(也可以点击“Browse Workspace”来选取TestNdk目录)。
4、【Edit Configuration】对话框中,配置选项卡【Refresh】。
勾选“Refresh resources upon completion”,
勾选“The entire workspace”,
勾选“Recuresively include sub-folders”。
5、【Edit Configuration】对话框中,配置选项卡【Build options】。
勾选“After a “Clean””,
勾选“During manual builds”,
勾选“During auto builds”,
勾选“Specify working set of relevant resources”。
6、点击“Specify Resources…”
勾选TestNdk工程的“jni“目录,点击”finish“。
点击“OK“,完成配置。
OK,到这里Eclipse就能够自动调用NDK编译jin目录下的C/C++代码了。