安卓JNI/NDK开发2(jni/ndk配置及 开发步骤)

JNI 开发步骤:

声明所需要的native 方法。

根据需要,在java代码中,声明所需要的native本地方法,和方法要实现的目的。
/**
 * 声明一个本地方法,
 * 调用C代码获得字符串信息,并返回
 * @return
 */
public native String getmessage();

在C代码中实现对应的native 方法

- 在项目中新建jni文件夹 在jni文件夹中新建一个c文件,如hello.c
- 在hello.c文件中,声明与native 方法对应的c的方法
    * 参数 ndk目录\platforms\android-16\arch-arm\usr\include\jni.h 文件
    /**
     * 返回值  jstring 是C中定义的与java中的String类型匹配的数据类型 
     * 方法名:
     * Java_包名_类名_方法名
     * 参数一:JNIEnv* env      java虚拟机运行jni的环境
     * 参数二: jobject jobj    是调用当前方法的java对象的引用
     */
    jstring Java_com_example_jnihello1_MainActivity_getmessage(JNIEnv* env,jobject jobj)
- 实现该方法,同时参考 JNINativeInterface 结构体中,返回对应的数据类型
        char * pstr = "hello i am from c";
        // 在 JNINativeInterface 结构中 查找到该方法
        //   jstring     (*NewStringUTF)(JNIEnv*, const char*);
        return (*env)->NewStringUTF(env,pstr);
- ** 注意在C文件中  #include <jni.h> **

将C代码编译为linux 环境下可运行的二进制文件

- 在jni目录中新建 Android.mk 配置文件
- 参照 ndk目录/docs/ANDROID-MK.html 编写该文件
        LOCAL_PATH := $(call my-dir)
        include $(CLEAR_VARS)
        LOCAL_MODULE    := hello  // 自己定义的当前模块的名称
        LOCAL_SRC_FILES := hello.c // 该模块需要的C文件
        include $(BUILD_SHARED_LIBRARY)
- 在文件游览器中打开jni文件夹,shift+右键,打开当前目录的cmd命令行。
    执行 ndk-build 命令
    * 注意 ndk的目录要事先加入 path 环境变量当中
- 编译成功后,会在android 项目中生成 libs/armeabi/libhello.so 文件 

在java 代码中,加载 so 文件

习惯上,都是在静态代码块中加载
static{
    // 加载编译好的  so 文件
    System.loadLibrary("hello");  // 注意 名称是libhello.so 去掉前三个和后三个字符省下的。其实就是Android.mk 文件中配置的模块名
}

JNI开发中的常见问题

  • Caused by: java.lang.UnsatisfiedLinkError: Couldn’t load hello: findLibrary returned null
    加载so库时出错,说找不到对应的库文件。
    出现错误的原因:
    一:可能是so文件的名称写错了
    注意:加载的文件名,出Android.mk 文件中声明的模块名要一致

    二:没有对应平台的so 文件
    编译出来的so文件是arm平台可用的,而模拟器是inter的模拟器
    解决方法:编译出支持inter CPU的so 文件

  • Caused by: java.lang.UnsatisfiedLinkError: getmessage
    调用native方法时,报此错误,是因为没有找到 与native 对应的C的函数
    出错的原因:
    极有可能是 C文件中 函数名没有写对。检查C函数名是否正确
    * 方法名:
    * Java_包名类名方法名

有参数的JNI 调用

  • 如果native 方法自身包含参数 那么对应的C的方法,也要有相应的参数
    如native方法: public native int jniAdd(int m,int n);
    那么对应的C的方法:
    /**
    • 返回值为 jint 类型
      *
    • 方向法:Java_包名类名方向名
    • 方法的参数,前二个是固定的 JNIEnv* 是jni的运行环境 jobject 是调用方法的java对象
    • 后面二个参数是 java代码中,native方法的真实的参数
      */
      jint Java_zz_itcast_jnihello2_MainActivity_jniAdd(JNIEnv* env,jobject obj,jint m,jint n){

javaH命令的使用

  • 打开项目bin/classes 目录,在此目录中,shift+ 右键 打开命令行,
    执行命令 javah zz.itcast.jnihello2.MainActivity
    会生成相应的头文件,该文件中就包含了和native方法对应的C的方法的声明,将方法的声明复制到C代码中,改为正确的方法即可。
    * 注意:上面的方法,在java1.6中有效 在java1.7中执行javaH 命令是在 src目录中而不是bin目录 *

NDK

NDK ( native develop kit ) 本地开发工具集,

是谷歌公司提供的,可以winodws平台,模拟出不同的其他平台的开发环境。

CDT 在eclipse中开发C语言的一个插件。

DNK 目录结构:

– build 编译代码时,所需要的工具脚本
* .sh sh扩展名是linux 下的可执行脚本,类似于windows中的bat 批处理命令
– docs ndk的说明文档
– platforms 包含不同的android版本,不同的CPU编译时,所需要的文件
– prebuilt 预编译,编译之前进行的准备,和测试的工具
– samples ndk自带的一些小例子
– sources 源码
– tests ndk的一些测试用例
– toolschains 编译的时候,需要的工具连

ndk 根目录下: ndk-build.cmd 编译时,执行的widnows命令。
* ndk解压后的目录,必须添加至系统path 环境变量 *

使用NDK集成开发环境的步骤:

在eclipse中配置ndk的安装目录

在 window/preferences/Android/NDK 中设置好NDK的解压目录

一:声明所需要的native 方法。

根据需要,在java代码中,声明所需要的native本地方法,和方法要实现的目的。
/**
 * 声明一个本地方法,
 * 调用C代码获得字符串信息,并返回
 * @return
 */
public native String getmessage();

二:集成NDK开发环境

> 选中项目-右键 -- Android Tools -- add Native Support
    如果打开的面板出错,是因为没有配置ndk目录
    在打开的面板中输入 Android.mk文件的模块名,该模块名,也是在java代码中加载so库文件的名称
    * NDK 环境默认创建的是cpp文件,即c++文件,目前先把 c++文件,都改为c文件

> 使用javah 命令生成对native 方法对应的C函数的声明,并复制至c文件中
> 此时,文件会报错,是因为没有关联C源码。
    关联C代码:
    选中项目,右键属性-- c/c++ general -- path and synbol 设定C源文件的路径:
    如: D:\android-ndk-r9b\platforms\android-16\arch-arm\usr\include 

三:实现C代码,并返回相应的数据

四:在java代码中加载so库文件

直接运行该应用,ndk会自动将C代码编译成so文件。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值