Android JNI 中级篇

本文介绍了JNI在Android平台的应用,包括C与C++的区别、数组处理及异常处理等关键技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


有关JNI的开发技术,我们继续围绕Android平台进行,JNI可以支持C或C++,从目前为止我们写过的JNI代码均为C实现的,即文件名为.C而C++的和这些有什么不同呢? Android平台上的JNI一般使用C还是C++编写呢?   Android平台在中间层和大部分的类库的底层使用了C++的开发方式,后缀为.cpp,比如Android Framework、OpenCore、Webkit、SQLite等等。使用C++好处就是可以使用很多库但目前Android不支持STL,我们知道 C表示字符串都是字符数组,但C++可以使用类似string这样的类型表示。

       1. 代码上编写C和C++有啥区别
  这里eoeAndroid就以将Java的unicode字符串转为jni中的utf8,然后再返回一个jstring类型为例子,可以看到jni和java之间字符串的转换方法。

   C的实现:

Java代码:

  1. JNIEXPORT jstring JNICALL Java_Android123_CwjC (JNIEnv *env, jobject obj, jstring string)
  2. {
  3. const char *strUTF = (*env)->GetStringUTFChars(env, string, 0);
  4. char szBuffer[255];
  5. strcpy(szBuffer, strUTF);
  6. (*env)->ReleaseStringUTFChars(env, string, strUTF);
  7. return (*env)->NewStringUTF(env, szBuffer);
  8. }

复制代码

       C++的实现:

Java代码:
  1. JNIEXPORT jstring JNICALL Java_Android123_CwjCpp (JNIEnv *env, jobject obj, jstring string)
  2. {
  3. const char *strUTF = env->GetStringUTFChars(string, 0);
  4. char szBuffer[255];
  5. strcpy(szBuffer, strUTF);
  6. env->ReleaseStringUTFChars(string, strUTF);
  7. return env->NewStringUTF(szBuffer);
  8. }

复制代码
        我们加粗了主要区别的关键字,可以看到C++的代码更简练。

       2. JNI操作数组代码

  JNI中处理数组通用对象为jobjectArray 当然常规的类型比如整形为jintArray,布尔型为jbooleanArray,但没有出现jstringArray这样的类型,有关字符数组的处理我们将在下次的 Android JNI开发进阶篇 详细说明 。处理数组时我们需要考虑数组的长度不能为0才能继续操作,不然就会有访问越界等问题,在JNI中提供了通用类型的 GetArrayLength函数。我们从Java传入一个以整形数组,在JNI中将每个元素相加为例返回一个整形告诉Java运算的结果。

Java代码:
  1. JNIEXPORT jint JNICALL Java_Android123_CwjTest (JNIEnv *env, jobject obj, jintArray array)
  2. {
  3. int sum = 0;
  4. jsize length = (*env)->GetArrayLength(env, array); //获取数组长度
  5. if(length==0) //防止异常发生,如果是空的需要返回了
  6. return 0;
  7. jint *pointer = (*env)->GetIntArrayElements(env, array, 0); //获取数组指针
  8. for (int i=0; i<="" p="">
  9. {
  10. sum += pointer[i]; //相加每个数组元素
  11. }
  12. (*env)->ReleaseIntArrayElements(env, array, pointer, 0); //释放内存,这个不能忘了

  13. return sum;
  14. }

复制代码

        如何在JNI中构造一个数组呢?  eoeAndroid给大家一个简单的示例,返回一个整形数组:

Java代码:

  1. JNIEXPORT jobjectArray JNICALL
  2. Java_eoeAndroid_CwjTest2(JNIEnv *env, jclass clazz)
  3. {
  4. jobjectArray result; //定义返回对象
  5. jclass intArrayClazz = (*env)->FindClass(env, "[I"); //查找整形数组
  6. if (intArrayClazz == NULL)
  7. {
  8. return NULL;
  9. }
  10. result = (*env)->NewObjectArray(env, size, intArrayClazz, NULL); //构造一个新的数组对象
  11. if (result == NULL)
  12. {
  13. return NULL;
  14. }
  15. for (int i = 0; i < 10 ; i++) //循环10次
  16. {
  17. jint szBuffer[256];
  18. int j;
  19. jintArray newIntArray = (*env)->NewIntArray(env, 10); //构造10个整形数组
  20. if (newIntArray == NULL)
  21. {
  22. return NULL;
  23. }
  24. for (j = 0; j < 10 ; j++) //10个
  25. {
  26. szBuffer[j] = i + j;
  27. }
  28. (*env)->SetIntArrayRegion(env, newIntArray, 0, 10, szBuffer); //设置长度为10个
  29. (*env)->SetObjectArrayElement(env, result, i, newIntArray);
  30. (*env)->DeleteLocalRef(env, newIntArray);
  31. }
  32. return result;
  33. }

复制代码

       3.  JNI中有关异常的处理
  JNI中抛出异常没有try...catch这样的,而是直接抛出错误
  方法1:  使用ThrowNew,比如IOException类发生了FileNotFound

Java代码:
  1. (*env)->ThrowNew(env,(*env)->FindClass("java/io/IOException"),"CWJLog Error, IOException");
复制代码
       方法2:  使用Throw,自己构造

Java代码:
  1. jclass clazz = (*env)->FindClass(env, "java/io/IOException");
  2. jmethodID methodId = (*env)->GetMethodID(env, clazz, "", "()V");
  3. jthrowable throwable = (*env)->NewObject(env, clazz, methodId);
  4. (*env)->Throw(env, throwable);

复制代码


系列之Android JNI基础篇的帖子链接 http://www.eoeandroid.com/thread-71578-1-1.html
系列之Android JNI高级篇的帖子链接 http://www.eoeandroid.com/thread-71582-1-1.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值