首页 > 代码库 > 编程基础知识——Java JNI开发流程(2)
编程基础知识——Java JNI开发流程(2)
android中使用jni调用本地C++库
android平台上的本地库文件后缀 .so。类似windows上的dll文件。
要在android上使用jni,首先需要下载android ndk。
操作步骤,正常建立android工程,然后在android工程那里右键,属性,选择Android Tools -> Add Native Support。就可以为android工程增加本地库支持。
添加支持后的android工程,会增加jni目录,C++代码就写在这个目录里。
新建一个类,并且使用native修饰一个函数。这个函数就是需要本地库来实现的。本例子中的本地库函数作用是将字符串进行内置算法转换,服务器可根据这个转换识别客户端的合法性,使用jni的目的是增加代码反编译破解的复杂度。
package com.show.shownative.lib; public class ShowNativeLib { public native String showConvertCode(String param); }
使用javah生成头文件:ShowNativeLib.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_show_shownative_lib_ShowNativeLib */ #ifndef _Included_com_show_shownative_lib_ShowNativeLib #define _Included_com_show_shownative_lib_ShowNativeLib #ifdef __cplusplus extern "C" { #endif /* * Class: com_show_shownative_lib_ShowNativeLib * Method: showConvertCode * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_show_shownative_lib_ShowNativeLib_showConvertCode (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
在android的native工程设置中需要 mk文件类进行编译配置。本例子中需要用到三个MK ,系统会为你自动创建一个,照着路径新建两个就可以了
1、Application.mk 内容如下
APP_STL := stlport_static APP_ABI := armeabi armeabi-v7a mips x86
以上两行配置说明:第一个是增加C++ STL模版支持。第二个是设置需要为哪几种CPU架构编译so文件。
2、Android.mk 内容如下
LOCAL_PATH := $(call my-dir) include $(LOCAL_PATH)/ShowNativeLib.mk
以上的配置,第一行是死的。第二行是一个多模块引入方式,如果你还有其他本地库模块,可以分模块。这里include就行了。
3、ShowNativeLib.mk 内容如下
include $(CLEAR_VARS) LOCAL_MODULE := ShowNativeLib LOCAL_SRC_FILES := ShowMD5.cpp ShowNativeLib.cpp include $(BUILD_SHARED_LIBRARY)
这个文件才是我们例子里面测试的这个模块的配置。 ShowNativeLib.cpp 就是我们的实现文件,ShowMD5.cpp是一个第三方MD5摘要算法开源库。(这里得吐槽一下,MD5,SHA1这种都叫摘要算法(DIGEST),因为发现很多人都没搞懂而喊它加密算法。)
其中ShowNativeLib.cpp的代码实现如下:解释都在代码里。
#include <jni.h> #include <stddef.h> #include <stdlib.h> #include <ShowMD5.h> #include <ShowNativeLib.h> #define CONVERT_KEY ("sobey_showfun_convert_key_47511441331441") JNIEXPORT jstring JNICALL Java_com_show_shownative_lib_ShowNativeLib_showConvertCode(JNIEnv* pEnv, jobject obj, jstring param) { if(!param) return NULL ; /* * JNI里面操作java对象的方式,全都是基于java反射机制来做的。 * 如果你完全没接触过java反射,那么你先应该去查查java反射的资料。 * 下面只做基本解释,不做深入讨论。 */ //取得java.lang.String的class jclass clzString = pEnv->FindClass("java/lang/String"); //取得String.getBytes的函数的Method对象 jmethodID getMethod = pEnv->GetMethodID(clzString,"getBytes","()[B"); //执行这个Method,得到String.getBytes返回的字节数组。 jobject byteObj = pEnv->CallObjectMethod(param, getMethod); jbyteArray paramBytes = (jbyteArray)byteObj ; //将java的byte[]转成C++的 unsigned char*。以进行后面的转换算法。 unsigned char* pBufIn = (unsigned char*)pEnv->GetByteArrayElements(paramBytes,NULL); jsize paramByteLen = pEnv->GetArrayLength(paramBytes); //调用MD5库,进行摘要处理。 std::string paramMd5 = GetMD5Code(pBufIn, (int)paramByteLen); int lengthMd5 = paramMd5.size(); //将内置的转换key,进行MD5处理 std::string paramKey = GetMD5Code((unsigned char*)CONVERT_KEY,strlen(CONVERT_KEY)); //进行转换算法。 for(int idx=0; idx<lengthMd5; idx++) { paramMd5[idx] ^= paramKey[idx]; paramMd5[idx] |= 0x31 ; } //将结果MD5二进制数据,转化成16进制表示的字符串 std::string resultMD5 = GetMD5Code((unsigned char*)paramMd5.c_str(),paramMd5.size()); //将C++字符串转化成java字符串。 jstring result = pEnv->NewStringUTF(resultMD5.c_str()); return result ; }
以上就是android里面使用JNI的例子。
jni还是很有帮助的,android的java毕竟在效率上有瓶颈(解释性语言的虚拟机,多了一个解释层),很多需要高效率的数据处理,还是免不了要调用本地库来处理。
苹果ios和android机比起来,从技术角度来看,人家的objc语言和ios平台,就比android平台的java执行效率高,这是不争的事实。所以同样的硬件配置,苹果机跑起来的流畅度是android机比不了的,但让实际情况是android机的硬件配置高得令人抓狂。
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。