佈局文件:java
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center"> <TextView android:id="@+id/tv_call" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, MyActivity" android:padding="10dp" android:gravity="center" /> <Button android:id="@+id/btn_call" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Call" /> <Button android:id="@+id/btn_send_int" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="傳遞int參數" /> <Button android:id="@+id/btn_send_str" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="傳遞String參數" /> <Button android:id="@+id/btn_ints" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="傳遞int數組" /> </LinearLayout>
Java代碼:android
public class MyActivity extends Activity implements View.OnClickListener { DataProvider mPro; /** * 使用靜態代碼塊加載庫文件 */ static { System.loadLibrary("Hello"); } public native String helloFromJNI (); /** * Called when the activity is first created. */ @Override public void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mPro = new DataProvider(); initView(); } TextView mTvCall; private void initView () { mTvCall = (TextView) findViewById(R.id.tv_call); Button btnCall = (Button) findViewById(R.id.btn_call); Button btnInts = (Button) findViewById(R.id.btn_ints); Button btnInt = (Button) findViewById(R.id.btn_send_int); Button btnStr = (Button) findViewById(R.id.btn_send_str); btnCall.setOnClickListener(this); btnInt.setOnClickListener(this); btnInts.setOnClickListener(this); btnStr.setOnClickListener(this); } @Override public void onClick (View v) { int id = v.getId(); switch (id) { case R.id.btn_call: //調用C\C++中的方法輸出"你好 from C++." mTvCall.setText(helloFromJNI()); Toast.makeText(MyActivity.this, helloFromJNI(), Toast.LENGTH_LONG).show(); break; case R.id.btn_send_int: //向C++代碼中傳遞兩個int型參數 mTvCall.setText(String.valueOf(mPro.add(10, 20))); break; case R.id.btn_send_str: //向C++代碼中傳遞一個String型參數 mTvCall.setText(mPro.sayHello(" JNI")); break; case R.id.btn_ints: //向C++代碼中傳遞int數組 int[] arr = mPro.intMethod(new int[]{30, 40}); StringBuilder sb = new StringBuilder(); for (int i = 0; i < arr.length; i++) { if (i == arr.length - 1) sb.append(arr[i]); else sb.append(arr[i]).append(","); } mTvCall.setText(sb.toString()); break; } } }
在定義native方法時,並不推薦直接定義在Activity中,而是專門創建一個定義native方法的類:ios
*/ public class DataProvider { static{ System.loadLibrary("Hello"); } public native int add(int x,int y); public native String sayHello(String str); public native int[] intMethod(int[] numbers); }
C++代碼的實現:c++
#include <iostream> #include <string> #include <malloc.h> #include <jni.h> #include "com_chen_jni_demo_MyActivity.h" #include "com_chen_jni_demo_DataProvider.h" using namespace std; //導入Log #include <android/log.h> #define LOG_TAG "System.out" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) //jni.h沒有導入的話,編譯時會出現符號錯誤的問題 //使用C++實現輸出 JNIEXPORT jstring JNICALL Java_com_chen_jni_demo_MyActivity_helloFromJNI (JNIEnv * env, jobject obj){ char* cstr = "你好 from C++."; LOGI("DEBUG %s",cstr); return (*env).NewStringUTF(cstr); } //向C++代碼中傳遞一個String型參數 JNIEXPORT jstring JNICALL Java_com_chen_jni_demo_DataProvider_sayHello (JNIEnv * env, jobject obj, jstring jstr){ //聲明要調用的函數 char* jstringTostring(JNIEnv* env, jstring jstr); //將java字符串轉換爲c++中的字符數組 char* str1=jstringTostring(env,jstr); char* str2="你好"; //拼接字符數組 strcat(str1,str2); return (*env).NewStringUTF(str1); } //向C++代碼中傳遞兩個int型參數 JNIEXPORT jint JNICALL Java_com_chen_jni_demo_DataProvider_add (JNIEnv * env, jobject obj, jint x, jint y){ return x+y; } //向C++代碼中傳遞一個int數組 JNIEXPORT jintArray JNICALL Java_com_chen_jni_demo_DataProvider_intMethod (JNIEnv * env,jobject obj, jintArray jintArr){ //得到整型數組的長度 jsize size = (*env).GetArrayLength(jintArr); //jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); //jboolean* 表示得到數據的方式 true-1-複製 false-0-引用 c語言中 jint* arr = (*env).GetIntArrayElements(jintArr,false); for(int i=0;i<size;i++){ //第一種 //*(arr+i) = *(arr+i)+10; //*(arr+i) +=10; /* 第二種 void (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*); 設置IntArray中指定範圍內元素的值 參數3:範圍的起始位置 參數4:範圍的擦海南過分(指定修改的元素的個數) 參數5:const jint* 指定元素的值(地址) */ int temp = *(arr+i)+10; (*env).SetIntArrayRegion(jintArr,i,1,&temp); } //使用的是引用方式,直接返回便可,數據已經改變 return jintArr; } /** *將Java的String轉換爲char* */ jstring stoJstring (JNIEnv*env, const char*pat) { jclass strClass = env -> FindClass("Ljava/lang/String;"); jmethodID ctorID = env -> GetMethodID(strClass, "", "([BLjava/lang/String;)V"); jbyteArray bytes = env -> NewByteArray(strlen(pat)); env -> SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *)pat); jstring encoding = env -> NewStringUTF("utf-8"); return (jstring) env -> NewObject(strClass, ctorID, bytes, encoding); } //invoke function JNIEXPORT jstring JNICALL Java_test_cs_web_SWIFTAlianceCASmfTest_strcal (JNIEnv*env, jclass obj, jstring jstr1, jstring jstr2) { jbyteArray bytes = 0; jthrowable exc; char*pszResult = NULL; char*pszSTR1 = NULL; char*pszSTR2 = NULL; pszSTR1 = jstringTostring(env, jstr1); pszSTR2 = jstringTostring(env, jstr2); int nlen = sizeof(char)*(strlen(pszSTR1) + strlen(pszSTR2)); pszResult = (char*)malloc(nlen); strcpy(pszResult, pszSTR1); strcat(pszResult, pszSTR2); jstring jstrRe = stoJstring(env, pszResult); free(pszSTR1); free(pszSTR2); free(pszResult); return (jstrRe); }