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
),如果看到这样的结果,那恭喜你,编译成功!
函数调用跟普通函数相同,有个前提就是调用之前在类中或调用方法的Activity中先静态加载:
static {
System.loadLibrary("process");
}
library名称为你所实现接口的那个c文件的名称。