注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

(转载)JNA移植到android上  

2015-02-02 11:55:12|  分类: Android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

(转载)JNA移植到android

2013-02-26 11:01 855人阅读 评论(8) 收藏 举报

http://blog.csdn.net/simpsonwang/article/details/8612225

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

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

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

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

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

 (转载)JNA移植到android上 - 还东国 - 还东国的博客

 

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

只所以要重新编译jna,是因为master.zip自带的jna.jar文件里面带so文件,而androidjar文件里面是不能带so文件的,否则无法生成apk文件。

下面进入第二步编译一个能在android上运行的libjnidispatch.so文件。

1:找一个linux操作系统我这里使用的是ubuntu12.04

建立一个叫jna的目录,将master.zip里面的native文件夹copylinux上这个新建的jna目录下,我是用工具winscp工具传倒ubuntu上去的。文件结构如系统所示:

 (转载)JNA移植到android上 - 还东国 - 还东国的博客

注:里面的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句话的下面修改CCCPP,LD,RANLIB,STRIPNDK_PLATFORM这几个变量的值改成交叉编译器和ndk所在的路径就行了。

下面是我的机器上的配置

 (转载)JNA移植到android上 - 还东国 - 还东国的博客

 

大家只要改成自己对应的路径就行了。

配置完Makefile后,接着生成com_sun_jna_Native.h文件

由于下载的master.zip里面native目录下缺少这个文件,所以导致编译失败所以需要自己生成。

javah目录就可以生成。

javah -classpath "前面eclipse里面生成的jnaclass文件所在的目录"    -d "生成的头文件存放的路径"   com.sun.jna.Native

这样就会在 "生成的头文件存放的路径里面生成com_sun_jna_Native.h文件了。将这个头文件传到服务器上。

 

接着执行在linuxjna目录下执行make  all命令

执行完后在jna/build/native下会生成几个so文件,如下图所示

(转载)JNA移植到android上 - 还东国 - 还东国的博客

 

libjnidispatch.so文件copy出来。

到这里编译完成。

 

下面介绍怎么在android里面调用JNA

首先建立一个android工程,在工程里面新建一个叫lib的文件夹,将前面生成的jna.jar文件copylib目录里面。

然后右键点击工程-->build path--->configure build path在弹出框里面的libraries选项里面add jarslib目录里面的jna.jar加进去。

然后在工程里面建立一个叫libs文件夹,然后在libs里面建立一个叫armeabi的文件夹,将libjnidispatch.so文件copyarmeabi文件夹里面。

 

接着建立一个Activityjava文件里面加上以下代码

 

 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);

}

 

接着在activityonCreate方法里面调用:

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 里面可以下载

 

添加的说明:

http://blog.csdn.net/jessyshen917/article/details/6064563中提出要修改build.xml,但在这篇博文中没有修改,想了一下,又仔细看了文档的不同,发现原因是本篇文章是直接从SRC中导出JAR包,所以就不需要再修改XML文件,但是另外一篇文章是用ANT来编译的,所以需要修改。而且确实如一些资料所讲,ant利用build.xml来编译Android程序并打包,方便并且安全,签名、混淆和对齐优化都已经有了。所以如果有可能还是使用Build.xml的方式。

另外:http://blog.csdn.net/feng88724/article/details/12714049

有简要的编译说明,其中ant -Dos.prefix=android-arm dist和上面用到的linux-arm只是名字不同,但是指向的交叉编译器是一致的。

Android JNA

分类: Android进阶】 2013-10-14 18:57 1441人阅读 评论(0) 收藏 举报

Add Android SDK/NDK tools into PATH (used by native/Makefile).

Set environment variable NDK_PLATFORM (used by native/Makefile).

Build using: ant -Dos.prefix=android-arm dist.

Tests must be run on the target platform, not the build platform.

Add dist/jna.jar and/or dist/platform.jar to your application, as needed.

If you're using android-maven-plugin, jna.jar can be used as-is (native libraries will be automatically copied into your project).

If you're using Google's Eclipse plugin then you must manually remove libjnidispatch.so from jna.jar/lib/armeabi and add it into your project's libs/armeabi directory.

See http://code.google.com/p/android/issues/detail?id=17861 and http://developer.android.com/guide/practices/jni.html for more information.

  评论这张
 
阅读(607)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017