Android jni提高

本文探讨了在Android平台上使用JNI技术进行C和C++开发的区别,并通过示例代码展示了字符串转换及数组处理的方法。此外,还介绍了JNI中异常处理的两种常见方式。
 
Android JNI开发提高篇,有关JNI的开发技术,我们继续围绕Android平台进行,JNI可以支持C或C++,从目前为止我们写过的JNI代码均为C实现的,即文件名为.C而C++的和这些有什么不同呢? Android平台上的JNI一般使用C还是C++编写呢

有关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++有啥区别

这里安博中程就以将Java的unicode字符串转为jni中的utf8,然后再返回一个jstring类型为例子,可以看到jni和java之间字符串的转换方法。

C的实现:

JNIEXPORT jstring JNICALL Java__CwjC (JNIEnv *env, jobject obj, jstring string)

{

const char *strUTF = (*env)->GetStringUTFChars(env, string, 0);

char szBuffer[255];

strcpy(szBuffer, strUTF);

(*env)->ReleaseStringUTFChars(env, string, strUTF);

return (*env)->NewStringUTF(env, szBuffer);

}

C++的实现:

JNIEXPORT jstring JNICALL Java__CwjCpp (JNIEnv *env, jobject obj, jstring string)

{

const char *strUTF = env->GetStringUTFChars(string, 0);

char szBuffer[255];

strcpy(szBuffer, strUTF);

env->ReleaseStringUTFChars(string, strUTF);

return env->NewStringUTF(szBuffer);

}

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

2. JNI操作数组代码

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

JNIEXPORT jint JNICALL Java__CwjTest (JNIEnv *env, jobject obj, jintArray array)

{

int sum = 0;

jsize length = (*env)->GetArrayLength(env, array); //获取数组长度

if(length==0) //防止异常发生,如果是空的需要返回了

return 0;

jint *pointer = (*env)->GetIntArrayElements(env, array, 0); //获取数组指针

for (int i=0; i

{

sum += pointer[i]; //相加每个数组元素

}

(*env)->ReleaseIntArrayElements(env, array, pointer, 0); //释放内存,这个不能忘了

return sum;

}

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

JNIEXPORT jobjectArray JNICALL

Java__CwjTest2(JNIEnv *env, jclass clazz)

{

jobjectArray result; //定义返回对象

jclass intArrayClazz = (*env)->FindClass(env, "[I"); //查找整形数组

if (intArrayClazz == NULL)

{

return NULL;

}

result = (*env)->NewObjectArray(env, size, intArrayClazz, NULL); //构造一个新的数组对象

if (result == NULL)

{

return NULL;

}

for (int i = 0; i < 10 ; i++) //循环10次

{

jint szBuffer[256];

int j;

jintArray newIntArray = (*env)->NewIntArray(env, 10); //构造10个整形数组

if (newIntArray == NULL)

{

return NULL;

}

for (j = 0; j < 10 ; j++) //10个

{

szBuffer[j] = i + j;

}

(*env)->SetIntArrayRegion(env, newIntArray, 0, 10, szBuffer); //设置长度为10个

(*env)->SetObjectArrayElement(env, result, i, newIntArray);

(*env)->DeleteLocalRef(env, newIntArray);

}

return result;

}

3. JNI中有关异常的处理

JNI中抛出异常没有try...catch这样的,而是直接抛出错误

方法1: 使用ThrowNew,比如IOException类发生了FileNotFound

(*env)->ThrowNew(env,(*env)->FindClass("java/io/IOException"),"CWJLog Error, IOException");

方法2: 使用Throw,自己构造

jclass clazz = (*env)->FindClass(env, "java/io/IOException");

jmethodID methodId = (*env)->GetMethodID(env, clazz, "", "()V");

jthrowable throwable = (*env)->NewObject(env, clazz, methodId);

(*env)->Throw(env, throwable);

有关JNI的异常,要说的还有很多,我们将在下次详细说明这些。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值