`

Android JNI实战

阅读更多

2.在Android上编译C程序
(1)风临左岸在这方面颇有建树,以下是他的blog:
http://blog.sina.com.cn/flza
    最简单的hello world程序可以参看下面这篇文章的做法。
Android原生(Native)C开发之一:环境搭建篇
http://blog.sina.com.cn/s/blog_4a0a39c30100auh9.html
    这里有个概念要弄清楚,之前的例子都是针对x86-win32平台的,而这里我们要在arm-linux下编程。我这里有个同事,曾将x86-win32下的dll放到Android模拟器中,然后抱怨无法使用JNI,这就是这类错误的一个典型的例子。
    还有一点需要注意的是,风临左岸使用的交叉编译工具,所编出的程序虽然可以在模拟器中运行,但却是无法直接用于JNI的,需要使用一定的技巧,可参见以下网页:
Shared library "Hello World!" for Android
http://honeypod.blogspot.com/2007/12/shared-library-hello-world-for-android.html
    从这篇文章可以看出,风临左岸使用的交叉编译工具的动态库的默认格式,和Android平台的动态库的格式是不同的,这也是之前有人说Android无法使用JNI的原因。
    更好的办法是直接使用google提供的交叉编译工具。

(2)获得Android的源代码
    获得源代码的官方方法如下:
http://sites.google.com/a/android.com/opensource/download
    虽然源代码在http://source.android.com下,但用浏览器是无法获得代码的,只能用上文提到的方法才行。
当然诸如www.androidin.com 之类的网站也提供了非官方的源代码下载。
    源代码的大小有1G左右,解压源代码,在源代码的prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin文件夹下可以找到google提供的交叉编译工具。
    使用prebuilt工具编译C程序的方法可以参考以下文章:
http://www.j2medev.com/android/native/200901/20090119222445.html

3.Android JNI
    正统的做法可以参照以下网页:
http://www.j2medev.com/android/native/200901/20090119222617.html
    当然简单的做法也是有的,可以只解压源代码中的bionic、dalvik、prebuilt这三个文件夹。
需要注意的是,和第三方的交叉编译工具不同,prebuilt下只有相关的头文件而没有相应的.o或.a文件,所以用一般的makefile的话,没有办法编译静态可执行文件,但是动态库文件是可以编的。
    这里还有一个奇怪的地方,如果直接使用cc生成.so的话,会出错。而先cc生成.o,再ld生成.so就没问题。不知道这是什么原因,尚需高手指点。
    这里也提供一个例子,功能和例子1.(3)相同。使用时,将.apk和.so都放在/data/app下即可。
http://www.namipan.com/d/cb2c2eb8c1c6852eaf744e382b8d9805b44e5a2e7f660000

4.关于一个语法现象
    AlertDialog dialog = new AlertDialog.Builder(SmartGuider.this)
           .setTitle("设置错误")
           .setMessage("GPS功能未开启,请先开启GPS后再使用本程序!\n\n点击Ok进入系统设置页面,点击Cancel退出程序。")
           .create();

    在apidemo中,有很多类似于这样的语句。刚阅读到的时候,先是觉得是不是语法有误,怎么能在一条语句中,调用两个成员函数。接着一想,这是人家出的demo,怎么可能犯这种低级错误,一处也就罢了,总不可能到处都出这种错吧。
    于是就考虑是不是Java的新语法,毕竟Java这种语言从1.0到1.7,已经有8个版本了,像@Override和模板之类的特性都是后来添加进去的。但查了半天也没查到出处。
    于是去Android SDK中查看相关类的方法,才发现了奥妙。
    AlertDialog create()
    AlertDialog.Builder setTitle(CharSequence title)
    AlertDialog.Builder setMessage(CharSequence message)
    由于setTitle和setMessage返回的都是AlertDialog.Builder类型的引用(多半就是this),从而使得这样连写的语法 得以实现。如果把create放到setTitle或setMessage之前,显然就会出错了。因此这根本就不是什么新语法,而只是一种技巧而已。
    在C语言中,其实也有类似的情况,例如
    char *strcpy(char *strDestination,const char *strSource);
为什么不写成
    void strcpy(char *strDestination,const char *strSource);
或者
    char *strcpy(const char *strSource);
呢?
    不采用第一种,是因为这样做可以使用诸如strlen(strcpy(...))之类的便捷写法。
    不采用第二种,当然是和内存分配有关了,这里就不多说了。

  • FUI.rar (25.6 KB)
  • 下载次数: 34
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics