妈妈剪头发游戏:Android JNI开发提高篇

来源:百度文库 编辑:偶看新闻 时间:2024/06/28 09:22:16
有关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++有啥区别  这里Android123就以将Java的unicode字符串转为jni中的utf8,然后再返回一个jstring类型为例子,可以看到jni和java之间字符串的转换方法。  C的实现:view plaincopy to clipboardprint?
JNIEXPORT jstring JNICALL Java_Android123_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);  

JNIEXPORT jstring JNICALL Java_Android123_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++的实现:view plaincopy to clipboardprint?
JNIEXPORT jstring JNICALL Java_Android123_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);  

JNIEXPORT jstring JNICALL Java_Android123_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运算的结果。view plaincopy to clipboardprint?
JNIEXPORT jint JNICALL Java_Android123_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;  
 } 
JNIEXPORT jint JNICALL Java_Android123_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开发网给大家一个简单的示例,返回一个整形数组:view plaincopy to clipboardprint?
JNIEXPORT jobjectArray JNICALL  
Java_Android123_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;  

JNIEXPORT jobjectArray JNICALL
Java_Android123_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类发生了FileNotFoundview plaincopy to clipboardprint?
(*env)->ThrowNew(env,(*env)->FindClass("java/io/IOException"),"CWJLog Error, IOException"); 
(*env)->ThrowNew(env,(*env)->FindClass("java/io/IOException"),"CWJLog Error, IOException"); 方法2:  使用Throw,自己构造view plaincopy to clipboardprint?
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);