编程基础知识——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机的硬件配置高得令人抓狂。

编程基础知识——Java JNI开发流程(2),布布扣,bubuko.com

时间: 2024-12-18 18:09:32

编程基础知识——Java JNI开发流程(2)的相关文章

编程基础知识——java类加载

java类加载 先来看一段小程序: package com; public class Main1 { static { System.out.println("1111") ; } public static void main(String[] args) { System.out.println("2222") ; } } 输出结果为: 1111 2222 其中static的执行时机就是class被 classloader加载的时候执行. 这有什么用?看下面代

编程基础知识——C++能不能支持Java和ObjC的反射?

C++能不能支持Java和ObjC的反射? 要回答这个问题,首先我们要清楚什么是反射.什么是反射? 教科书的解释我就不说了,(^o^)其实我也记不得.实际开发应用的反射就是在没有某个类型的头文件或者类结构定义的情况下,存取这个类型的对象的成员字段的值,调用这个对象的成员函数(方法). 比如我有定义了一个类型 Class  A,里面有 a,b,c三个字段,有fun()函数.现在我手里只有一个 void* pA,注意它的类型只是一个void指针,我手里也没有Class的头文件,我要怎么样得到,a,b

C#——编程基础知识

编程基础知识适用于所有高级编程语言.学了C#的第一小节,又对这些基础知识梳理了一遍.感觉比学习VB的时候的理解好了很多.下面看图: 基础知识:数据类型,表达式,流程控制语句.一切皆在图中. 一直在做编织知识网的工作.自己真的是不撞南墙不回头啊.米老师早就说过:要记笔记,要少记笔记,多了没用,又不会回头看.可是自己看的时候完全相反了.依旧几乎全部是截图,总结的时候特别费劲儿.得浏览所有截图,然后在几乎与视频等量的信息里再找主题,找中心.可是苦不堪言啊.现在终于下定决心,不再截图了.虽然总是有那股冲

unix环境高级编程基础知识之第一篇

陆陆续续看完了圣经第一章,熟悉了unix的整个编程流程,c语言的用处在这里得到伸张. 从unix的体系结构,原来操作系统包括内核及一些其他软件,我们常常误称为linux内核为操作系统,这俨然成为一种共识.基本熟悉了shell的介绍,主流的是bash(Bourne-again shell),unix的文件的基本操作,出错处理,用户ID,信号(感觉类似windows的消息),时间值,最后还有系统调用和库函数的区别. 自己把这篇的所有代码用vim的敲完了,主要前期是熟悉unix的基本命令编程,大致了解

JNI开发流程-JNI/NDK【转】

本文转载自:http://wiki.jikexueyuan.com/project/jni-ndk-developer-guide/workflow.html 开发流程 JNI 全称是 Java Native Interface(Java 本地接口)单词首字母的缩写,本地接口就是指用 C 和 C++ 开发的接口.由于 JNI 是 JVM 规范中的一部份,因此可以将我们写的 JNI 程序在任何实现了 JNI 规范的 Java 虚拟机中运行.同时,这个特性使我们可以复用以前用 C/C++ 写的大量代

PB编程基础知识汇总

PB编程基础知识汇总 第一章      1.  程序的开始,application的open事件. 退出程序例程:halt为退出函数 int SureQuit SureQuit = 2 SureQuit=Messagebox("退出系统","退出前请确认已保存好数据",Question!,OKCancel!, 2) if SureQuit = 1 then halt 2.  变量定义有效范围: ◎     declare-globe 全局变量,整个程序均有效 ◎  

c#编程基础知识

一.静态与动态 html属于静态,没有数据库 asp.net属于动态,将数据库中不断变化的数据显示在浏览器 二..NET的发展历程 96年以前都是以dos为核心的运行系统 年份         框架版本(.NET Frame work)        开发工具版本号(visual studio) 2002           1.0                                   vs2002 2003           1.1                       

JNI/NDK开发指南(一)—— JNI开发流程及HelloWorld

转载请注明出处:http://blog.csdn.net/xyang81/article/details/41777471 JNI全称是Java Native Interface(Java本地接口)单词首字母的缩写,本地接口就是指用C和C++开发的接口.由于JNI是JVM规范中的一部份,因此可以将我们写的JNI程序在任何实现了JNI规范的Java虚拟机中运行.同时,这个特性使我们可以复用以前用C/C++写的大量代码. 开发JNI程序会受到系统环境的限制,因为用C/C++语言写出来的代码或模块,编

多线程编程基础知识

多线程编程基础知识 http://www.cnblogs.com/cy163/archive/2006/11/02/547428.html 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.因此掌握