JNA移植到android上

一直以来在android上只是用JNI和和ndk来调用底层,写jni的确是件很痛苦的事情,各种数据的转换很头疼。

下面介绍我自己在android上使用jna的情况。

jna的知识我就不在这里重复说明了,从https://github.com/twall/jna/archive/master.zip下载jna3.5.0,里面dist\javadoc目录下的index.html文件介绍了jna的使用方法。

通常在windows,linux,mac上直接就可以将dist目录下的jna.jar文件放到eclipse里面直接调用了,但是在android下不行,android里面调用的需要重新编译

libjnidispatch.so文件和jna源文件。

 

 1:在eclipse里面建一个java工程名字叫jna,将下载的master.zip里面的src里面的源文件全部copy到jna的src目录下:结构如下图所示:

然后将该工程里面的class文件打包成一个jar文件,名字叫jna.jar。

只所以要重新编译jna,是因为master.zip自带的jna.jar文件里面带so文件,而android上jar文件里面是不能带so文件的,否则无法生成apk文件。
 
下面进入第二步编译一个能在android上运行的libjnidispatch.so文件。
1:找一个linux操作系统我这里使用的是ubuntu12.04。
建立一个叫jna的目录,将master.zip里面的native文件夹copy到linux上这个新建的jna目录下,我是用工具winscp工具传倒ubuntu上去的。文件结构如系统所示:
 
注:里面的MakefileCopyOf是我自己备份的Makefile文件。
 
先打开Makefile文件。
首先大家看到了一段话
OS=$(shell uname | sed -e 's/CYGWIN.*/win32/g' \
                 -e 's/MINGW32.*/win32/g' \
                        -e 's/SunOS.*/solaris/g' \
                        -e 's/NetBSD/netbsd/g' \
                        -e 's/FreeBSD/freebsd/g' \
                        -e 's/OpenBSD/openbsd/g' \
                        -e 's/Darwin.*/darwin/g' \
                        -e 's/AIX.*/aix/g' \
                        -e 's/Linux.*/linux/g')
这段代码的功能是获取操作系统的名称是linux还是别的其他系统。但是在android上我们将这段代码替换成OS=android
接着大家会看到JNA_JNI_VERSION=3.5.0 # auto-generated by ant这样的代码。
这个时候需要将他改成JNA_JNI_VERSION=3.5.0
注意3.5.0后面不能带空格啊,我第一次编译的时候就是因为#号前面的空格没有去掉害的我查了半天的错误才找出来。
 
接着是需要配置交叉编译器和ndk了。
大概在Makefile110行左右
# Android build (cross-compile) requires the android SDK+NDK.
# Ensure the following tools are in your path and adjust NDK_PLATFORM as needed
在这2句话的下面修改CC,CPP,LD,RANLIB,STRIP和NDK_PLATFORM这几个变量的值改成交叉编译器和ndk所在的路径就行了。
下面是我的机器上的配置
 
大家只要改成自己对应的路径就行了。
 
 
配置完Makefile后,接着生成com_sun_jna_Native.h文件
由于下载的master.zip里面native目录下缺少这个文件,所以导致编译失败所以需要自己生成。
用javah目录就可以生成。
javah -classpath "前面eclipse里面生成的jna的class文件所在的目录"    -d "生成的头文件存放的路径"   com.sun.jna.Native
这样就会在 "生成的头文件存放的路径"  里面生成com_sun_jna_Native.h文件了。将这个头文件传到服务器上。
 
接着执行在linux的jna目录下执行make  all命令
执行完后在jna/build/native下会生成几个so文件,如下图所示
将libjnidispatch.so文件copy出来。
到这里编译完成。
 
下面介绍怎么在android里面调用JNA了
首先建立一个android工程,在工程里面新建一个叫lib的文件夹,将前面生成的jna.jar文件copy到lib目录里面。
然后右键点击工程-->build path--->configure build path在弹出框里面的libraries选项里面add jars将lib目录里面的jna.jar加进去。
然后在工程里面建立一个叫libs文件夹,然后在libs里面建立一个叫armeabi的文件夹,将libjnidispatch.so文件copy到armeabi文件夹里面。
 
接着建立一个Activity在java文件里面加上以下代码
 
 static{
     try{
            System.setProperty("jna.library.path", "/system/lib");
             System.loadLibrary("jnidispatch");
     }catch(Exception e){
      e.printStackTrace();
     }
    }
其中 System.setProperty("jna.library.path", "/system/lib");表示从/system/lib目录下加载要调用的so文件,如果要调用的so文件在多个路径下,则多个路径用冒号分隔
如:System.setProperty("jna.library.path", "/system/lib:/usr/lib");表示jna会从/system/lib目录和/usr/lib目录下查找so文件。
如果so文件是用户自己编译的,则只需要将so文件放在libs/armeabi目录下就行了,jna会自动查找这个目录下的so文件,不在这个
目录下的so文件需要将路径设置到jna.library.path属性里面,通过System.setProperty("jna.library.path", "/system/lib:/usr/lib:so文件所在的路径");设置即可。
System.loadLibrary("jnidispatch");这条语句是加载jna运行所必需的so文件。
 

下面是我通过jna调用libc.so里面的malloc函数的代码:
其中libc.so在我的androi手机的/system/lib目录下,所以我设置的so路径为 System.setProperty("jna.library.path", "/system/lib");
首先建立一个叫StandardC的接口,代码如下

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;

public interface StandardC extends Library {
 StandardC INSTANCE = (StandardC)Native
   .loadLibrary("c", StandardC.class);
 
 public Pointer malloc(int size);
}

接着在activity的onCreate方法里面调用:
try{
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
                Pointer p = StandardC.INSTANCE.malloc(4);
        p.setInt(0, 4);
         Toast.makeText(this, "value="+p.getInt(0)+" and malloc(4)="+Pointer.nativeValue(p), 1).show();
     }catch(Throwable t){
       t.printStackTrace();
     }
 
将生产的apk放在手机里面运行,运行成功的话,会弹出一个提示,里面的内容是value=4 and malloc(4)=内存地址的值。
到此,android上移植jna和调用jna就全部完成了。
 
由于不能上传附件,所以运行程序和其他的资源在  我的资源 http://download.csdn.net/detail/simpsonwang/5088614 里面可以下载
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值