要想閱讀並調試下文源碼,首先要確保你的NDK環境是ok的;
編譯環境:win7+Eclipse+ADT+SDK+NDK;基本用最新的就ok。
說明下,下文代碼就是一個簡單的個人jni實現【挺簡單的個實現,只是完整實現出來之間經曆了好多曲折,記錄下呵】;
不是現成的例子,是自己學習了下jni對Java、c/c++的映射關係之後的一個實現,如有不妥請指正。
先看一下開始到結束的流程: 【1-10步】
而後產生相應的*.so動態庫,自動嵌入到libs/armeabi目錄下;
其中obj目錄下產生的是中間檔案*.o;其中控制台輸出的日誌我還不清楚什麼意思,有明白的請明示:
10.正常操作後的效果示範:
日誌效果:
真機實測效果:
好啦, 到現在為止,效果已經看的差不多了,那麼接下來就是上代碼了··
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下面將顯示來自jni端的返回--" /> <TextView android:id="@+id/show_jni_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/textView2" android:layout_below="@+id/textView2" android:layout_marginTop="77dp" android:text="此處即將顯示來自jni的訊息--" /> <Button android:id="@+id/jni_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentRight="true" android:layout_below="@+id/textView2" android:layout_marginTop="17dp" android:text="點擊此btn調用jni方法" /></RelativeLayout>
package com.quanjin.jni;import android.os.Bundle;import android.app.Activity;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class QuanjinJniActivity extends Activity implements OnClickListener {private static final String TAG = "MainActivity";private Button jniButton;private TextView showJniText;//載入共用庫static {System.loadLibrary("quanjin_jni");//去掉共用庫的首碼lib/尾碼so}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_quanjin_jni);Log.d(TAG, show());//log查看返回值。Log.d("info_out", show());jniButton = (Button) findViewById(R.id.jni_btn);showJniText = (TextView) findViewById(R.id.show_jni_text);jniButton.setOnClickListener(this);}//聲明native方法 在jni中實現。private native String show();private void callback() {Log.d(TAG, " call back from native");//故意拋出一個異常留給jni處理,如果處理,java層就不會拋;不處理,java層就會拋出異常;throw new NullPointerException();}@Overridepublic void onClick(View v) {if(v.getId() == R.id.jni_btn) {//將jni返回值顯示在特定控制項上。showJniText.setText(show());}}}
#include <string.h>#include <jni.h>jstringJava_com_quanjin_jni_QuanjinJniActivity_show( JNIEnv* env, jobject thiz){//通過此方法得到傳入對象的類型資訊//此時的對象,就是調用native方法的那個對象jclass jcls = (*env)->GetObjectClass(env, thiz);//根據類資訊得到callback方法的methodIDjmethodID jmId = (*env)->GetMethodID(env, jcls, "callback", "()V");//調用callback方法(*env)->CallVoidMethod(env, thiz, jmId);//Java層的callback方法中拋出異常, 故此時 jni調用必然出現異常, 必須檢查並處理異常;否則異常將會拋給Java層的callback方法;//而此時的Java層的callback也未捕獲異常, 故:此時進程死掉;if((*env)->ExceptionCheck(env)){(*env)->ExceptionDescribe(env);(*env)->ExceptionClear(env);//清除異常;如果登出此句,異常將被拋回至Java層,即Java層中將在log中顯示異常情況;}//處理異常後響應Java層的調用return (*env)->NewStringUTF(env, "show message from jni by quanjin!""\n ABCDEFGHIGKLMNOPQRSTUVWXYZ \n ""when you have watch the above messages, congratulations, you got it!");//中文貌似亂碼了-- 大爺的 \\n 中文: 這是來自本人寫的jni內容, 當你看到這些話的時候呢, 恭喜你, jni調用成功啦}
說明下: 如果沒接觸過的同志們,可能看起來雲裡霧裡的,閱讀前先熟悉下比較好【稍後部落格繼續探討】;
詳情見代碼注釋。主要用Java反射,通過獲得由jni傳進來的對象引用,然後相繼獲得其他資訊;
至於拓展開來,其他商務邏輯該怎麼去展開,之後部落格再寫一下,今天的內容主要是開個頭吧~~~
嗯 , 基本先說這麼多吧; 百聞不如一試試,完整的項目就不貼出來了, 如果有需要進一步研究的請留言附郵箱地址。
1. 我之前一直在項目過程中抽空研究其實過程中既增強了自己對物件導向的理解,又可以更深入的研究Android架構源碼(Java+C++);
感覺都是差不多的,瞭解基礎性內容不難,若真想做到融會貫通,短時間內不太容易,慢慢深入慢慢研究吧;
2. 是個好東西哦~ 無論是哪個版本的,有空的時候閱讀一下,感覺真的很爽;就像你在拜讀一本武林秘籍一樣,你也不知道該怎麼讀,但是當你開始著迷的時候便一發不可收拾,太棒了!