在一些Android應用的開發中,需要通過JNI和 Android NDK工具實現JAVA和C/C++之間的相互調用。
Java Native Interface (JNI)標準是java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。JNI是本地編程接口,它使得在 Java 虛擬機 (VM)內部運行的 Java代碼能夠與用其它編程語言(如 C、C++和彙編語言)編寫的應用程序和庫進行交互操作。
由於Android的應用層的類都是以Java寫的,這些Java類編譯爲Dex型式的Bytecode之後,必須靠Dalvik虛擬機(VM: Virtual Machine)來執行。在執行Java類的過程中,如果Java類需要與C組件溝通時,VM就會去載入C組件,然後讓Java的函數順利地調用到C組件的函數。此時,VM扮演着橋樑的角色,讓Java與C組件能通過標準的JNI介面而相互溝通。
在實際應用中這兩者之間的調用關係可以歸納爲以下四種方式:
1. 在應用的JAVA代碼中調用NDK中C/C++實現的函數。
2. 在NDK開發中的C/C++代碼調用應用中JAVA類的靜態函數。
3. 在NDK開發中的C/C++代碼調用應用中JAVA類當前傳入NDK中的實例的函數。
4. 在NDK開發中的C/C++代碼調用應用中JAVA類新建實例的函數。
下面我們就怎樣在Eclipse中實現JNI編碼和四種調用方式加以闡述。
一、在Eclipse中建立一個包含JNI開發的工程。
在這裏我們不直接導入NDK中的hello-jni來說明JNI的使用方法。而是新建立一個工程,來說明怎樣建立一個包含JNI的工程。
第一步:建立一個Andriod工程JniDemo,在該工程的根目錄下建立一個叫jni的目錄,在jni目錄下建立一個叫Android.mk的文件,(當然你也可以從其他地方,比如ndk樣例代碼hello-jni中將裏面的Android.mk複製過來修改)。 Android.mk裏面的內容如下所示
LOCAL_PATH :=$(call my-dir)
include$(CLEAR_VARS)
LOCAL_MODULE := demo-jni
LOCAL_SRC_FILES := demo-jni.c
include$(BUILD_SHARED_LIBRARY)
關於這幾句話的含義,在這裏不再贅述。網上搜下,就可以很明白。
然後在jni目錄下生成demo-jni.c文件。實現的接口的內容。
現在選中工程中的jni目錄,點擊鼠標右鍵,選Refresh,jni目錄中的文件就顯示在工程的jni目錄下了。
第二步:設置jni的編譯環境。選中工程中的根目錄JniDemo,點擊鼠標右鍵,選Properties。彈出對話框,選中列表中的Builders。如圖一所示:
圖一:JniDemo特性設置對話框
點擊對話框右端的new按鈕,彈出“Choose configuration type”對話框,如圖二,選擇Program,點擊對話框下面的OK按鈕。
圖二:選擇配置類型
現在我們打開了”Edit Configuration”對話框,在Name對應的文本框中輸入名字JniBuilder(當然也可是你喜歡的其他名字).在Main選項下,在Location中輸入cygwin系統中bash.exe的絕對路徑。我這裏是c:\cygwin\bin\bash.exe(c:\cygwin\爲我的系統中cygwin的安裝目錄,這裏要根據你的電腦中cygwin的安裝目錄來確定),在Working Directory中輸入c:\cygwin\bin\.在Arguments中輸入--login -c "cd /cygdrive/d/study/JniDemo && /cygdrive/d/android-ndk-r6b/ndk-build"。這裏/cygdrive/d/study/JniDemo爲工程根目錄, /cygdrive/d/android-ndk-r6b爲NDK的安裝目錄。這兩個目錄參數根據你的工程目錄和ndk的安裝目錄而定。注意的是驅動器要採用cygwin的方式。(比如:Windows系統下的D:對應/cygdrive/d,其餘類推)。設置結果如圖三所示,然後點擊 OK按鈕即可。
圖三:編輯JNI配置參數
二、演示四種調用方式
演示界面如圖四所示,四個按鈕分別測試四種調用方式。
圖四:演示界面圖
分別點擊按鈕Test1, Test2, Tes3, Test四的測試結果如圖五、六、七、八所示。
圖五:點擊Test1的測試結果
圖六:點擊Test2的測試結果
圖七:點擊Test3的測試結果
圖八:點擊Test4的測試結果
Test1演示在應用中調用NDK中C/C++實現的函數。JAVA代碼和C代碼分別爲:
JAVA 代碼:
- Button btn01 = (Button)findViewById(R.id.Button01);
- btn01.setOnClickListener(new Button.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- TextView tv = (TextView)findViewById(R.id.tv01);
- tv.setText(stringFromJNI());
- showMessage(JniDemoActivity.this,"JNI test1", stringFromJNI());
- }
- });
Button btn01 = (Button)findViewById(R.id.Button01);
btn01.setOnClickListener(new Button.OnClickListener()
{
publicvoid onClick(View v)
{
TextView tv = (TextView)findViewById(R.id.tv01);
tv.setText(stringFromJNI());
showMessage(JniDemoActivity.this,"JNI test1", stringFromJNI());
}
});
C代碼:
- Jstring Java_study_jnidemo_JniDemoActivity_stringFromJNI( JNIEnv* env,jobject thiz )
- {
- return (*env)->NewStringUTF(env,"JniDemo, Hello from JNI!");
- }
Jstring Java_study_jnidemo_JniDemoActivity_stringFromJNI( JNIEnv* env,jobject thiz )
{
return (*env)->NewStringUTF(env,"JniDemo, Hello from JNI!");
}
l Test2 靜態調用。JAVA代碼和C代碼分別爲:
JAVA 代碼:
- // 測試C/C++中對JAVA函數的靜態回調
- Button btn02 = (Button)findViewById(R.id.Button02);
- btn02.setOnClickListener(new Button.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- int ret =jniStaticShowMessage(JniDemoActivity.this,"JNI test2","test static callback Message");
- TextView tv = (TextView)findViewById(R.id.tv01);
- if(ret == 0)
- {
- tv.setText("test JNI static callback successed");
- }
- else
- {
- tv.setText("test JNI static callback fialed");
- }
- }
- });
// 測試C/C++中對JAVA函數的靜態回調
Button btn02 = (Button)findViewById(R.id.Button02);
btn02.setOnClickListener(new Button.OnClickListener()
{
publicvoid onClick(View v)
{
int ret =jniStaticShowMessage(JniDemoActivity.this,"JNI test2","test static callback Message");
TextView tv = (TextView)findViewById(R.id.tv01);
if(ret == 0)
{
tv.setText("test JNI static callback successed");
}
else
{
tv.setText("test JNI static callback fialed");
}
}
});
C代碼:
- Jint Java_study_jnidemo_JniDemoActivity_jniStaticShowMessage(JNIEnv* env,
Jint Java_study_jnidemo_JniDemoActivity_jniStaticShowMessage(JNIEnv* env,
- jobject thiz,jobject ctx, jstring strTitle, jstring strMessage)
- {
- jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
- // jclass cls = (*env)->GetObjectClass(env, thiz);
- if(cls != NULL)
- {
- jmethodID id = (*env)->GetStaticMethodID(env, cls,"staticShowMessage",
- "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
- if(id != NULL)
- {
- return (*env)->CallStaticIntMethod(env, cls, id, ctx, strTitle, strMessage);
- }
- }
- return 1;
- }
jobject thiz,jobject ctx, jstring strTitle, jstring strMessage)
{
jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
// jclass cls = (*env)->GetObjectClass(env, thiz);
if(cls != NULL)
{
jmethodID id = (*env)->GetStaticMethodID(env, cls,"staticShowMessage",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
if(id != NULL)
{
return (*env)->CallStaticIntMethod(env, cls, id, ctx, strTitle, strMessage);
}
}
return 1;
}
l Test3 當前實例調用:JAVA代碼和C代碼分別爲:
JAVA 代碼:
- Button btn03 = (Button)findViewById(R.id.Button03);
- btn03.setOnClickListener(new Button.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- strTest = " [message has changed now]";
- int ret = jniShowMessage(JniDemoActivity.this,"JNI test3","test callback in current instance");
- TextView tv = (TextView)findViewById(R.id.tv01);
- if(ret == 0)
- {
- tv.setText("test JNI callback successed");
- }
- else
- {
- tv.setText("test JNI callback fialed");
- }
- }
- });
Button btn03 = (Button)findViewById(R.id.Button03);
btn03.setOnClickListener(new Button.OnClickListener()
{
publicvoid onClick(View v)
{
strTest = " [message has changed now]";
int ret = jniShowMessage(JniDemoActivity.this,"JNI test3","test callback in current instance");
TextView tv = (TextView)findViewById(R.id.tv01);
if(ret == 0)
{
tv.setText("test JNI callback successed");
}
else
{
tv.setText("test JNI callback fialed");
}
}
});
C代碼:
- Jint Java_study_jnidemo_JniDemoActivity_jniShowMessage(JNIEnv* env, jobject thiz,
- jobject ctx, jstring strTitle, jstring strMessage)
- {
- jclass cls = (*env)->GetObjectClass(env, thiz);
- if(cls != NULL)
- {
- jstring str;
- jmethodID strTest_id = (*env)->GetMethodID(env, cls, "getTestString","()Ljava/lang/String;");
- if(strTest_id != NULL)
- {
- str = (*env)->CallObjectMethod(env, thiz, strTest_id);
- }
- jmethodID showMessage_id = (*env)->GetMethodID(env, cls, "showMessage",
- "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
- if(showMessage_id != NULL)
- {
- return (*env)->CallIntMethod(env, thiz, showMessage_id, ctx,
- strTitle, combine_jstring(env, strMessage, str));
- }
- }
- return 1;
- }
Jint Java_study_jnidemo_JniDemoActivity_jniShowMessage(JNIEnv* env, jobject thiz,
jobject ctx, jstring strTitle, jstring strMessage)
{
jclass cls = (*env)->GetObjectClass(env, thiz);
if(cls != NULL)
{
jstring str;
jmethodID strTest_id = (*env)->GetMethodID(env, cls, "getTestString","()Ljava/lang/String;");
if(strTest_id != NULL)
{
str = (*env)->CallObjectMethod(env, thiz, strTest_id);
}
jmethodID showMessage_id = (*env)->GetMethodID(env, cls, "showMessage",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
if(showMessage_id != NULL)
{
return (*env)->CallIntMethod(env, thiz, showMessage_id, ctx,
strTitle, combine_jstring(env, strMessage, str));
}
}
return 1;
}
l Test4新建實例調用:JAVA代碼和C代碼分別爲:
JAVA 代碼:
- Button btn04 = (Button)findViewById(R.id.Button04);
- btn04.setOnClickListener(newButton.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- strTest = " [message has changed now]";
- int ret = jniInstanceShowMessage(JniDemoActivity.this,
- JNI test4","test callback in new instance");
- TextView tv = (TextView)findViewById(R.id.tv01);
- if(ret == 0)
- {
- tv.setText("test JNI new instance successed");
- }
- else
- {
- tv.setText("test JNI new instance fialed");
- }
- }
- });
Button btn04 = (Button)findViewById(R.id.Button04);
btn04.setOnClickListener(newButton.OnClickListener()
{
publicvoid onClick(View v)
{
strTest = " [message has changed now]";
int ret = jniInstanceShowMessage(JniDemoActivity.this,
"JNI test4","test callback in new instance");
TextView tv = (TextView)findViewById(R.id.tv01);
if(ret == 0)
{
tv.setText("test JNI new instance successed");
}
else
{
tv.setText("test JNI new instance fialed");
}
}
});
C代碼:
- jint Java_study_jnidemo_JniDemoActivity_jniInstanceShowMessage(JNIEnv* env, jobject thiz,
- jobject ctx, jstring strTitle, jstring strMessage)
- {
- jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
- if(cls != NULL)
- {
- // get instance
- jmethodID constuctor_id = (*env)->GetMethodID(env, cls, "<init>", "()V");
- if(constuctor_id != NULL)
- {
- jobject obj = (*env)->NewObject(env, cls, constuctor_id);
- if(obj != NULL)
- {
- jstring str;
- jmethodID strTest_id = (*env)->GetMethodID(env, cls, "getTestString","()Ljava/lang/String;");
- if(strTest_id != NULL)
- {
- str = (*env)->CallObjectMethod(env, obj, strTest_id);
- }
- jmethodID showMessage_id = (*env)->GetMethodID(env, cls,"showMessage",
- "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
- if(showMessage_id != NULL)
- {
- return (*env)->CallIntMethod(env, obj, showMessage_id, ctx,strTitle, combine_jstring(env, strMessage, str));
- }
- }
- }
- }
- return 1;
- }
jint Java_study_jnidemo_JniDemoActivity_jniInstanceShowMessage(JNIEnv* env, jobject thiz,
jobject ctx, jstring strTitle, jstring strMessage)
{
jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
if(cls != NULL)
{
// get instance
jmethodID constuctor_id = (*env)->GetMethodID(env, cls, "<init>", "()V");
if(constuctor_id != NULL)
{
jobject obj = (*env)->NewObject(env, cls, constuctor_id);
if(obj != NULL)
{
jstring str;
jmethodID strTest_id = (*env)->GetMethodID(env, cls, "getTestString","()Ljava/lang/String;");
if(strTest_id != NULL)
{
str = (*env)->CallObjectMethod(env, obj, strTest_id);
}
jmethodID showMessage_id = (*env)->GetMethodID(env, cls,"showMessage",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
if(showMessage_id != NULL)
{
return (*env)->CallIntMethod(env, obj, showMessage_id, ctx,strTitle, combine_jstring(env, strMessage, str));
}
}
}
}
return 1;
}
Test1 和Test2都是常規的調用,在這裏不做解釋了。現在我們看看Test3和Test4的區別,在Test3中,strTest
= " [message has changed now]" 在相應的代碼中都做了賦值。但是在Test4中並沒有改變,還是初始值。這是因爲Test創建了一個新實例,和應用的JAVA代碼中所賦值的實例並不是同一個。因此纔出現了不同的結果。
附完整的JAVA和C代碼
JAVAD代碼: JniDemoActivity.java
- package study.jnidemo;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.os.Bundle;
- import android.widget.Button;
- import android.view.View;
- import android.widget.TextView;
- import android.content.Context;
- import android.content.DialogInterface;
- publicclass JniDemoActivityextends Activity {
- public StringstrTest =" [initial message]";
- /** Called when the activity is first created. */
- @Override
- publicvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- findAndModifyButton();
- }
- public String getTestString()
- {
- returnstrTest;
- }
- // 測試JAVA的NDK調用
- publicnative String stringFromJNI();
- // 測試C/C++中對JAVA函數的靜態回調
- publicnativestaticint jniStaticShowMessage(Context ctx, String strTitle, String strMessage);
- // 測試實例中C/C++中對JAVA類的函數的調用
- publicnativeint jniShowMessage(Context ctx, String strTitle, String strMessage);
- // 測試創建新實例C/C++對JAVA類的函數的調用
- publicnativeint jniInstanceShowMessage(Context ctx, String strTitle, String strMessage);
- static {
- System.loadLibrary("demo-jni");
- }
- staticint staticShowMessage(Context ctx, String strTitle, String strMessage)
- {
- AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
- builder.setTitle(strTitle);
- builder.setMessage(strMessage);
- builder.setPositiveButton("確定",
- new DialogInterface.OnClickListener(){
- public void onClick(DialogInterface dialog,int whichButton){
- }
- });
- builder.show();
- return 0;
- }
- publicint showMessage(Context ctx, String strTitle, String strMessage)
- {
- returnstaticShowMessage(ctx, strTitle, strMessage);
- }
- privatevoid findAndModifyButton()
- {
- // 測試JAVA的NDK調用
- Button btn01 = (Button)findViewById(R.id.Button01);
- btn01.setOnClickListener(new Button.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- TextView tv = (TextView)findViewById(R.id.tv01);
- tv.setText(stringFromJNI());
- showMessage(JniDemoActivity.this,"JNI test1", stringFromJNI());
- }
- });
- // 測試C/C++中對JAVA函數的靜態回調
- Button btn02 = (Button)findViewById(R.id.Button02);
- btn02.setOnClickListener(new Button.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- int ret =jniStaticShowMessage(JniDemoActivity.this,"JNI test2", "test static callback Message");
- TextView tv = (TextView)findViewById(R.id.tv01);
- if(ret == 0)
- {
- tv.setText("test JNI static callback successed");
- }
- else
- {
- tv.setText("test JNI static callback fialed");
- }
- }
- });
- // 測試實例中C/C++中對JAVA類的函數的調用
- Button btn03 = (Button)findViewById(R.id.Button03);
- btn03.setOnClickListener(new Button.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- strTest = " [message has changed now]";
- int ret = jniShowMessage(JniDemoActivity.this,"JNI test3", "test callback in current instance");
- TextView tv = (TextView)findViewById(R.id.tv01);
- if(ret == 0)
- {
- tv.setText("test JNI callback successed");
- }
- else
- {
- tv.setText("test JNI callback fialed");
- }
- }
- });
- // 測試創建新實例C/C++對JAVA類的函數的調用
- Button btn04 = (Button)findViewById(R.id.Button04);
- btn04.setOnClickListener(new Button.OnClickListener()
- {
- publicvoid onClick(View v)
- {
- strTest = " [message has changed now]";
- int ret = jniInstanceShowMessage(JniDemoActivity.this,"JNI test4", "test callback in new instance");
- TextView tv = (TextView)findViewById(R.id.tv01);
- if(ret == 0)
- {
- tv.setText("test JNI new instance successed");
- }
- else
- {
- tv.setText("test JNI new instance fialed");
- }
- }
- });
- }
- }
package study.jnidemo;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import android.widget.Button;
import android.view.View;
import android.widget.TextView;
import android.content.Context;
import android.content.DialogInterface;
publicclass JniDemoActivityextends Activity {
public StringstrTest =" [initial message]";
/** Called when the activity is first created. */
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findAndModifyButton();
}
public String getTestString()
{
returnstrTest;
}
// 測試JAVA的NDK調用
publicnative String stringFromJNI();
// 測試C/C++中對JAVA函數的靜態回調
publicnativestaticint jniStaticShowMessage(Context ctx, String strTitle, String strMessage);
// 測試實例中C/C++中對JAVA類的函數的調用
publicnativeint jniShowMessage(Context ctx, String strTitle, String strMessage);
// 測試創建新實例C/C++對JAVA類的函數的調用
publicnativeint jniInstanceShowMessage(Context ctx, String strTitle, String strMessage);
static {
System.loadLibrary("demo-jni");
}
staticint staticShowMessage(Context ctx, String strTitle, String strMessage)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle(strTitle);
builder.setMessage(strMessage);
builder.setPositiveButton("確定",
new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog,int whichButton){
}
});
builder.show();
return 0;
}
publicint showMessage(Context ctx, String strTitle, String strMessage)
{
returnstaticShowMessage(ctx, strTitle, strMessage);
}
privatevoid findAndModifyButton()
{
// 測試JAVA的NDK調用
Button btn01 = (Button)findViewById(R.id.Button01);
btn01.setOnClickListener(new Button.OnClickListener()
{
publicvoid onClick(View v)
{
TextView tv = (TextView)findViewById(R.id.tv01);
tv.setText(stringFromJNI());
showMessage(JniDemoActivity.this,"JNI test1", stringFromJNI());
}
});
// 測試C/C++中對JAVA函數的靜態回調
Button btn02 = (Button)findViewById(R.id.Button02);
btn02.setOnClickListener(new Button.OnClickListener()
{
publicvoid onClick(View v)
{
int ret =jniStaticShowMessage(JniDemoActivity.this,"JNI test2", "test static callback Message");
TextView tv = (TextView)findViewById(R.id.tv01);
if(ret == 0)
{
tv.setText("test JNI static callback successed");
}
else
{
tv.setText("test JNI static callback fialed");
}
}
});
// 測試實例中C/C++中對JAVA類的函數的調用
Button btn03 = (Button)findViewById(R.id.Button03);
btn03.setOnClickListener(new Button.OnClickListener()
{
publicvoid onClick(View v)
{
strTest = " [message has changed now]";
int ret = jniShowMessage(JniDemoActivity.this,"JNI test3", "test callback in current instance");
TextView tv = (TextView)findViewById(R.id.tv01);
if(ret == 0)
{
tv.setText("test JNI callback successed");
}
else
{
tv.setText("test JNI callback fialed");
}
}
});
// 測試創建新實例C/C++對JAVA類的函數的調用
Button btn04 = (Button)findViewById(R.id.Button04);
btn04.setOnClickListener(new Button.OnClickListener()
{
publicvoid onClick(View v)
{
strTest = " [message has changed now]";
int ret = jniInstanceShowMessage(JniDemoActivity.this,"JNI test4", "test callback in new instance");
TextView tv = (TextView)findViewById(R.id.tv01);
if(ret == 0)
{
tv.setText("test JNI new instance successed");
}
else
{
tv.setText("test JNI new instance fialed");
}
}
});
}
}
C代碼 demo-jni.cpp
- #include<string.h>
- #include<jni.h>
- // 加載此動態庫時系統自動首先加載
- jint JNI_OnLoad(JavaVM* vm, void *reserved)
- {
- JNIEnv *env;
- if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK)
- {
- return -1;
- }
- return JNI_VERSION_1_4;
- }
- jstring
- Java_study_jnidemo_JniDemoActivity_stringFromJNI( JNIEnv* env,jobject thiz )
- {
- return (*env)->NewStringUTF(env,"JniDemo, Hello from JNI!");
- }
- jstring
- combine_jstring(JNIEnv* env, jstring str1, jstring str2)
- {
- jboolean b_ret;
- constchar *s1 = (*env)->GetStringUTFChars(env, str1, &b_ret);
- constchar *s2 = (*env)->GetStringUTFChars(env, str2, &b_ret);
- int n1 = strlen(s1);
- int n2 = strlen(s2);
- char *new_str = (char *)malloc(n1+n2+1);
- memset(new_str, 0, n1+n2+1);
- strcat(new_str, s1);
- strcat(new_str, s2);
- jstring ret_str = (*env)->NewStringUTF(env,(constchar *)new_str);
- free(new_str);
- return ret_str;
- }
- jint
- Java_study_jnidemo_JniDemoActivity_jniStaticShowMessage(JNIEnv* env, jobject thiz,
- jobject ctx, jstring strTitle, jstring strMessage)
- {
- jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
- // jclass cls = (*env)->GetObjectClass(env, thiz);
- if(cls != NULL)
- {
- jmethodID id = (*env)->GetStaticMethodID(env, cls,
- "staticShowMessage",
- "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
- if(id != NULL)
- {
- return (*env)->CallStaticIntMethod(env, cls, id, ctx, strTitle, strMessage);
- }
- }
- return 1;
- }
- // 在當前已有的JAVA實例中調用
- jint
- Java_study_jnidemo_JniDemoActivity_jniShowMessage(JNIEnv* env, jobject thiz,
- jobject ctx, jstring strTitle, jstring strMessage)
- {
- jclass cls = (*env)->GetObjectClass(env, thiz);
- if(cls != NULL)
- {
- jstring str;
- jmethodID strTest_id = (*env)->GetMethodID(env, cls, "getTestString",
- "()Ljava/lang/String;");
- if(strTest_id != NULL)
- {
- str = (*env)->CallObjectMethod(env, thiz, strTest_id);
- }
- jmethodID showMessage_id = (*env)->GetMethodID(env, cls, "showMessage",
- "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
- if(showMessage_id != NULL)
- {
- return (*env)->CallIntMethod(env, thiz, showMessage_id, ctx,
- strTitle, combine_jstring(env, strMessage, str));
- }
- }
- return 1;
- }
- // 在新建JAVA實例中調用
- jint
- Java_study_jnidemo_JniDemoActivity_jniInstanceShowMessage(JNIEnv* env, jobject thiz,
- jobject ctx, jstring strTitle, jstring strMessage)
- {
- jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
- if(cls != NULL)
- {
- // get instance
- jmethodID constuctor_id = (*env)->GetMethodID(env, cls, "<init>", "()V");
- if(constuctor_id != NULL)
- {
- jobject obj = (*env)->NewObject(env, cls, constuctor_id);
- if(obj != NULL)
- {
- jstring str;
- jmethodID strTest_id = (*env)->GetMethodID(env, cls,"getTestString",
- "()Ljava/lang/String;");
- if(strTest_id != NULL)
- {
- str = (*env)->CallObjectMethod(env, obj, strTest_id);
- }
- jmethodID showMessage_id = (*env)->GetMethodID(env, cls,"showMessage",
- "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
- if(showMessage_id != NULL)
- {
- return (*env)->CallIntMethod(env, obj, showMessage_id, ctx,
- strTitle, combine_jstring(env, strMessage, str));
- }
- }
- }
- }
- return 1;
- }
#include<string.h>
#include<jni.h>
// 加載此動態庫時系統自動首先加載
jint JNI_OnLoad(JavaVM* vm, void *reserved)
{
JNIEnv *env;
if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK)
{
return -1;
}
return JNI_VERSION_1_4;
}
jstring
Java_study_jnidemo_JniDemoActivity_stringFromJNI( JNIEnv* env,jobject thiz )
{
return (*env)->NewStringUTF(env,"JniDemo, Hello from JNI!");
}
jstring
combine_jstring(JNIEnv* env, jstring str1, jstring str2)
{
jboolean b_ret;
constchar *s1 = (*env)->GetStringUTFChars(env, str1, &b_ret);
constchar *s2 = (*env)->GetStringUTFChars(env, str2, &b_ret);
int n1 = strlen(s1);
int n2 = strlen(s2);
char *new_str = (char *)malloc(n1+n2+1);
memset(new_str, 0, n1+n2+1);
strcat(new_str, s1);
strcat(new_str, s2);
jstring ret_str = (*env)->NewStringUTF(env,(constchar *)new_str);
free(new_str);
return ret_str;
}
jint
Java_study_jnidemo_JniDemoActivity_jniStaticShowMessage(JNIEnv* env, jobject thiz,
jobject ctx, jstring strTitle, jstring strMessage)
{
jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
// jclass cls = (*env)->GetObjectClass(env, thiz);
if(cls != NULL)
{
jmethodID id = (*env)->GetStaticMethodID(env, cls,
"staticShowMessage",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
if(id != NULL)
{
return (*env)->CallStaticIntMethod(env, cls, id, ctx, strTitle, strMessage);
}
}
return 1;
}
// 在當前已有的JAVA實例中調用
jint
Java_study_jnidemo_JniDemoActivity_jniShowMessage(JNIEnv* env, jobject thiz,
jobject ctx, jstring strTitle, jstring strMessage)
{
jclass cls = (*env)->GetObjectClass(env, thiz);
if(cls != NULL)
{
jstring str;
jmethodID strTest_id = (*env)->GetMethodID(env, cls, "getTestString",
"()Ljava/lang/String;");
if(strTest_id != NULL)
{
str = (*env)->CallObjectMethod(env, thiz, strTest_id);
}
jmethodID showMessage_id = (*env)->GetMethodID(env, cls, "showMessage",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
if(showMessage_id != NULL)
{
return (*env)->CallIntMethod(env, thiz, showMessage_id, ctx,
strTitle, combine_jstring(env, strMessage, str));
}
}
return 1;
}
// 在新建JAVA實例中調用
jint
Java_study_jnidemo_JniDemoActivity_jniInstanceShowMessage(JNIEnv* env, jobject thiz,
jobject ctx, jstring strTitle, jstring strMessage)
{
jclass cls = (*env)->FindClass(env, "study/jnidemo/JniDemoActivity");
if(cls != NULL)
{
// get instance
jmethodID constuctor_id = (*env)->GetMethodID(env, cls, "<init>", "()V");
if(constuctor_id != NULL)
{
jobject obj = (*env)->NewObject(env, cls, constuctor_id);
if(obj != NULL)
{
jstring str;
jmethodID strTest_id = (*env)->GetMethodID(env, cls,"getTestString",
"()Ljava/lang/String;");
if(strTest_id != NULL)
{
str = (*env)->CallObjectMethod(env, obj, strTest_id);
}
jmethodID showMessage_id = (*env)->GetMethodID(env, cls,"showMessage",
"(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I");
if(showMessage_id != NULL)
{
return (*env)->CallIntMethod(env, obj, showMessage_id, ctx,
strTitle, combine_jstring(env, strMessage, str));
}
}
}
}
return 1;
}
歡迎進入我的微信公衆號: