用到的概念
- 交叉编译,在一个平台上为另一个平台编译程序,不同的操作系统,window, Mac OS, Linux;不同处理器架构,X86 ARM Mips
本地编译。编译代码的平台Host,运行代码的平台Target
交叉编译工具链,一系列工具依次调用,形成链条,arm-linux-gcc
jni开发用到工具
- cdt: c/c++ development tools eclipse插件
- NDk: Native Development kit
- Cygwin : windows上提供unix模拟环境
NDK 目录结构
- build 目录下XXX.mk 指导编译配置文件
- docs 文档
- platforms 编程需要头文件,
- android-ndk-r10e\platforms\android-18\arch-arm\usr\include 头文件
- \android-ndk-r10e\platforms\android-18\arch-arm\usr\lib 库文件 .so
- prebuilt 目录下 make.exe 工程管理器,编译工程,帮我们调用工具链中工具 android-ndk-r10e\prebuilt\windows-x86_64\bin
- samples 例子目录
toolchains 工具链
ndk-build.cmd 包装好的make
jni开发流程
- 阶段1 编码
创建工程,用native 声明本方法,新建jni文件夹,添加hello.c文件
#include <jni.h> //jni要求本地方法名按格式 Java_包名(.需要换成_)_类名_方法名 // JNIEnv * env 代表java环境 // jobject obj 调用这个方法的类的对象 jstring Java_com_itheima_hello_MainActivity_helloFromC(JNIEnv *env, jobject obj){ char *ptr = "Hello world"; // env : JNIEnv * : struct JNINativeInterface* * // (*env)->NewStringUTF() //jstring (*NewStringUTF)(JNIEnv*, const char*);//把char *转为jstring return (*env)->NewStringUTF(env, ptr); }
阶段2 编译
在jni目录下添加Android.mk指导编译
LOCAL_PATH := $(call my-dir) #指定当前目录 include $(CLEAR_VARS) #清除LOCAL_XXX变量,除了LOCAL_PATH LOCAL_MODULE := hello #指定最终生成的库名hello, 库文件名libhello.so LOCAL_SRC_FILES := hello.c #指定由hello.c来生成最终的库 include $(BUILD_SHARED_LIBRARY) #指定生成动态链接库 .so
把ndk-build.cmd路径添加到Path环境变量,进入jni目录下,执行ndk-build
D:\jni02\code\01_hello\jni>ndk-build [armeabi] Compile thumb : hello <= hello.c [armeabi] SharedLibrary : libhello.so [armeabi] Install : libhello.so => libs/armeabi/libhello.so
在调用类中加载.so动态库
static{ System.loadLibrary("hello");//需要是库名而不是库的文件名 }
jni开发过程中常见错误
方法找不到, Native method not found: com.itheima.hello2.MainActivity.resultFromC:(II)I
- 本地方法名没有按jni要求写
- 动态库没在类中加载
库找不到,Couldn’t load resultfr0mc: findLibrary returned null
- 加载的库名写错
- 生成的库不是指定平台,arm 库在x86下运算
- 可以在jni文件夹下添加Application.mk,其中添内容APP_ABI := all,再重新编译
eclipse结合ndk工具开发jni程序
- 1.新建工程,声明本地方法,调用本地方法
- 2.工程中指定NDK路径,见add ndk location2.gif
- 3.工程中右键Andoird Tools –> Add Native Support 可以自动添加jni文件夹及.cpp源文件和Android.mk,需要修改源文件为.c文件,在Android.mk文件中也要修改 见add native support.gif
- 4.在.c源文件中添加jni.h头文件路径,见include jni head file.gif
- 5.在.c源文件中实现本地方法,利用javah生成本地函数名
- 6.在类加载动态库
- 7.运行应用,会自行编译动态库并安装。
利用javah命令生成jni格式头文件及jni本地函数声明
- jdk1.6 在工程的bin\classes执行