Android-JNI2

一、
  1. linux开发环境搭建
    • -----程序被运行要经历两个步骤(1.编译 2.链接)
      •  .java ---> .class ----> java虚拟机解释,链接
      •  .c    ---> .o(中间文件)--> 根据不同的操作系统不同的cpu平台生产对应平台的可执行代码(windows .exe  linux elf)
    • 交叉编译: 在一种操作系统平台或者cpu平台下 编译生成 另外一个平台(cpu)可以运行的二进制代码
    • 工具一:  交叉编译的工具链: NDK 
      • 在ndk的交叉编译的工具链里面 有很多.sh 的linux系统下的脚本文件.
      • 要在windows下使用ndk的工具,必须要提供一个工具(linux环境的模拟器)
    • 工具二:  cygwin(windows下linux系统环境的模拟器, 主要是为了能够运行ndk的工具).安装 devel shell
    •          linux 特点:所有的设备 硬件 都是以文件的方式定义的.
    • 工具三: cdt(c/c++ develop tools)  eclipse 的一个插件  用来让c\c++代码 语法高亮显示. 
    •              adt(android develop tools)
  2. 配置sygwin的环境变量:sygwin的安装目录下的etc子目录下的profile文件第32行添加ndk的目录
    • PATH="/usr/local/bin:/usr/bin:/cygdrive/d/heima/android/JNI/ziliao/android-ndk-r7b:${PATH}"
    • 蓝色部分为ndk的解压目录。cygdrive表示的是linux下的盘符
  3. ndk-helloworld调用C代码
    • JNI的适配器文件:
      • D:\heima\android\JNI\ziliao\android-ndk-r7b\platforms\android-8\arch-arm\usr\include\jni.h
    • 6大步骤:
      • 1.activity中定义一个native方法
        • public  native String  callHelloFromC(); //由c代码实现
      • 2.工程下新建jni目录,编写c代码,实现native中定义的方法. 注意方法名。
        • jstring  Java_com_itheima_ndkhelloworld_MainActivity_callHelloFromC(JNIEnv* env,jobject obj){
        • return (*(*env)).NewStringUTF(env,"hello from c.");
        •         // return  (*env)-> NewStringUTF(env,"hello from c.");等价于上一句代码,开发常用
        • }
      • 3.将写好的c代码编译成二进制可执行文件  -> .so
        • 使用交叉编译工具编译.c文件。cd cygdrive/f
      • 4.jni目录下编写Android.mk文件,将c代码编译成 .so文件。mk写法参照ndk的
        • LOCAL_MODULE    := Hello //可随便起
        • LOCAL_SRC_FILES   := Hello.c
      • 5.activity中通过静态代码块 加载 动态库
        • static{  System.loadLibrary("Hello"); }  //去掉前后缀
      • 6.调用c代码
        • 直接调用native的方法名。
    • native方法名出现下划线的问题: call_from_c。在Hello.c文件中加1。MainActivity_call_1From_1c
  4. 采用javah生成头文件。
    •  dos命令下,进到activity的 classes目录,执行 javah  com.itheima.ndkhelloworld2.MainActivity,生成头文件获取签名,一定要在classes文件下
    • 拷贝生成的.h文件到工程的jni目录,并在 Hello.c 中引用 .h文件
  5. Android.mk文件
  6. JNI开发常见的错误
    • 忘记创建Android.mk文件或Android.mk文件为空
    • 中文的回车或者换行
    • java.lang.UnsatisfiedLinkError: hello
      • 忘记加载了c代码的.so库 或者 函数的签名不正确,没有找到与之对应的c代码
      • 没有找到对应的c代码库
    • *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***07-30 11:53:17.898: INFO/DEBUG(31): Build fingerprint: 'generic/sdk/generic/:2.2/FRF91/43546:eng/test-keys'
      • c代码里面有严重的逻辑错误,产生内存的泄露.
    • make: *** [obj/local/armeabi/objs/Hello/Hello.o] Error 1
      • 编译的时候 程序出现了问题,c语言的语法有问题
      • c语言代码编译错误的时候 先去解决第一个错误.
二、
  1. java传递数据给c语言,c返回数据给java
    • 在c中使用logcat打印日志?
    • public  native  int  add(int  x , int  y);
      • c代码的int 类型和java的int类型不需转换
      • JNIEXPORT  jint  JNICALL Java_com_itheima_ndk3_DataProvider_add(JNIEnv * env, jobject jobj, jint x, jint y){
      • LOGI("int x = %d", x);
      • LOGD("int y = %d", y);
      • return x+y;
      • }
    • public  native  String  sayHello(String  name);
      • char*  cstr  = Jstring2CStr(env,jstr);
      • LOGI(cstr);
      • strcat(cstr," hello");  //导入 <stdlib.h>  文件
      • LOGI(cstr);
      • return  (*env)->NewStringUTF( env , cstr );
    • public  native  int[]  getArrayFromc( int[]  arr );
      • jint* arrint = (*env)->GetIntArrayElements(env,jarr,0);
      • int len = (*env)->GetArrayLength(env,jarr);
      • int i;
      • for(i=0;i<len;i++){
      • LOGI( "arr[%d]=%d" , i , arrint[i] );
      • *(arrint+i)+=10;
      • }
      • return jarr;
  2. 实际开发流程

  3. c语言回调用java方法. 
    • c语言回调java的一个应用场景.
      • 如果有一个操作已经有方便的java实现,才用c调用java可以避免重复发明一个轮子.
    • c语言回调java的第二个应用场景.
      • 想在c代码里面通知界面更新ui.
    • 哪个对象调用了本地方法,哪个对象就是 jobject,不是同一个类中的方法调用,c中使用AllocObject类
      •   jobject     (*AllocObject)(JNIEnv*, jclass);
    • c调用java的静态方法:
      •  void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值