1 package com.test.androidjni; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.widget.TextView; 7 8 9 public class MainActivity extends Activity { 10 private static final String DEBUGTAG = "NATIVE"; 11 private String myString; 12 private static int si=0; 13 private static String helloString = "What's your name"; 14 15 //對基本數據類型的訪問 16 private native String GetNativeString(String str);//訪問字串 17 private native int SumArray(int [] ar, int length);//傳一個數組的長度 18 private native int SumArrayA(int [] ar);//不傳長度 19 private native int SumArray2D(int [][]ar2d);//傳一個二維數組,返回一個長度 20 private native int [][] ModifyArray2d(int [][]ar2d);//傳入一個二維數組,返回一個二維數組 21 22 //這一部分是對成員和方法的訪問 23 private native void AccessField();//訪問靜態成員 24 private native void AccessMethod(); 25 26 private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh); 27 28 /** 29 * 對於加動.so庫作一點說明 30 * System.loadLibrary 這個方法默認去system/lib去找這個.so庫, 31 * 再到data/data/com.test.androidjin/lib/目錄下找。本應數據存放的目錄下 32 * 咱們能夠經過eclipse上的ddms去查看。前提是把調試的機器聯上, 33 * 動態庫的名稱是:lib前綴+庫名+.so後綴。此函數不要前綴,也不要後綴,只要包名,不然找不到 34 * 可是咱們在這個apk的libs/armeabi/目錄下要用libmyjni.so這個全名. 35 * 另外還有一個加載庫的函數 36 * System.load 這個函數是傳入全路徑名.這樣就能夠到指定的路徑加載了 37 * System.load(/system/lib/libXXX.so);注意訪問目錄的權限問題 ,這個與linux的目錄訪問權限同樣的. 38 * 有時候咱們在使用第三訪.so庫是,找不到庫,但明明庫已加打包進了。這裏咱們要看它的本地方法是在 39 * 那個java包下的那個類中聲明的,好比這個apk的native方法是在 40 * com.test.androidjni包的MainActivity 這個類中聲明的。生成的native函數都有 41 * Java_com_test_androidjni_MainActivity_這個前綴.咱們能夠根據第三訪.so的函數接口的前綴 42 * 創建相應的包和類名,而後就能夠正確加載了。這裏與前面講的找庫的路徑是恰好相互應證了。 43 * 44 */ 45 static{ 46 System.loadLibrary("myjni"); 47 } 48 49 @Override 50 protected void onCreate(Bundle savedInstanceState) { 51 super.onCreate(savedInstanceState); 52 setContentView(R.layout.activity_main); 53 //字符串操做 54 String retStr = GetNativeString("Please give me A String"); 55 Log.d(DEBUGTAG, retStr); 56 if(null != retStr){ 57 TextView t = (TextView)findViewById(R.id.nativeString); 58 t.setText(retStr); 59 } 60 61 //傳入一維數組,累計和,並修改了第0,第1個數組元素的值 62 int arr[] =new int[]{1,2,3,4,5,6,7}; 63 Integer value = SumArrayA(arr); 64 TextView t = (TextView)findViewById(R.id.nativeArray); 65 t.setText(value.toString()); 66 Log.d(DEBUGTAG, "arr[0] = "+ arr[0]+" arr[1]"+arr[1]); 67 68 //訪問二維數組,累計和, 69 int arr2d[][] = {{1,1,5,5},{2,2,2,2,}};//new int[2][4]; 70 int sum = SumArray2D(arr2d); 71 Log.d(DEBUGTAG, "len = " + sum); 72 73 //訪問二維數組,並返回一個二維數組,且修改了傳入二維數組的元素 74 int arr2dA[][] = null; 75 int sumV = 0; 76 arr2dA = ModifyArray2d(arr2d); 77 for(int i=0;i<2;i++) 78 { 79 for(int j=0;j<4;j++) 80 { 81 sumV += arr2dA[i][j]; 82 } 83 } 84 Log.d(DEBUGTAG, "sumV = " + sumV); 85 86 87 //c中訪問java域和方法 88 this.myString = "Android Java String"; 89 this.AccessField(); 90 Log.d(DEBUGTAG, "after modify by native myString = " + myString); 91 Log.d(DEBUGTAG, "after modify by native si = " + si); 92 Log.d(DEBUGTAG, "after modify by native helloString = " + helloString); 93 //c中調用java中的方法 94 this.AccessMethod(); 95 } 96 private void callback(String strFromNative,int i,byte b,char c,boolean bl,long l,double d,float f,short sh){ 97 Log.d(DEBUGTAG,"CALL FROM NATIVE:"+strFromNative +i+b+c+bl+l+d+f+sh); 98 } 99 private static String callStaticBack(){ 100 return "What's your name "; 101 } 102 103 }
1 #include <string.h> 2 #include <jni.h> 3 #include "com_test_androidjni_MainActivity.h" 4 /* 5 * @學習使用jni字串函數 JNIEnv 是一個結構體,下面列出的是這個結構體的部分函數指針,還有不少其餘的 6 * 7 * unicode16編碼,字串符沒有結束符'\0', 8 * jstring (*NewString)(JNIEnv*, const jchar*, jsize);//最後一個參數表示jchar* 內存長度 9 * jsize (*GetStringLength)(JNIEnv*, jstring); 10 * const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*); 11 * void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*); 12 * void (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*); 13 * 14 * utf8編碼,獲得的字串是有結束符'\0'的 15 * jstring (*NewStringUTF)(JNIEnv*, const char*); 16 * jsize (*GetStringUTFLength)(JNIEnv*, jstring); 17 * const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*); 18 * void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*); 19 * void (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*); 20 * 21 * 獲取直接指向jstring的地址,所以沒有編碼區別。這一對函數中,不能有阻塞操做 22 * 這對函數之間,不能有任何對jni的操做,所以這對函數,通常較少用。 23 * const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*); 24 * void (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*); 25 * 26 */ 27 jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString( 28 JNIEnv *env, jobject obj, jstring str) { 29 const char * pStr; 30 const char* pUTF8Str = "From jni String"; 31 char outbuff[128] = { 0 }; 32 33 //獲取傳入字串中的全部字串 34 pStr = (*env)->GetStringUTFChars(env, str, NULL); 35 if (pStr == NULL) 36 return NULL; 37 strcat(outbuff, pStr); 38 (*env)->ReleaseStringUTFChars(env, str, pStr); //這裏要釋放,不然內存泄漏 39 strcat(outbuff, "/"); //加一個分隔符 40 //從傳入字串第三個位置開始,獲取4個,到字串尾 41 (*env)->GetStringUTFRegion(env, str, 3, 4, outbuff + strlen(outbuff)); 42 strcat(outbuff, "/"); //加一個分隔符 43 strcat(outbuff, pUTF8Str); //聯接一個本地字串 44 //從buff中構建一個jstring返回給java,這個新構建的字串由虛擬機負責回收 45 return (*env)->NewStringUTF(env, outbuff); 46 } 47 /** 48 * 訪問基本數組類型 49 jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); 50 jbyteArray (*NewByteArray)(JNIEnv*, jsize); 51 jcharArray (*NewCharArray)(JNIEnv*, jsize); 52 jshortArray (*NewShortArray)(JNIEnv*, jsize); 53 jintArray (*NewIntArray)(JNIEnv*, jsize); 54 jlongArray (*NewLongArray)(JNIEnv*, jsize); 55 jfloatArray (*NewFloatArray)(JNIEnv*, jsize); 56 jdoubleArray (*NewDoubleArray)(JNIEnv*, jsize); 57 58 jboolean* (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); 59 jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); 60 jchar* (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); 61 jshort* (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); 62 jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); 63 jlong* (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); 64 jfloat* (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); 65 jdouble* (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*); 66 67 void (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,jboolean*, jint); 68 void (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray,jbyte*, jint); 69 void (*ReleaseCharArrayElements)(JNIEnv*, jcharArray,jchar*, jint); 70 void (*ReleaseShortArrayElements)(JNIEnv*, jshortArray,jshort*, jint); 71 void (*ReleaseIntArrayElements)(JNIEnv*, jintArray,jint*, jint); 72 void (*ReleaseLongArrayElements)(JNIEnv*, jlongArray,jlong*, jint); 73 void (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,jfloat*, jint); 74 void (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,jdouble*, jint); 75 76 77 void (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, jboolean*); 78 void (*GetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, jbyte*); 79 void (*GetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, jchar*); 80 void (*GetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, jshort*); 81 void (*GetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, jint*); 82 void (*GetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, jlong*); 83 void (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, jfloat*); 84 void (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, jdouble*); 85 86 spec shows these without const; some jni.h do, some don't 87 void (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, const jboolean*); 88 void (*SetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, const jbyte*); 89 void (*SetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, const jchar*); 90 void (*SetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, const jshort*); 91 void (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*); 92 void (*SetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, const jlong*); 93 void (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, const jfloat*); 94 void (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, const jdouble*); 95 * 96 * 97 *這裏能夠求得任意數組大小的,累計合 98 */ 99 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray( 100 JNIEnv *env, jobject obj, jintArray arr, jint length) { 101 int i, sum = 0; 102 jint* pOutbuf = NULL; 103 if (length > 0) 104 pOutbuf = (jint*) malloc(length * sizeof(jint)); 105 else 106 return 0; 107 (*env)->GetIntArrayRegion(env, arr, 0, length, pOutbuf); 108 for (i = 0; i < 10; i++) 109 sum += pOutbuf[i]; 110 free(pOutbuf); 111 pOutbuf = NULL; 112 113 return sum; 114 } 115 /* 116 * 117 * ReleaseIntArrayElements 118 * 第三個參數就是決定更新與否的。 119 * 取值 零(0) 時,更新數組並釋放全部元素; 120 * 取值 JNI_COMMIT 時,更新但不釋放全部元素; 121 * 取值 JNI_ABORT 時,不做更新但釋放全部元素; 122 * #define JNI_COMMIT 1 // copy content, do not free buffer 123 * #define JNI_ABORT 2 // free buffer w/o copying back ^/ 124 * //獲取數組長度,注意jarray是指全部類型j<類型>array 125 * typedef jarray jintArray //其餘的jbyteArray或jfloatArray都是jarray. 126 * jsize (*GetArrayLength)(JNIEnv*, jarray); 127 */ 128 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA( 129 JNIEnv *env, jobject obj, jintArray arr) { 130 int i,j, sum = 0; 131 jint* buf; 132 j = (*env)->GetArrayLength(env,arr); 133 //另外,這裏返回的值,是jint*,不是const jint*,也就是說能夠對其中的值進行修改 134 buf = (*env)->GetIntArrayElements(env, arr, NULL);//這一句其實也告java內存回收器,不要回收arr數組的內存,或者不要整理內存 135 //若是回收器,回收和整理內存,那麼咱們在c中,訪問的地址就可能錯了 136 for (i = 0; i < j; i++)//這裏是求合 137 sum += buf[i]; 138 //如今咱們來修改一下buf中的元素,看看返回後,會不會把buf中的值,更新到java中的arr裏去 139 buf[0] = 100; 140 buf[1] = 200; 141 142 (*env)->ReleaseIntArrayElements(env, arr, buf, 0);//調用這個方法,告訴java內存回收器,我憶用完了arr,,如今能夠回收arr的內存了 143 return sum; 144 } 145 /** 146 * 要點:演示對傳入二維數組的訪問 147 * 功能:計算二維數組的和 148 * NewObjectArray( env,len,jcIntArray,NULL ); 149 * 參數2:是要建立的元數個數 150 * 參數3:是要建立的元素的類型 151 * 參數4:是建立時的初值,能夠傳空 152 */ 153 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D 154 (JNIEnv *env, jobject obj, jobjectArray arr2D) 155 { 156 int len = 0,length = 0; 157 int i,j,sum=0; 158 jarray jaIntArray; 159 jintArray jiaTmpIntArray; 160 jobjectArray joaReturnInt2DArray;//定義一個數組指針,到時候返回用 161 jclass jcIntArray; 162 jboolean jbIsCopy = JNI_FALSE; 163 164 len = (*env)->GetArrayLength( env, arr2D );//獲取第一維的元數長度 165 jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, 0);//獲取第0個元素 ,它是一個一維數組首地址 166 length = (*env)->GetArrayLength( env, jaIntArray );//獲取一維數組的長度 167 168 jcIntArray = (*env)->FindClass( env, "[I" );//獲得一個一維數組的引用 169 joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//建立len個jcIntArray. 170 171 for(i=0;i<len;i++) 172 { 173 jint *piSrc,*piDes; 174 175 jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, i);//void*指針 176 jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指針,元素個數是length 177 178 piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//這裏仍是獲取首地址,獲得的是jin*類型的了 179 piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//這裏仍是獲取首地址,獲得的是jin*類型的了 180 181 for(j=0;j<length;j++) 182 { 183 piDes[j] = piSrc[j];//把傳入數組的值,賦給新建立的數組 184 sum +=piDes[j];//經過新建立數的值。累計 185 } 186 187 (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//對應的釋放函數 188 (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//對應的釋放函數 189 190 (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//將新建的一維數組,作爲二維數組的元素 191 (*env)->DeleteLocalRef( env, jiaTmpIntArray );//刪掉這個引用. 192 } 193 194 (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//釋放整個建立的二維數組 195 196 return sum; 197 } 198 /* 199 * 要點: 200 * 1:訪問傳入的二維數組 201 * 2:建立一個新的二維數組 202 * 3:修改傳入的二維數組的值 203 * 4:返回一個二維數組對象給java調用端 204 */ 205 JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d 206 (JNIEnv *env, jobject obj, jobjectArray arr2D) 207 { 208 int len = 0,length = 0; 209 int i,j,sum=0; 210 jarray jaIntArray; 211 jintArray jiaTmpIntArray; 212 jobjectArray joaReturnInt2DArray;//定義一個數組指針,到時候返回用 213 jclass jcIntArray; 214 jboolean jbIsCopy = JNI_FALSE; 215 216 len = (*env)->GetArrayLength( env, arr2D );//獲取第一維的元數長度 217 jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, 0);//獲取第0個元素 ,它是一個一維數組首地址 218 length = (*env)->GetArrayLength( env, jaIntArray );//獲取一維數組的長度 219 220 jcIntArray = (*env)->FindClass( env, "[I" );//獲得一個一維數組的引用 221 joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//建立len個jcIntArray. 222 223 for(i=0;i<len;i++) 224 { 225 jint *piSrc,*piDes; 226 227 jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, i);//void*指針 228 jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指針,元素個數是length 229 230 piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//這裏仍是獲取首地址,獲得的是jin*類型的了 231 piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//這裏仍是獲取首地址,獲得的是jin*類型的了 232 233 for(j=0;j<length;j++) 234 { 235 piDes[j] = piSrc[j];//把傳入數組的值,賦給新建立的數組 236 sum +=piDes[j];//經過新建立數的值。累計 237 piDes[j] = 5;//修改傳入數組的值 238 } 239 240 (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//對應的釋放函數 241 (*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//對應的釋放函數 242 243 (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//將新建的一維數組,作爲二維數組的元素 244 (*env)->DeleteLocalRef( env, jiaTmpIntArray );//刪掉這個引用. 245 } 246 247 // (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//釋放整個建立的二維數組 248 249 return joaReturnInt2DArray; 250 } 251 /** 252 * 訪問java中的成員[通用的邏輯] 253 * 注意:訪問的是java中非靜態成員,非靜態成員是屬於對象的.另外還要訪問靜態成員,靜態成員屬於類 254 * 步驟: 255 * 1:先找到對象的類 256 * 2:根據成員的名稱和類型,獲取該成員的id引用 257 * 3:根據id引用,獲取該成員的域引用 258 * 4:根據域引用再獲得具體的內容 259 * 260 */ 261 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField 262 (JNIEnv *env, jobject obj) 263 { 264 jclass cls;//void*指針 265 jfieldID fid;//抽象的結構體指針 266 jstring jstr;//void*指針 267 jint value; 268 const char* str; 269 270 cls = (*env)->GetObjectClass(env,obj);//獲得類的引用 271 fid = (*env)->GetFieldID(env, cls, "myString", "Ljava/lang/String;");//獲得成員id的引用 272 if( fid == NULL ){//檢測根據給定的信息是否找到了id, 273 return ; 274 } 275 jstr = (*env)->GetObjectField(env, obj, fid);//獲得對象的引用 276 str = (*env)->GetStringUTFChars(env, jstr, NULL);//從對象引用中獲得內容 277 if( str == NULL ){ 278 return ; 279 } 280 //printf(" c.s = "%s"\n", str ) ; 281 (*env)->ReleaseStringUTFChars(env, jstr, str);//更新或釋放,不過最好用SetObjectField來操做。 282 jstr = (*env)->NewStringUTF(env, "accedfild");//建立一個新的字串,這個是用java的方法建立的 283 if( jstr == NULL ){ 284 return ; 285 } 286 //用jstr,更新obj對象的fid域. 287 (*env)->SetObjectField(env, obj, fid, jstr);//設置域對象 288 289 //===============訪問int靜態成員======================= 290 fid = (*env)->GetStaticFieldID(env,cls,"si","I"); 291 if(NULL == fid) 292 return; 293 value = (*env)->GetStaticIntField(env, cls, fid);//注意第二個參數是類,不是對象,由於是靜態成員 294 value = 100; 295 (*env)->SetStaticIntField(env, cls, fid, 100); 296 //===============訪問String靜態成員======================= 297 fid = (*env)->GetStaticFieldID(env, cls, "helloString", "Ljava/lang/String;"); 298 jstr = (*env)->GetStaticObjectField(env, cls, fid);//注意第二個參數是類,不是對象,由於是靜態成員 299 str = (*env)->GetStringUTFChars(env, jstr, NULL); 300 //能夠對str作一些處理 301 (*env)->ReleaseStringUTFChars(env, jstr, str); 302 jstr = (*env)->NewStringUTF(env, "static string"); 303 (*env)->SetStaticObjectField(env, cls, fid, jstr);//注意第二個參數是類,不是對象,由於是靜態成員 304 305 return; 306 } 307 /* 308 * 訪問java中的方法 309 * 並傳遞了全部java中的數據類型,對象類型除外 310 * 311 * 312 */ 313 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod 314 (JNIEnv *env, jobject obj) 315 { 316 jclass cls; 317 jmethodID mid; 318 const char *str = "hello call back"; 319 jstring jstr; 320 321 jboolean z = 1; 322 jbyte b = 0xff; 323 jchar c = 'c'; 324 jshort s = 60; 325 jint i = 100; 326 jlong j = 568978523; 327 jfloat f = 125643.22222; 328 jdouble d = 123456789.12654789; 329 //jobject l = ; 330 331 cls = (*env)->GetObjectClass(env,obj);//獲得類的引用 332 333 //從靜態方法中獲得str,再傳回給callback方法 334 mid = (*env)->GetStaticMethodID(env, cls,"callStaticBack","()Ljava/lang/String;"); 335 jstr = (*env)->CallStaticObjectMethod(env,cls,mid); 336 337 mid = (*env)->GetMethodID(env, cls, "callback", "(Ljava/lang/String;IBCZJDFS)V"); 338 339 if (mid == NULL) { 340 return; /* method not found */ 341 } 342 //printf("In C\n"); 343 344 //jstr = (*env)->NewStringUTF(env, str); 345 (*env)->CallVoidMethod(env, obj, mid,jstr,i,b,c,z,j,d,f,s); 346 347 }
1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class com_test_androidjni_MainActivity */ 4 5 #ifndef _Included_com_test_androidjni_MainActivity 6 #define _Included_com_test_androidjni_MainActivity 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: com_test_androidjni_MainActivity 12 * Method: GetNativeString 13 * Signature: (Ljava/lang/String;)Ljava/lang/String; 14 */ 15 JNIEXPORT jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString 16 (JNIEnv *, jobject, jstring); 17 18 /* 19 * Class: com_test_androidjni_MainActivity 20 * Method: SumArray 21 * Signature: ([II)I 22 */ 23 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray 24 (JNIEnv *, jobject, jintArray, jint); 25 26 /* 27 * Class: com_test_androidjni_MainActivity 28 * Method: SumArrayA 29 * Signature: ([I)I 30 */ 31 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA 32 (JNIEnv *, jobject, jintArray); 33 34 /* 35 * Class: com_test_androidjni_MainActivity 36 * Method: SumArray2D 37 * Signature: ([[I)I 38 */ 39 JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D 40 (JNIEnv *, jobject, jobjectArray); 41 42 /* 43 * Class: com_test_androidjni_MainActivity 44 * Method: ModifyArray2d 45 * Signature: ([[I)[[I 46 */ 47 JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d 48 (JNIEnv *, jobject, jobjectArray); 49 50 /* 51 * Class: com_test_androidjni_MainActivity 52 * Method: AccessField 53 * Signature: ()V 54 */ 55 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField 56 (JNIEnv *, jobject); 57 58 /* 59 * Class: com_test_androidjni_MainActivity 60 * Method: AccessMethod 61 * Signature: ()V 62 */ 63 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod 64 (JNIEnv *, jobject); 65 66 /* 67 * Class: com_test_androidjni_MainActivity 68 * Method: signature 69 * Signature: (Ljava/lang/String;IBCZJDFS)V 70 */ 71 JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_signature 72 (JNIEnv *, jobject, jstring, jint, jbyte, jchar, jboolean, jlong, jdouble, jfloat, jshort); 73 74 #ifdef __cplusplus 75 } 76 #endif 77 #endif
jni.h 這個頭文件在android-ndk包中的platroms/具體的api包的inlcude中。 java
關於android jni編程,java與c,c++之間數據的傳遞都在jni.h這個頭文件中.根據類型結構,可知爲何不能夠在c中,直接訪問java傳入的jstring或一些其餘類型linux
它們的類如果void*的,那麼就沒法訪問了。由於咱們不知道它在內存的佈局,佔幾個字節,也就沒法訪問。這就是所謂不透明類型。另外對於c++裏面訪問java,實android
際是對c的封裝.c++
咱們注意一下jni.h中編程
#if defined(__cplusplus)//這裏表示是c++用的 typedef _JNIEnv JNIEnv;//這是native方法的第一個參數 typedef _JavaVM JavaVM;//這個是虛擬機 #else typedef const struct JNINativeInterface* JNIEnv; typedef const struct JNIInvokeInterface* JavaVM; #endif struct JNINativeInterface{ //具體內容省略, //它們都是一些函數指針,這個結構體,每一個native方法的第一個參數JNIEnv env 就是它本身 }; 另外注意一下 //這兩個方法,是由java虛擬機調用的,它傳入一個vm,經過vm咱們能夠獲得JNIEnv,經過JNIEnv咱們能夠獲得 //java與c,c++之間的交互接口。 JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved); JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);
上面這些代碼,是對<JNI編程指南> 前4章方法的彙總.也總結了許多網友的代碼,並對其作了一些修改,加入了本身的理解。api
private static final String DEBUGTAG = "NATIVE"; private String myString; private static int si=0; private static String helloString = "What's your name"; //對基本數據類型的訪問 private native String GetNativeString(String str);//訪問字串 private native int SumArray(int [] ar, int length);//傳一個數組的長度 private native int SumArrayA(int [] ar);//不傳長度 private native int SumArray2D(int [][]ar2d);//傳一個二維數組,返回一個長度 private native int [][] ModifyArray2d(int [][]ar2d);//傳入一個二維數組,返回一個二維數組 //這一部分是對成員和方法的訪問 private native void AccessField();//訪問靜態成員 private native void AccessMethod(); //這個方法是爲了生成一個包括全部基本類型的方法簽名,請查看頭文件 private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh);