设为首页 加入收藏

TOP

Android Native jni 编程入门
2015-04-07 15:29:33 来源: 作者: 【 】 浏览:35
Tags:Android Native jni 编程 入门

在某些情况下,Java编程已经不能满足我们的需要,比如一个复杂的算法处理,这时候就需要用到jni(java native interface)技术;


jni开发工具ndk的安装:
在最新的ndk版本中,安装ndk很简单,只需要装ndk的路径配置到系统环境变量中即可;
在编译的时候,进入工程根目录;执行命令 ?ndk-build ?即可完成编译;


下面就通过一个例子一步一步的来初步学习jni


一、HelloWorld


新建一个工程,你甚至不需要其它额外的设置,然后在工程中添加一个jni目录,然后就可以开始了;


1.新建一个java类HelloWorld.java


在HelloWorld中,定义了一个方法helloworld(),只不过这个方法被申明成了native的,并没有具体的实现,具体功能我们在接下来的cpp文件中实现;


2.在jni目录下添加一个helloworld.cpp


从上面这个cpp文件中可以很明白的看出,它有一个方法,具体包括方法申明和方法实现两个部分;但是相信大家也都看出来了,方法的命令很怪异,怎么这么长的方法名?


我们在这里先思考一个问题,java类中的方法是如何调用c++中的方法的呢?要解决这个问题,就得先来看这个长长的方法名;


其实这是jni的一个规范之一,用于映射java方法和c/c++中的方法对应;


再来看在cpp中定义的函数名:Java_com_jni_HelloWorld_helloworld


其实不难看出,java文件与cpp文件中函数名的配对定义方式为Java + 包名 + java类名 + 方法/函数名,中间用_分隔;其中两个参数分别是:


这里的helloworld方法,其实就只是返回了一个单词"helloworld";


3.在jni目录下添加一个Android.mk文件


4.在命令行下进入工程目录执行 ndk-build 命令,然后运行程序,调用HelloWorld实例的helloworld方法就可以得到它的返回字符串了;



二、jni调用Java类的方法(1)


通过上面的helloworld练手之后,我们来看一下jni调用java类里面的方法的实现;


1.新建设一个MethodCall.java文件如下


该类有6个方法,其中有3个是java类的方法,另外3个是native方法,3个native方法分别去调用3个java方法;


2.添加三个native方法具体实现 methodcall.cpp


该cpp文件中有3个方法(我这里把方法名都写得很明白直观,相信不需要注释都知道是调用的哪一个java方法)


我们知道,在java编程中,对一个类的调用,其实是先创建一个类的对象实例,然后再调用它的方法(这里指的是非static方法) ,那么我们是如何在c/c++文件中调用java方法的呢?


回到上面的HelloWorld,我们讲方法名的时候,下边有随便提到的方法的参数,其中,第二个参数obj其实就是我们在java中使用的类的实例,到这里,相信是如何调用java方法的大家都明白了吧;


在java中,每一个方法其实都有一个id,我们在c/c++中不能直接通过obj来调用一个java方法,我们要先获取方法的id,通过GetMethodID()来获取,需要传入类的类型,方法名,方法的签名(方法签名在文章后面会讲到签名规则);然后再在线程里面调用java方法,通过env->Call****Method();需要传入对象实例,方法id,或者其它参数;(上面只展示了几个这种方法,其它的方法如果大家有需要用到可以自行查找资料解决);


3.编写Android.mk文件,在Android.mk文件后面添加如下内容


4.执行ndk-build 命令,下面是分别执行3个jniCall****方法的结果



三、jni调用Java类的方法(1)


上面是c++调用java方法的例子,下面再帖一个c调用java方法的例子


1.Java文件 MethodCall1.java


2.methodcall.c


3.完善Android.mk文件,参照二里面第四步;


4.运行代码



四、方法签名规则?


上面是各种数据类型对应的签名字符


方法的签名组成:"(参数签名)" + "返回值签名"


例如Java方法long fun(int n, String str, int[] arr);
根据上面的签名规则可以得到其签名为:(ILjava/lang/String;[I)J
上面的签名分为两部分:括号里面为函数的参数,参数的内容分三部分"I","Ljava/lang/String;","[I",之间没有空格;括号外边是函数的返回类型签名。需要注意的是如果函数返回类型为void则其中返回类型签名为V;


五、动态注册函数


前面二和三都是c/c++里面方法的名称来映射函数,其实jni还为我们提供了动态注册函数的功能;


1.添加java文件 DynamicRegisterMethod.java


2.添加 c 文件?


3.在Android.mk文件中进行编译的配置(省略,参考前面的例子)


4.ndk-build编译项目?


执行结果:



可以看到通过动态注册方法的方式,也是成功的调用了 native 方法;


六、加入链接库


在程序开发过程中,会频繁的用到调试,方式有很多种,下面要讲的这一种是通过log打印信息来打印程序运行时的一些状态数值;


修改Android.mk文件,添加一句代码


加入了log库之后,即可通过c/c++文件直接打印log信息;


在c/c++中调用log打印输出信息:


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++程序内存泄漏检测方法 下一篇Android 使用NDK编译sipdroid Lib..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: