android NDK--C 調用java

在java 端定義三個方法供C語言調用,當點擊三個方法對應的button的時候,C代碼會調用相應的java 方法。

創建工程,同時在該包下創建一個用於存放C代碼調用方法的類DataProvider,DataProvider的代碼如下:

package com.example.calljava;

public class DataProvider {
    static{
        System.loadLibrary("CAllJava");
    }
    public native void callPrintString();
    public native int callAdd();
    public native void callFromJava();

    //c 調用java空方法
    public void printString(String s){
        System.out.println("java"+s);
    }

    public int add(int x,int y){
        System.out.println("java"+(x+y));
        return x+y;
    }

    public void fromJava(){
        System.out.println("hello from java");
    }

}

使用javah 工具生成本地方法的方法簽名 .h頭文件

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_calljava_DataProvider */

#ifndef _Included_com_example_calljava_DataProvider
#define _Included_com_example_calljava_DataProvider
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_calljava_DataProvider
 * Method:    callPrintString
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_calljava_DataProvider_callPrintString
  (JNIEnv *, jobject);

/*
 * Class:     com_example_calljava_DataProvider
 * Method:    callAdd
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_calljava_DataProvider_callAdd
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     com_example_calljava_DataProvider
 * Method:    callFromJava
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_calljava_DataProvider_callFromJava
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

在jni目錄下,根據頭文件實現C代碼

#include<stdio.h>
#include<stdlib.h>
#include <jni.h>
#include "com_example_calljava_DataProvider.h"
#include<android/log.h>
#include<malloc.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__)



JNIEXPORT void JNICALL Java_com_example_calljava_DataProvider_callFromJava
  (JNIEnv *env, jobject obj){
    //接收到要調用的java端方法所在的全名
    char* classname="com/example/calljava/DataProvider";
    //通過包名尋找java中的class
    jclass clas;
    clas=(*env)->FindClass(env,classname);
    if(clas==0){
        LOGI("cann't find clas");
    }else{
        LOGI("find cals");
    }

    //通過方法簽名找到對應的方法
    jmethodID jmethod=(*env)->GetMethodID(env,clas,"fromJava","()V");
    if(jmethod==0){
        LOGI("cann't find jmethod");
    }else{
        LOGI("find jmethod");
    }
    //調用虛擬機中的方法
    (*env)->CallVoidMethod(env,obj,jmethod);
}


JNIEXPORT void JNICALL Java_com_example_calljava_DataProvider_callPrintString
  (JNIEnv *env, jobject obj){
    char* classname="com/example/calljava/DataProvider";
    jclass clas;
    clas=(*env)->FindClass(env,classname);
    if(clas==0){
        LOGI("clas cann't find");
    }else{
        LOGI(" find clas");
    }

    jmethodID jmethod=(*env)->GetMethodID(env,clas,"printString","(Ljava/lang/String;)V");
    if(jmethod==0){
        LOGI("cann't find jmethod");
    }else{
        LOGI("find jmethod");
    }
    (*env)->CallVoidMethod(env,obj,jmethod,(*env)->NewStringUTF(env,"haha from c"));
}

JNIEXPORT jint JNICALL Java_com_example_calljava_DataProvider_callAdd
  (JNIEnv *env, jobject obj, jint x, jint y){
    char* classname="com/example/calljava/DataProvider";
    jclass clas;
    clas=(*env)->FindClass(env,classname);
    if(clas==0){
        LOGI("cann't find clas");
    }else{
        LOGI("find clas");
    }

    jmethodID jmethod=(*env)->GetMethodID(env,clas,"add","(II)I");
     if(jmethod==0){
         LOGI("cann't find jmethod");
     }else{
         LOGI("find jmethod");
     }

     jint result=(*env)->CallIntMethod(env,obj,jmethod,2,4);
     LOGI("c code=%d",result);
}

NDK 編譯生成動態庫

java代碼load動態庫,調用native 方法
MainActivity 中調用native 方法

package com.example.calljava;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public void click(View view){
        DataProvider provider=new DataProvider();
        provider.callFromJava();
    }

    public void click2(View view){
        DataProvider provider=new DataProvider();
        provider.callAdd();
    }

    public void click3(View view){
        DataProvider provider=new DataProvider();
        provider.callPrintString();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章