03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写
1? 案例場景,通過C語言回調Java的代碼,案例的最終界面:
2? 案例的代碼結構如下:
3 編寫DataProvider的代碼:
| package com.example.ndkcallback; ? public class DataProvider { ??? //C調用java空方法 ??? public void helloFromJava(){ ?????? System.out.println("哈哈哈? 我被調用了"); ??? } ??? //C調用java中的帶兩個int參數的方法 ??? public int Add(int x,int y){ ?????? int result=x+y; ?????? System.out.println("result:"+result); ?????? return result; ??? } ??? //C調用java中參數為string的方法 ??? public void printString(String s) { ?????? System.out.println(s); ??? } ??? ??? public static void demo(){ ?????? System.out.println("哈哈哈,我是靜態方法"); ??? } ??? ??? public native void callMethod1(); ??? public native void callMethod2(); ??? public native void callMethod3(); ??? public native void callMethod4(); ??? public native void callMethod5(); } |
4 通過DataProvider獲得頭文件
接著帶有header的結構如下:
5 編寫MainActivity代碼:
| package com.example.ndkcallback; ? import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.View; ? public class MainActivity extends ActionBarActivity { ? ???????? DataProvider dp; ???????? ???????? static { ?????????????????? System.loadLibrary("hello"); ???????? } ???????? ???????? public void helloFromJava() { ?????????????????? System.out.print("哈哈哈,我被調用了"); ???????? } ???????? ???????? @Override ???????? protected void onCreate(Bundle savedInstanceState) { ?????????????????? super.onCreate(savedInstanceState); ?????????????????? setContentView(R.layout.activity_main); ?????????????????? dp = new DataProvider(); ???????? } ???????? ???????? public void click1(View view){ ?????????????????? dp.callMethod1();??? ???????? } ???????? ???????? public void click2(View view){ ?????????????????? dp.callMethod2(); ???????? } ???????? ???????? public void click3(View view){ ?????????????????? dp.callMethod3(); ???????? } ???????? ???????? public void click4(View view){ ?????????????????? dp.callMethod4(); ???????? } ???????? ???????? public void click5(View view){ ?????????????????? dp.callMethod5(); ???????? } } |
6 編寫布局文件activity_main.xml:
| <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" ??? tools:context=".MainActivity" > ? ??? <Button ??????? android:onClick="click1" ??????? android:id="@+id/button1" ??????? android:layout_width="wrap_content" ??????? android:layout_height="wrap_content" ??????? android:layout_alignParentLeft="true" ??????? android:layout_alignParentTop="true" ??????? android:text="回調java中helloFromJava" /> ? ??? <Button ???????? android:onClick="click2" ??????? android:id="@+id/button2" ??????? android:layout_width="wrap_content" ??????? android:layout_height="wrap_content" ??????? android:layout_alignParentLeft="true" ??????? android:layout_below="@+id/button1" ??????? android:text="回調java中Add" /> ? ??? <Button ??????? android:onClick="click3" ??????? android:id="@+id/button3" ??????? android:layout_width="wrap_content" ??????? android:layout_height="wrap_content" ??????? android:layout_alignParentLeft="true" ??????? android:layout_below="@+id/button2" ??????? android:text="回調java中PrintString" /> ? ??? <Button ???????? android:onClick="click4" ??????? android:id="@+id/button4" ??????? android:layout_width="wrap_content" ??????? android:layout_height="wrap_content" ??????? android:layout_alignParentLeft="true" ??????? android:layout_below="@+id/button3" ??????? android:text="回調java中其它類的方法" /> ? ??? <Button ??????? android:onClick="click5" ??????? android:id="@+id/button5" ??????? android:layout_width="wrap_content" ??????? android:layout_height="wrap_content" ??????? android:layout_alignParentLeft="true" ??????? android:layout_below="@+id/button4" ??????? android:text="回調java中靜態的方法" /> ? </RelativeLayout> |
7 接下來,通過javap命令獲得DataProvider的方法簽名,在cygwin上進入/NdkCallBack/bin/classes.
命令如下:
toto@toto-PC /cygdrive/e/workspace/Android/NdkCallBack/bin/classes
$ javap -scom.example.ndkcallback.DataProvider
上面紅框圈的分別是執行命令和方法簽名。這個簽名在hello.c中會用到。
7 接下來編寫hello.c
| #include "com_example_ndkcallback_DataProvider.h" ? /** ?* 調用:DataProvider中的 public void helloFromJava(); ?*/ JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod1 ? (JNIEnv *env, jobject jobject) { ??? /** ???? * Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider"); ???? * Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{}); ???? * declaredMethod.invoke(forName.newInstance(), new Object[]{}); ???? */ ???????? //jclass????? (*FindClass)(JNIEnv*, const char*); ??? jclass clazz = (*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); ??? //jmethodID (*GetMethodID)(JNIEnv*,jclass,const char*,const char*) ??? //方法簽名?? 參數和返回值 ??? //GetMethodID中參數分別是env指針,class,方法名,方法簽名 ??? jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V"); ??? //通過 void??????? (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);來調用Java的代碼 ??? (*env)->CallVoidMethod(env,jobject,methodId); } ? /** ?* 調用:DataProvider中的 public int Add(int, int); ?*/ JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod2 ? (JNIEnv *env, jobject jobject) { ???????? jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); ???????? //這里的方法簽名中有幾個I表示有幾個參數 ???????? jmethodID methodId=(*env)->GetMethodID(env,clazz,"Add","(II)I"); ???????? // jint??????? (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); ???????? (*env)->CallIntMethod(env,jobject,methodId,3,5); } ? /** ?* 調用:DataProvider中的 public void printString(java.lang.String); ?*/ JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod3 ? (JNIEnv *env, jobject jobject) { // 參數 object? 就是native方法所在的類 ???????? jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); ???????? jmethodID methodId=(*env)->GetMethodID(env,clazz,"printString","(Ljava/lang/String;)V"); ???????? // jint??????? (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); ???????? jstring str=(*env)->NewStringUTF(env,"hello"); ? ???????? (*env)->CallVoidMethod(env,jobject,methodId,str); } ? JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod4 ? (JNIEnv * env, jobject j){ ???????? jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/MainActivity"); ???????? //? jmethodID?? (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); ???????? // 方法簽名? 參數和返回值 ???????? jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V"); ???????? // void??????? (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); ???????? // 需要創建DataProvider的 對象 ???????? // jobject???? (*AllocObject)(JNIEnv*, jclass); ???????? jobject obj=(*env)->AllocObject(env,clazz);? // new MainActivity(); ???????? (*env)->CallVoidMethod(env,obj,methodId); ? } ? JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod5 ? (JNIEnv * env, jobject j){ ???????? jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); ???????? //???? jmethodID?? (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*); ???????? ?jmethodID? methodid=(*env)->GetStaticMethodID(env,clazz,"demo","()V"); ???????? //void??????? (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); ???????? ?(*env)->CallStaticVoidMethod(env,clazz,methodid); } |
8 編寫Android.mk文件,內容如下:
| LOCAL_PATH := $(call my-dir) ? include $(CLEAR_VARS) ? LOCAL_MODULE??? := libhello LOCAL_SRC_FILES := Hello.c ? include $(BUILD_SHARED_LIBRARY) |
9 編寫Android的清單文件,內容如下:
| <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" ??? package="com.example.ndkcallback" ??? android:versionCode="1" ??? android:versionName="1.0" > ? ??? <uses-sdk ??????? android:minSdkVersion="8" ??????? android:targetSdkVersion="19" /> ? ??? <application ??????? android:allowBackup="true" ??????? android:icon="@drawable/ic_launcher" ??????? android:label="@string/app_name" ??????? android:theme="@style/AppTheme" > ??????? <activity ??????????? android:name="com.example.ndkcallback.MainActivity" ??????????? android:label="@string/app_name" > ??????????? <intent-filter> ??????????????? <action android:name="android.intent.action.MAIN" /> ? ??????????????? <category android:name="android.intent.category.LAUNCHER" /> ??????????? </intent-filter> ??????? </activity> ??? </application> ? </manifest> |
10 交叉編譯,生成.so文件
成功之后,查看Android控制臺打印的結果
?
?
總結
以上是生活随笔為你收集整理的03_Android NDK中C语言调用Java代码,javah的使用,javap的使用以及生成签名,Android.mk的编写,C代码的编写的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 葫芦掉地是挡灾了吗,没摔坏?
- 下一篇: 袁记肉夹馍怎么样 品尝袁记肉夹馍的口感和