在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();
}
}