Android-NDK开发示例--通过JNI获取MD5码

JAVA中获取MD5码

     对于MD5码,大家一定耳熟能详了,这里也不多做解释,由于在JDK中有相关封装,所以在java代码中很简单就可以获取,获取32位MD5如下:

public static String encrypt(String str) {
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance("MD5");
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		char[] charArray = str.toCharArray();
		byte[] byteArray = new byte[charArray.length];

		for (int i = 0; i < charArray.length; i++) {
			byteArray[i] = (byte) charArray[i];
		}
		byte[] md5Bytes = md5.digest(byteArray);

		StringBuffer hexValue = new StringBuffer();
		// 写法(1),忒不专业,不推荐////////////////////
		// for (int i = 0; i < md5Bytes.length; i++) {
		// int val = ((int) md5Bytes[i]) & 0xff;
		// if (val < 16) {
		// hexValue.append("0");
		// }
		// hexValue.append(Integer.toHexString(val));
		// }
		// 写法(2)/////////////////////////
		// for (int i = 0; i < arr.length; ++i) {
		// sb.append(Integer.toHexString((arr[i] & 0xFF) | 0x100).substring(1,
		// 3));
		// }
		// 写法(3)/////////////////////////////////////
		// for (byte b : toencode) {
		// sb.append(Integer.toHexString((b & 0xf0) >>> 4));
		// sb.append(Integer.toHexString(b & 0x0f));
		// }
		// 写法(4) 封装好的格式化方法自有它的道理//////////////////
		for (int i = 0; i < md5Bytes.length; i++) {
			hexValue.append(String.format("%02x", ((int) md5Bytes[i]) & 0xff));
		}
		return hexValue.toString();
	}
    对于在代码里字符串的转换拼接过程,写法(1)网上疯传,但感觉好土,不建议大家使用,另外还有 写法(2)(3)(4),如果你是C转java的可能更习惯后面的,不纠结这个了,其实都可以,都列出来供大家参考吧。

    既然java这么简单就可以获取md5码了,那干嘛还用jni调用C代码呢?这里只是把我在学习基于Android-NDK开发起步的一个小例子,大家就不要纠结这个了,就当做Hello-Jni吧

NDK开发环境搭建

1.Android基本环境(此处省略N字大笑

2.下载下载安装Android NDK

   官方已经是r8e版本了,不过我没下载最新的,区别不大,对这个例子不会有影响。NDK全称:Native Development Kit,所以下载完就像对待sdk那样对待它就行了,找个目录解压,不过路径不要有中文和空格,不然日后会有麻烦,这个习惯一定要养成哦,前车之鉴。

3.下载安装cygwin

我这里有精简的离线版20多M,有需要的可以联系我

4.配置NDK环境变量 

 由于我安装配置过程没有截图,详情参考:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/13/2136982.html

编码工作

1.java代码中编写native 函数接口:

	/**
	 * getInfoMD5: native方法,在C代码里实现
	 */
	public static native String getInfoMD5(String info);
2.编译程序,确保bin目录已生成

3.打开cmd命令窗口,跳转到项目bin/classes目录下,使用  javah +包名+类名命令,回车,如无任何错误信息,则头文件生成成功。

4.项目中新建jni文件夹,打开classes目录找到.h文件复制进来,头文件格式如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jerome_jni_JNIProcess */

#ifndef _Included_com_jerome_jni_JNIProcess
#define _Included_com_jerome_jni_JNIProcess
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jerome_jni_JNIProcess
 * Method:    getInfoMD5
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jerome_jni_JNIProcess_getInfoMD5
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

(相当于java中的接口)

5.C编码对头文件中的方法进行实现

/*
 * Class:     com_jerome_jni_JNIProcess
 * Method:    getInfo
 * Signature: (Ljava/lang/String;I)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jerome_jni_JNIProcess_getInfoMD5(JNIEnv* env,
		jclass clazz, jstring jInfo) {
	char* jstr = Jstring2CStr(env, jInfo);

	MD5_CTX context = { 0 };
	MD5Init(&context);
	MD5Update(&context, jstr, strlen(jstr));
	unsigned char dest[16] = { 0 };
	MD5Final(dest, &context);

	int i;
	char destination[32]={0};
	for (i = 0; i < 16; i++) {
		sprintf(destination, "%s%02x", destination, dest[i]);
	}
	LOGI("%s", destination);
	return (*env)->NewStringUTF(env, destination);
}

其中MD5为开源库,很容易就能找到,我不懂C,不是自己写的,惭愧。

描述和编译

 android.mk文件用于告知编译系统编译信息:
(1)Android.mk文件首先需要指定LOCAL_PATH变量,用于查找源文件

由于一般情况下Android.mk和需要编译的源文件在同一目录下,所以定义成如下形式:
LOCAL_PATH:=$(call my-dir)
上面的语句的意思是将LOCAL_PATH变量定义成本文件所在目录路径。
(2)Android.mk中可以定义多个编译模块,每个编译模块都是以include $(CLEAR_VARS)开始
以include $(BUILD_XXX)结束。

include $(CLEAR_VARS)
CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除除LOCAL_PATH以外的所有LOCAL_XXX变量,
如LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_SHARED_LIBRARIES,LOCAL_STATIC_LIBRARIES等。
include $(BUILD_STATIC_LIBRARY)表示编译成静态库
include $(BUILD_SHARED_LIBRARY)表示编译成动态库。
include $(BUILD_EXECUTABLE)表示编译成可执行程序

对于动态库静态库我的理解还很浅显,希望对这方面研究透彻的童鞋能给些指点。

makefile文件还有很多内容,后续继续研究分享

好了,一切准备完毕就可以编译了,打开cygwin cd到项目根目录(温馨提示:cygwin 中,我们的磁盘在 /cygdrive下),执行ndk-build(这里根据你配置的不同而不同,你或许要这样$NDK/ndk-build
),如果看到这样的结果,那恭喜你,编译成功!

Android-NDK开发示例--通过JNI获取MD5码_第1张图片

函数调用跟普通函数相同,有个前提就是调用之前在类中或调用方法的Activity中先静态加载:

	static {
		System.loadLibrary("process");
	}
library名称为你所实现接口的那个c文件的名称。
项目源码已上传,刚刚接触ndk,有不对的地方还望批评指正,也希望能跟一起奋斗在代码里的朋友有更多的交流,来提升自己,您的批评是我前进的动力!大笑

你可能感兴趣的:(android,MD5,jni)