1、建立Android應用
application name: CallJavaMethod
package name: com.example.cjm
main Activity: MainActivity
main Activity layout: activity_main
2、Java實現
打開layout/activity_main.xml布局文件,添加按鈕控件,ID為“display_button_activity_main”
<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" > <Button android:id="@+id/display_button_activity_main" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="Display" tools:context=".MainActivity" /> </RelativeLayout>
新建接口CJMListener,定義接口方法displaymessage
package com.example.cjm; public interface CJMListener { void displayMessage(String message); }
新建類CJM,實現接口CJMListener
定義native public方法displaySomething
package com.example.cjm; import android.os.Handler; public class CJM implements CJMListener { static { System.loadLibrary("cjm"); } private Handler handler; private CJMListener listener; public CJM(CJMListener listener) { handler = new Handler(); this.listener = listener; } @Override public void displayMessage(final String message) { handler.post(new Runnable() { @Override public void run() { listener.displayMessage(message); } }); } public native void displaySomething(); }
為MainActivity類,實現CJMListener,添加CMJ對象域
添加Button對象域,引用在布局文件中定義ID為“display_button_activity_main”的按鈕控件
package com.example.cjm; import android.os.Handler; public class CJM implements CJMListener { static { System.loadLibrary("cjm"); } private Handler handler; private CJMListener listener; public CJM(CJMListener listener) { handler = new Handler(); this.listener = listener; } @Override public void displayMessage(final String message) { handler.post(new Runnable() { @Override public void run() { listener.displayMessage(message); } }); } public native void displaySomething(); }
當用戶按下按鈕,執行CJM對象的displaySomething方法
類CJM的displaySomething方法使用native關鍵字進行聲明,將使用native code實現
實現上,在nativie code中,會回調CJM對象的displayerMessage方法,並傳遞String類型的消息,用於顯示
注意,在CJM類中displayerMessage的實現,由於native code並不是在主線程中執行,所以使用了Android的Handler執行MainActivity的方法
3、C實現
使用javah為CJM的native方法生成頭文件(步驟省略……)
新建.c文件,實現該頭文件的方法
#include "com_example_cjm_CJM.h" JNIEXPORT void JNICALL Java_com_example_cjm_CJM_displaySomething (JNIEnv *env, jobject thiz) { jclass ClassCJM = (*env)->FindClass(env, "com/example/cjm/CJM"); jmethodID MethodDisplayMessage = (*env)->GetMethodID(env, ClassCJM, "displayMessage", "(Ljava/lang/String;)V"); jstring value = (*env)->NewStringUTF(env, "Hello World!"); (*env)->CallVoidMethod(env, thiz, MethodDisplayMessage, value); }
JNI調用Java方法的步驟:
1) 獲取jmethodID;
GetMethodID
jmethodID GetMethodID(JNIEnv *env, jclass clazz,
const char *name, const char *sig);
Returns the method ID for an instance (nonstatic) method of a class or interface. The method may be defined in one of the clazz’s superclasses and inherited by clazz. The method is determined by its name and signature.
GetMethodID() causes an uninitialized class to be initialized.
To obtain the method ID of a constructor, supply <init> as the method name and void (V) as the return type.
2) 調用Java方法;
NativeType Call<type>Method(JNIEnv *env, jobject obj,
jmethodID methodID, ...);
Methods from these three families of operations are used to call a Java instance method from a native method.They only differ in their mechanism for passing parameters to the methods that they call.
These families of operations invoke an instance (nonstatic) method on a Java object, according to the specified method ID. The methodID argument must be obtained by calling GetMethodID().
When these functions are used to call private methods and constructors, the method ID must be derived from the real class of obj, not from one of its superclasses.
Instance Method Calling Routines:
CallVoidMethod | void |
CallObjectMethod | jobject |
CallBooleanMethod | jboolean |
CallByteMethod | jbyte |
CallCharMethod | jchar |
CallShortMethod | jshort |
CallIntMethod | jint |
CallLongMethod | jlong |
CallFloatMethod | jfloat |
CallDoubleMethod | jdouble |
運行結果截圖: