JNI使用流程

熟悉JNI开发:
 JNI:java本地开发接口(Java Native Interface)
 想要在java的应用程序里面调用C代码,就必须用到JNI
 JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(c/c++)
 通过这个协议,java代码就可以调用外部的c/c++代码,
    外部的c/c++代码也可以调用java代码
    
为什么要用JNI:
 JNI扩展了java虚拟机的能力
 Native code(c代码) 效率高。在数学运算,实时渲染的游戏,音视频处理(极品飞车)。

为什么c比java高效???
 暂时理解为java是夸平台的,要通过虚拟机和操作系统进行交互,
 而c语言不是。
 
JNI开发流程:
 1.创建一个android工程
 2.JAVA代码中写声明native 方法 public native String helloFromJNI();
 3.用javah工具生成头文件
 4. 创建jni目录,引入头文件,根据头文件实现c代码
 5.编写Android.mk文件
 6.Ndk编译生成动态库
 7.Java代码load 动态库.调用native代码
 
具体操作:
 ndkpassdata工程:
 1,在DataProvider.java中:(注意:这些方法都有一个修饰符native)
  /**
   * 把两个java中的int传递给c语言, c语言处理完毕后,把相加的结果返回给java
   * @param x
   * @param y
   * @return
   */
  public native int add(int x ,int y);
  /**
   * 把java中的string传递给c语言, c语言获取到java中的string之后 ,在string后面添加 一个hello 字符串
   * @param s
   * @return
   */
  public native String sayHelloInC(String s);
  /**
   * 把java中的一个int数组 传递给c语言,c语言处理完毕这个java数组
   * 把int数组中的每一个元素+10 ;
   * 然后把结果返回给java
   * @param iNum
   * @return
   */
  public native int[] intMethod(int[] iNum);
  
 2,DemoActivity.java中:
  private DataProvider provider;
  onCreate()方法中:provider=new DataProvider();
  public void onClick(View v) {
   switch (v.getId()) {
   case R.id.bt1:
    int result = provider.add(3, 5);
    Toast.makeText(this, "相加的结果"+result, 1).show();
    break;
 
   case R.id.bt2:
    String str = provider.sayHelloInC("zhangsan ");
    Toast.makeText(this, str, 1).show();
    break;
   case R.id.bt3:
    int[] arr = {1,2,3,4,5};
    provider.intMethod(arr);
    
    for(int i=0;i<arr.length;i++){
     System.out.println("java "+ arr[i]);
    }
    break;
  }
  
 3,利用javah生成头文件:
  命令行进入当前工程目录:cd /d G:\android-JNI\ndkpassdata_LJ
  然后进入bin目录:cd bin
  进入classes目录 :cd classes (classes目录下面包含当前工程所有编译好的class文件)
  然后生成头文件:javah cn.itcast.ndk3.DataProvider
  这样在classes目录下面就会有一个.h的头文件。
  
 4,在ndkpassdata工程下新建一个jni目录,把生成的头文件拷贝到该目录。
  在jni目录下新建一个Android.mk,并编写mk文件:
   LOCAL_PATH := $(call my-dir)
   include $(CLEAR_VARS)
   LOCAL_MODULE    :=Hello
   LOCAL_SRC_FILES :=Hello.c
   LOCAL_LDLIBS += -llog   //这一行的作用是为了在c代码中使用logcat
   include $(BUILD_SHARED_LIBRARY)
   
 5,编写在jni目录下新建Hello.c,并编写Hello.c
  #include<stdio.h>
  #include<jni.h>
  #include "cn_itcast_ndk3_DataProvider.h";
  #include <android/log.h>
  #include<malloc.h>
  #define LOG_TAG "System.out.c"
  #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
  #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
  
  JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add
    (JNIEnv * env, jobject obj , jint x, jint y){
   LOGD("x=%d",x);
   LOGD("y=%d",y);
   return x+y;
  }
  
  JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC
    (JNIEnv * env, jobject obj, jstring jstr ){
   //在c语言中 是没有java的String
   char* cstr = Jstring2CStr(env, jstr);
   LOGD("cstr=%s",cstr);
   // c语言中的字符串 都是以'/0' 作为结尾
   char arr[7]= {' ','h','e','l','l','o','\0'};
   strcat(cstr,arr);
   LOGD("new cstr=%s",cstr);
   return (*env)->NewStringUTF(env,cstr);
  }
  
  JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod
    (JNIEnv * env , jobject obj , jintArray arr){
   //1.知道数组的长度
   //2.操作这个数组里面的每一个元素
   int len = (*env)->GetArrayLength(env,arr);
   LOGD("shuzu len =%d",len);
   jint* intarr = (*env)->GetIntArrayElements(env,arr,1);
   int i =0; //c99
   for(;i<len;i++){
    //*(intarr+i) += 10;
    LOGD("intarr[%d]=%d", i, intarr[i]);
    intarr[i]+= 10;
   }
   return arr;
  }
 
 6,NDK编译生成动态库:
  打开Cygwin这个程序,
  1,cd cygdrive 
  2,cd g (进入G盘)
  3,cd android-JNI
  4,cd ndkpassdata_LJ
  5,ndk-build (把c代码编译成.so的可执行的二进制文件)
   这样在ndkpassdata_LJ/libs/armeabi就生成了一个libHello.so文件
  
 7,java代码load动态库,并调用native方法:
  DemoActivity.java中:
  static{
   System.loadLibrary("Hello");
   //注意这里的Hello和mk文件中的LOCAL_MODULE    :=Hello
   //还有libHello.so是对应的。。
  }

在 Android Studio 中进行 JNI(Java Native Interface)开发的流程如下: 1. 创建新的 Android 项目或打开现有项目。 2. 在项目的 `app` 模块下创建 `jni` 文件夹。可以右键点击 `app` 模块,选择 "New" -> "Folder" -> "JNI Folder"。 3. 在 `jni` 文件夹中创建一个新的 C/C++ 文件,例如 `native-lib.cpp`。 4. 在 `native-lib.cpp` 文件中编写您的 C/C++ 代码,可以与 Java 代码进行交互。 5. 打开 `CMakeLists.txt` 文件,它位于 `app` 模块的根目录中。如果没有该文件,则可以创建一个。 6. 在 `CMakeLists.txt` 文件中添加以下内容: ```cmake # 添加自动生成的 C/C++ 头文件 include_directories(src/main/cpp) # 添加你的 C/C++ 源文件 add_library(native-lib SHARED src/main/cpp/native-lib.cpp) ``` 7. 在 `MainActivity.java`(或您想要使用 JNI 的任何其他类)中,添加以下代码来加载和调用本地库: ```java static { System.loadLibrary("native-lib"); } // 调用本地方法示例 public native String yourNativeMethod(); ``` 8. 点击顶部菜单栏的 "Build" -> "Make Project" 来构建项目。 9. 如果一切顺利,您就可以在您的 Java 代码中调用您定义的本地方法了。 请注意,这只是一个简单的 JNI 开发流程示例。在实际开发中,您可能还需要处理类型转换、异常处理等其他细节。同时,您还需要了解更多关于 JNI 的知识,例如如何在 Java 和 C/C++ 之间传递数据、使用 JNI 的限制和最佳实践等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值