JNI开发个人总结

常见概念

交叉编译

在一个平台上编译出来另外一个平台可以运行的二进制代码.不同的操作系统(windows, mac os,linux),不同的处理器平台(x86,arm,MIPS)

交叉编译的原理

源代码--->编译---->链接---->可执行性程序

模拟另外一种平台的cpu和操作系统的特性.

交叉编译的工具链

一大堆工具,放在一起,链式调用,工具链

常见工具

  • ndk : native develop kits 本地开发工具集(交叉编译工具链)
  • cdt : c/c++ develop tools c和c++开发工具 (eclipse的一个插件) 语法的高亮显示
  • Cygwin : windows下一个linux模拟器(了解)

NDK的目录结构

  • docs : 开发文档
  • build: linux下编译的批处理命令
  • platform : 某种平台下编译需要的头文件和函数库
  • prebuild : 预编译的工具
  • sample: 实例代码
  • sources : 一些工具链的源码
  • toolschains: 工具链
  • ndk-build.cmd: ndk编译的命令脚本

JNI开发的步骤

  1. 在java代码里面声明一个native的方法.

     public native String helloFromC();
    
  2. 在工程目录下面创建一个jni的文件夹.

  3. 在jni文件夹里面编写c代码

    //env是虚拟机的环境 obj调用者对象
    jstring Java_包名_类名_方法名(JNIEnv* env,jobject obj){
    
    }
    
  4. 实现c代码

    使用env环境指向的结构体,有自带的函数,利用jvm的函数进行操作
    return (*(*env)).NewStringUTF(env,arr);
    return (*env)->NewStringUTF(env,arr);
    
  5. 编译c代码

    配置c代码编译的脚本文件 Android.mk文件
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_MODULE    := hello //编译后的模块名
    LOCAL_SRC_FILES := Hello.c //编译的源文件的名称
    include $(BUILD_SHARED_LIBRARY)
    
  6. 调用ndk-build.cmd指令编译c代码

    注意配置环境变量
    
  7. 生成一个.so的文件 ( c代码编译出来的二进制可执行文件)

  8. 在java代码里面写静态代码块,加载so文件

    static{
    System.loadLibrary("hello");
    }
    
  9. 像使用一般java方法一样调用native的方法.

jni开发的常见错误

10-22 02:18:35.672: E/AndroidRuntime(1552): Caused by: java.lang.UnsatisfiedLinkError: Couldn't load hello: findLibrary returned null* 如果处理器平台不匹配,返回的lib就是空

在Application.mk文件中编写APP_ABI := all

  • 检查lib的名字是否拼写错误

10-22 02:24:50.418: E/AndroidRuntime(1696): Caused by: java.lang.UnsatisfiedLinkError: Native method not found: com.itheima.hello2.MainActivity.add:(II)I

  • 检查c语言里面编写的方法名是否符合规范 Java包名类名_方法名(参数)

掌握要点

  • 把基本类型的数据传递给c语言.
  • String 字符串 传递给c语言(工具方法 jstring2cstr)
  • 传递java数组给c语言

c代码回调java

  • 复用已经存在的java代码
  • c语言需要给java一些通知
  • c代码不方便实现的逻辑

回顾一下反射

    //1.把字节码装载进来
    Class clazz = Demo.class.getClassLoader().loadClass("Dialog");
    //2.查询对话框里面的方法
    Method method = clazz.getDeclaredMethod("showDialog", String.class);
    //3.调用方法
    method.invoke(clazz.newInstance(), "哈哈嘎嘎嘎");

实际开发的流程

  1. java程序员先去定义native的方法.
  2. jni程序员根据native的方法生成函数的签名
  3. 找个c工程师 给我添代码.
  4. 配置编译环境,编译调用

jni使用过程和代码集锦

jni使用过程

使用eclipse中的ndk插件

  • 1.修改工程的默认编码为utf-8...工程目录右键property编码
  • 2.导入ndktool...工程目录右键androidTool下的clear lint makers
  • 3.导入c源码库...工程目录右键proper下的cgeneral下的pathandsymbols点击add....filesystem..选择ndk的目录下的platform下的一个include文件应用
  • 4.在main中新建一个native方法...此方法需要在c语言中实现.即是java中调用本地native方法.native方法在c中实现
  • 5.main中添加静态代码块..加载时就加载c库文件
  • 6.找到工程目录中的bin目录下的com.执行命令javah 包名类名.生成h文件查看文件中生成的cnative方法..复制进去jni下的c语言文件中..加上括号就是方法
  • 7.实现方法即可
  • 注意..没有在eclipse工具集的环境下,每一步文件夹都需要自己创建和添加...其中需要手动编译c文件....在.c文件的目录下执行指令ndk-build.cmd...需要配置环境变量..并且需要配置android.mk文件...加上application文件可以在四个处理器上跑

上述是java中调用c代码过程

  • c代码也可以调用java代码
  • 1.在main方法中定义好方法a();
  • 2.在c代码中利用反射原理..可以调用到c代码///
  • 三行代码调用java方法...详细如下
  • 下面的参数字节码的获得.可以在class所在的目录执行命令javap -s 包名类名则可以找到

    //jclass      (*FindClass)(JNIEnv*, const char*);
    //1.查找字节码...第二个参数是方法所在的包名加上类名
    jclass  jclazz = (*env)->FindClass(env,"com/itheima/alipay/MainActivity");
    //2.查找方法.......第二个参数所要调用的方法名...第三个参数是方法参数的字节码
    //  jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    jmethodID methodid = (*env)->GetMethodID(env,jclazz,"showDialog","(Ljava/lang/String;)V");
    //3.调用方法.第二个之后的即为参数.newstringutf方法返回以utf-8形式返回的java字符串
    //void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    (*env)->CallVoidMethod(env,obj,methodid,(*env)->NewStringUTF(env,cstr));
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值