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++代码了。

Android JNI,,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。