最近在公司要新开一个项目,和后端商量了一下,准备把http的加密算法换一下,这一换不要紧,尽然发觉水还挺深,先是碰到了自己没有涉及过的NDK,然后是JNI,这里就对上面的内容做一些总结。
首先是NDK环境配置
后来了解到Android studio已经支持NDK了,赶紧从eclipse切了过来,找到了一个很好的教程,基本上可以很简单的做出一个demo.
好了,项目已经搭起来了,下面就是jni的编程了,刚开始看人家的项目,简直没头没脑,乱七八糟来形容,经过一段时间的研究,发现jni调用java的方法其实很简单,常用的几个初始化,声明,调用会了,就可以将java代码转化过去,下面是常用的几个方法:
AndroidJNI.FindClass 查找类
static function FindClass (name : string) : IntPtr
Description描述
This function loads a locally-defined class.
这个函数加载一个本地定义的类。
AndroidJNI.GetMethodID 获取方法ID
static function GetMethodID (clazz : IntPtr, name : string, sig : string) : IntPtr
Description描述
Returns the method ID for an instance (nonstatic) method of a class or interface.
返回类或接口实例(非静态)方法的方法 ID。方法可在某个 clazz 的超类中定义,也可从 clazz 继承。该方法由其名称和签名决定。
GetMethodID() 可使未初始化的类初始化。
AndroidJNI.NewObject 新建对象
static function NewObject (clazz : IntPtr, methodID : IntPtr, args : jvalue[]) : IntPtr
Description描述
Constructs a new Java object. The method ID indicates which constructor method to invoke. This ID must be obtained by calling GetMethodID() with as the method name and void (V) as the return type.
构造新的 Java 对象。方法 ID指示应调用的构造函数方法。该 ID 必须通过调用 GetMethodID() 获得,且调用时的方法名必须为 <init>,而返回类型必须为 void (V)。
clazz 参数务必不要引用数组类。
</pre><pre code_snippet_id="574605" snippet_file_name="blog_20150107_5_7301243" name="code" class="java">AndroidJNI.CallIntMethod 调用整数方法
static function CallObjectMethod (obj : IntPtr, methodID : IntPtr, args : jvalue[]) : IntPtr
Description描述
Calls an instance (nonstatic) Java method defined by methodID, optionally passing an array of arguments (args) to the method.
调用一个由methodID定义的实例的Java方法,可选择传递参数(args)的数组到这个方法。
更详细的请查看下面的文章
AndroidJNI 函数介绍
下面看个例子:
jclass string_cls = env->FindClass("java/lang/String");
jmethodID substring_mid = env->GetMethodID(string_cls, "substring", "(II)Ljava/lang/String;");
return reinterpret_cast<jstring>(env->CallObjectMethod(sign,substring_mid,4, 17));
需要注意的是 GetMethodID方法的格式。
jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);
JNIEnv这个参数C++中不需要。clazz就是前面得到的jclass.
name则是方法名称,sig是方法签名。
方法签名有特定的格式:(param-type)ret-type,括号内表示该方法传入参数类型,后面的是返回类型
其中param-type和ret-type都是由特定符号组成。那么sig如何能获取到尼?
$ javap -s class
比如:
$ javap -s java.lang.String
public java.lang.String toUpperCase();
Signature: ()Ljava/lang/String;
public java.lang.String trim();
Signature: ()Ljava/lang/String;
public java.lang.String toString();
Signature: ()Ljava/lang/String;
就能看到所有的方法和签名。
追加:
非java方法,比如android.util.Base64 需要到目录下面先javac -c class.java编译,然后再 javap -s class 才可以