qq:78080458 学习交流群:150633458
分类: Android平台
2014-11-27 11:31:07
原文地址:android学习之三--JNI使用 作者:gongping11
由于项目的需要不得不停止之前拟定的android学习计划,学习了一个多月已经做了几个项目了,虽然这些项目整体比较简单,但是对于了解android还是有很大的帮助,项目的内容主要是广播电视相关的实现,主要完成电视播放、电视的控制等部分。
在这个过程中学习了android的四的组件,了解了组件之间相互控制的实现。有时候真的感叹做项目才是真正有助于学习的过程,自学只能说帮你了解一定的知识储备,在真正运用时还需要进一步的查找。
1、shell脚本与java的处理
这段时间的主要工作是shell脚本与java交互的控制处理,由于电视控制的处理需要shell和java的交互,测试发现java直接调用底层的shell脚本有时候不奏效(也可能是学艺不精,Process的实现),虽然执行单挑的命令能够成功,但往往底层的脚本会经常的改变,因此不希望在java中重写脚本的内容,而是希望直接调用底层的脚本执行相关的处理。java的实现不奏效,就改走曲线救国的方式了。
记得的项目中C语言可以直接调用shell脚本的处理,其中可以实现的方式较多,
(1)多进程fork+exec和waitpid的实现方式,让父进程等待子进程执行完毕在进行相关的处理。
(2)system函数,该函数其实也是(1)的一种扩展,这种实现无法获取到对应的执行结果
(3)popen函数,该函数可以获取子进程的执行结果。
因此若在C语言中直接调用对应的shell程序,然后在java中采用JNI调用对应的接口,这样就能解决java与shell脚本的交互。
当然还可以采用服务器和客户端的实现方式
在后台执行一个命令服务器,接收客户端的命令,在接收到客户端的命令后将转换为对应的执行操作,服务器可以用于执行命令的命令的控制。这种实现方式可以采用android提供的localsocket实现,java与底层的c服务器进行交换,由该服务器执行对应的操作,可以参看localsocket的相关说明。
2、控制的转换
在前期方案的探索过程中我们采用了脚本的实现方式,但是考虑到扩展性以及方案的控制性,我将控制的逻辑转换为了jni的处理。不过相对实现比较简单,只是将控制的逻辑移植到了java的控制面,而数据面还是在底层进行。
关于jni的转换,其实也没有那么复杂,简单的jni转换实际上只需要将原有函数的main作为接口即可,即将某个功能的main函数转换为native_main().然后使用jni相关命令规则的函数来调用native_main即可实现最基础功能的转换。这种转换方式也可以简化一些功能的实现,保证了代码可以复用原有的一些功能。
java接口
|
V
jni接口(命名规则)
|
V
native_main()
关于JNI的编写过程中主要需要注意String和C语言中char *的一些差异,根据相关的文档操作即可,JNI是指就是一个中间层,解决java与其他语言交换的功能而已,是多语言之间的桥梁。当然目前我只是接触皮毛。
3、shell和java数据交互的问题
在shell和java中若有数据进行交互,最常用的当然是写文件了,也就是其中一方在写文件,另一方读文件,这种方式不好解决双方读写的问题。当然也可以采用多个文件的形式,读写文件的操作在java和shell中都比较好实现。
最近的需求是监听shell对文件的更改操作,然后在发生变化之后通知java进行相关的操作,最开始的实现过程中想到了采用inotify的机制,该机制主要用来监听文件和文件夹的变化。该机制虽然能较好的监听内容,但是在shell脚本中执行 echo "just" > /test,这个过程中会将/test先删除再添加新的内容,这就会导致inotify会监听到两次内容修改事件,导致无法辨认具体的操作。
为了实现echo "just" > /test只添加不删除在更新的方式,考虑了一种方式,也就是采用内核就作为中间桥梁,在内存文件系统/proc或者sysfs中创建文件,往该文件中写内容并不会导致文件的删除操作,保证echo "just" >/test不会被删除再创建。
为了更加有效,提供类似管道的机制,其中一段只能读,一段只能写,简单的方式就是提供两个文件,但是对这两个文件的操作都是同一块内存空间。
目前在项目中只是实现了双向的管道,shell可以直接将内容写入到java中,同时java也可以写入到shell中,基本的实现如下图所示。
Java
|
shell jni
| |
读写proc C读写/proc
| |
--------------kernel------------
关于jni的好处就是能够将之前完成的代码快速的复用到android中,但是也会遇到 一些无法解决的问题,如lib库不支持等问题。目前还处在学习中。