Android中使用JNI七個步驟:java
1.建立一個android工程android
2.JAVA代碼中寫聲明native 方法 public native String helloFromJNI();數組
3.用javah工具生成頭文件app
4. 建立jni目錄,引入頭文件,根據頭文件實現c代碼ide
5.編寫Android.mk文件函數
6.Ndk編譯生成動態庫工具
7.Java代碼load 動態庫.調用native代碼this
Java調用C進行數據傳遞spa
這裏分別傳遞整形、字符串、數組在C中進行處理。.net
聲明native 方法:
- public class DataProvider {
-
- public native int add(int x ,int y);
-
-
- public native String sayHelloInC(String s);
-
-
-
- public native int[] intMethod(int[] iNum);
- }
下面是生成的頭文件,參數: JENEnv* 表明的是java環境 , 經過這個環境能夠調用java的方法,jobject 表示哪一個對象調用了 這個c語言的方法, thiz就表示的是當前的對象
- #include <jni.h>
-
- #ifndef _Included_cn_itcast_ndk3_DataProvider
- #define _Included_cn_itcast_ndk3_DataProvider
- #ifdef __cplusplus
- extern "C" {
- #endif
- JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add
- (JNIEnv *, jobject, jint, jint);
-
- JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC
- (JNIEnv *, jobject, jstring);
-
- JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod
- (JNIEnv *, jobject, jintArray);
-
- #ifdef __cplusplus
- }
- #endif
- #endif
C代碼出了要引用頭文件外,還要引入日誌信息,以方便在C 中進行調試
- #include "cn_itcast_ndk3_DataProvider.h"
- #include <string.h>
- #include <android/log.h>
- #define LOG_TAG "logfromc"
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-
- char* Jstring2CStr(JNIEnv* env, jstring jstr)
- {
- char* rtn = NULL;
- jclass clsstring = (*env)->FindClass(env,"java/lang/String");
- jstring strencode = (*env)->NewStringUTF(env,"GB2312");
- jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");
- jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);
- jsize alen = (*env)->GetArrayLength(env,barr);
- jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
- if(alen > 0)
- {
- rtn = (char*)malloc(alen+1);
- memcpy(rtn,ba,alen);
- rtn[alen]=0;
- }
- (*env)->ReleaseByteArrayElements(env,barr,ba,0);
-
- return rtn;
- }
-
- JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add
- (JNIEnv * env, jobject obj, jint x, jint y){
-
- LOGI("log from c code ");
- LOGI("x= %ld",x);
- LOGD("y= %ld",y);
- return x+y;
- }
-
- JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC
- (JNIEnv * env, jobject obj, jstring str){
-
- char* p = Jstring2CStr(env,str);
- LOGI("%s",p);
- char* newstr = "append string";
-
-
- LOGI("END");
- return (*env)->NewStringUTF(env, strcat(p,newstr));
- }
-
- JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod
- (JNIEnv * env, jobject obj, jintArray arr){
-
-
- int len = (*env)->GetArrayLength(env, arr);
- LOGI("len=%d", len);
-
- if(len==0){
- return arr;
- }
-
- jint* p = (*env)-> GetIntArrayElements(env,arr,0);
- int i=0;
- for(;i<len;i++){
- LOGI("len=%ld", *(p+i));
- *(p+i) += 5;
- }
- return arr;
- }
編寫Android.mk文件
- LOCAL_PATH := $(call my-dir)
-
- include $(CLEAR_VARS)
-
- LOCAL_MODULE := Hello
- LOCAL_SRC_FILES := Hello.c
- #增長 log 函數對應的log 庫 liblog.so libthread_db.a
- LOCAL_LDLIBS += -llog
-
- include $(BUILD_SHARED_LIBRARY)
Java代碼load 動態庫.調用native代碼
- static{
- System.loadLibrary("Hello");
- }
- DataProvider dp;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- dp = new DataProvider();
- }
-
-
- public void add(View view){
-
- int result = dp.add(3, 5);
- Toast.makeText(this, "相加的結果"+ result, 1).show();
- }
C中回調java方法
聲明native 方法:
- public class DataProvider{
- public native void callCcode();
- public native void callCcode1();
- public native void callCcode2();
-
-
- public void helloFromJava(){
- System.out.println("hello from java ");
- }
-
- public int Add(int x,int y){
- System.out.println("相加的結果爲"+ (x+y));
- return x+y;
- }
-
- public void printString(String s){
- System.out.println("in java code "+ s);
- }
- }
頭文件能夠用jdk自帶的javah進行自動生成,使用javap -s能夠獲取到方法的簽名。
C代碼實現回調須要三個步驟:首先要要獲取到 某個對象 , 而後獲取對象裏面的方法 ,最後 調用這個方法 .
- #include "cn_itcast_ndk4_DataProvider.h"
- #include <string.h>
- #include <android/log.h>
- #define LOG_TAG "logfromc"
- #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
- #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
-
- JNIEXPORT void JNICALL Java_cn_itcast_ndk4_DataProvider_callCcode
- (JNIEnv * env , jobject obj){
-
- char* classname = "cn/itcast/ndk4/DataProvider";
- jclass dpclazz = (*env)->FindClass(env,classname);
- if (dpclazz == 0) {
- LOGI("not find class!");
- } else
- LOGI("find class");
-
-
- jmethodID methodID = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
- if (methodID == 0) {
- LOGI("not find method!");
- } else
- LOGI("find method");
-
- (*env)->CallVoidMethod(env, obj,methodID);
- }
-
- JNIEXPORT void JNICALL Java_cn_itcast_ndk4_DataProvider_callCcode1
- (JNIEnv * env, jobject obj){
- LOGI("in code");
-
- char* classname = "cn/itcast/ndk4/DataProvider";
- jclass dpclazz = (*env)->FindClass(env,classname);
- if (dpclazz == 0) {
- LOGI("not find class!");
- } else
- LOGI("find class");
-
- jmethodID methodID = (*env)->GetMethodID(env,dpclazz,"printString","(Ljava/lang/String;)V");
- if (methodID == 0) {
- LOGI("not find method!");
- } else
- LOGI("find method");
-
-
- (*env)->CallVoidMethod(env, obj,methodID,(*env)->NewStringUTF(env,"haha"));
- }
-
- JNIEXPORT void JNICALL Java_cn_itcast_ndk4_DataProvider_callCcode2
- (JNIEnv * env, jobject obj){
- char* classname = "cn/itcast/ndk4/DataProvider";
- jclass dpclazz = (*env)->FindClass(env,classname);
- jmethodID methodID = (*env)->GetMethodID(env,dpclazz,"Add","(II)I");
- (*env)->CallIntMethod(env, obj,methodID,3l,4l);
- }