Android JNI開發提高篇

來源:互聯網
上載者:User
有關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的實現:

  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++的實現:

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運算的結果。

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<length; i++)
  {
     sum += pointer[i]; //相加每個數組元素
  }
  (*env)->ReleaseIntArrayElements(env, array, pointer, 0); //釋放記憶體,這個不能忘了
  return sum;
}

  如何在JNI中構造一個數組呢?  Android開發網給大家一個簡單的樣本,返回一個整形數組:

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類發生了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, "<init>", "()V");
  jthrowable throwable = (*env)->NewObject(env, clazz, methodId);

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

/**
* @author 張興業
* 郵箱:xy-zhang#163.com
* android開發進階群:278401545
*
*/

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.