Android is the first free, open source, and fully customizable mobile platform. Android offers a full stack: an operating system, middleware, and key mobile applications. It also contains a rich set of APIs that allows third-party developers to develop great applications.

制作 cygwin 环境下的 Cross tool chain

在完全开源前,很多开发者在用 CodeSourcery 的 GNU Toolchains for ARM 。现在简单了,下载到源码 后,在 prebuild 目录下就有完整的 toolchain 用了。如果需要在其他系统环境下使用,可以去下载 android-toolchain-20081019.tar.bz2 源码重新编译。在 cygwin 下编译时,先检查一下 gcc make flex bison gettext-devel 等是否装全(编译过程中会用到 msgfmt 命令,cygwin 把它放到 gettext-devel 包里了),然后按照其 readme.txt 里的 linux 方式编译就可以了。cgywin 下有时会出现文件写失败的错误,用 chmod +w 修改即可解决。
在 <android source>/build/core/combo 目录下的 linux-arm.mk 文件对我们来说非常有帮助,其中 C_INCLUDES 描述 C 语言的所有头文件位置,在 android source 里找到这些目录,并复制到新编译好的 <toolchain>/arm-eabi/include 目录下,动态库在编译过的 <android source>/out/target/product/generic/system/lib 目录下,也可以从 Android SDK 的模拟器中 /system/lib 下找到这些文件,并复制到 <toolchain>/arm-eabi/lib 目录下。在 <android source>/build/core 下有 armelf.x armelf.xsc ,是以后编译必须的连接脚本。在 <android source>/out/target/product/generic/obj/lib 下的 crtbegin_static.o crtbegin_dynamic.o crtend_android.o 编译时还要根据自己情况选择并连接到可执行文件中去,当然也可以在程序 main 函数后加如下函数代替。

void _start(int argc, char **argv) { exit( main(argc, argv) ); }


First native C application on android

制作好了 toolchain ,就可以写个 hello.c 测试一下了。代码如下:

#include <stdio.h>
int main(int argc, char **argv)
{ printf("Hello World!/n");
return 0; }

编译命令:

$ arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,armelf.x -Wl,-dynamic-linker,/system/bin/linker /
-include AndroidConfig.h -lc -o hello hello.c crtbegin_dynamic.o crtend_android.o
$ adb push hello /data
$ adb shell chmod 777 /data/hello
$ adb shell /data/hello
Hello World!
$ 哈哈,Android 之旅开始了…


Shared library for android


接下来测试 shared library ,编写代码 libhello.c :

#include <stdio.h>
int sayhello(char *name)
{ printf("Hello %s/n", name);
return 0x12345; } 编写代码 hello2.c :

extern int sayhello(char *name); int main(int argc, char **argv)
{ sayhello("World!");
return 0; }
编译代码及测试运行:

$ arm-eabi-gcc -nostdlib -Wl,-T,armelf.xsc -Wl,-shared,-Bsymbolic -lc -o libhello.so libhello.c $ arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,armelf.x -Wl,-dynamic-linker,/system/bin/linker /
-L./ -lc -lhello -o hello2 hello2.c crtbegin_dynamic.o crtend_android.o
$ adb push libhello.so /data
$ adb push hello2 /data
$ adb shell chmod 777 /data/hello2
$ adb shell /data/hello2
Hello World!
$


呵呵,又迈进一步 ...


The Java Native Interface (JNI) for Android

在 eclipse 里新建一个 android 项目,新增加一个类 hello.java :

package cn.oopsware.hello;

public class hello {
static { try { System.load("/data/lib/libhello_jni.so"); } catch (Exception e) {} }
public native int test1();
public native int test2(int[] name); }


修改主程序
onCreate 的代码,用来调用显示结果:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
hello h = new hello();
TextView tv = new TextView(this);
tv.setText( Integer.toHexString( h.test1() ) );
setContentView(tv); }


android 使用的 JNI 头文件在目录 <android source>/dalvik/libnativehelper/include/nativehelper 下。也许是为了提高 android 映射库函数的速度,android 另加了两个函数,在加载和释放库时被VM调用,即:jint JNI_OnLoad(JavaVM* vm, void*) 和 void JNI_OnUnload(JavaVM* vm, void*) 。通过
JNIEnv 的 RegisterNatives 用法把一个 JNINativeMethod 数组 注册到 VM 。<android source>/ dalvik/libcore/dalvik/src/main 加有个简单的例子,可以帮助理解 JNINativeMethod 中 signature 的写法。 共享库代码 libhello_jni.c :

#include "jni.h"

static int test1(JNIEnv* env, jclass clazz)
{ return 0x654321; }

static int test2(JNIEnv* env, jclass clazz, jarray a)
{ return 0x765432; }

#define gClassName "cn/oopsware/hello/hello"

static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
{ "test1", "()I", test1 },
{ "test2", "([I)I", test2 }, };

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *env;
jclass cls;
if ( (*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_4) ) return JNI_ERR;
cls = (*env)->FindClass(env, gClassName);
(*env)->RegisterNatives(env, cls, &gMethods[0], 2);
return JNI_VERSION_1_4; }

void JNI_OnUnload(JavaVM* vm, void* reserved)
{
JNIEnv *env;
jclass cls;
if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_4)) return;
cls = (*env)->FindClass(env, gClassName);
(*env)->UnregisterNatives(env, cls); }


编译并上传到模拟器:

$ arm-eabi-gcc -nostdlib -Wl,-T,armelf.xsc -Wl,-shared,-Bsymbolic /
-lc -o libhello_jni.so hello_jni.c

$ adb push libhello_jni.so data/bin/libhello_jni.so

在 eclipse 里运行 android 项目,即可看到正确结果。 测试环境 Android SDK 1.0-r2 ,测试代码及编译好的库和apk可以到 http://sites.google.com/site/oopsware/android 下载。

http://hi.baidu.com/oopsware/blog/item/5a86550152edf7d1267fb56e.html

更多相关文章

  1. android edittext 显隐密码代码转换两种方式
  2. android制作一个简单登入界面的部分代码
  3. Android 6.0 源代码编译实践
  4. android控制home键 代码
  5. Android之常用功能代码
  6. android客户端加密代码
  7. Android引入外部字体源代码

随机推荐

  1. 全能HOOK框架 JNI NATIVE JAVA ART DALVI
  2. Android学习记录(6)—将java中的多线程下载
  3. 尝试用Android获取IMEI,折腾的一天,结果只
  4. Android表格布局之设置边框
  5. Android 中如何将带有html格式的文章转换
  6. Android Q 适配详细操作
  7. Android 修图(换证件照背景,污点修复)
  8. Android(安卓)MultiDex
  9. 我今天的面试题,注册广播有几种方式,这些方
  10. 腾讯T3大牛带你了解 2019 Android开发趋