Java调用本地接口jni与C通信----------------JNI

参照链接:http://blog.csdn.net/drean725/article/details/1599116

·1.首先要把环境配置好:

需要安装: 在window下需要Linux环境cygwin ,安装Develp的install;

在cygwin.bat增加NDK的路径set ndk=D:\android-ndk-r6-windows;

etc目录下文件profile修改:PATH="/usr/local/bin:/usr/bin:/cygdrive/d/android-ndk-r6-windows:${PATH}"

系统环境变量classpath:.;D:\Genuitec\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\lib Java环境配了就OK。

2.在NDK下测试

make-v命令

ndk-build命令 构建c所需的库

ndk-build clean清除

3.Android.mk文件介绍:

Android.mk 的含义

LOCAL_PATH:=$(call my-dir)

LOCAL_PATH是定义源文件在哪个目录用的.

my-dir 是个定义的宏方法, $(call my-dir)就是调用这个叫 my-dir的宏方法,这个方法返回值就是

Android.mk文件所在的目录

include $(CLEAR_VARS)

CLEAR_BARS 变量是build system里面的一个变量

这个变量指向了所有的类似 LOCAL_XXX的变量,

执行完这一句话, 这个编译系统就把 所有的类似

LOCAL_MODULE,LOCAL_SRC_FILES,LOCAL_STATIC_LIBRARIES,...这样的变量都清除掉

但是不会清除掉 LOCAL_PATH

LOCAL_MODULE 就是你要生成的库的名字,这个名字要是唯一的.不能有空格.

编译后系统会自动在前面加上lib的头, 比如说我们的Hello 就编译成了libHello.so

还有个特点就是如果你起名叫libHello 编译后ndk就不会给你的module名字前加上lib了

但是你最后调用的时候 还是调用Hello这个库

LOCAL_SRC_FILES = :Hello.c

这个是指定你要编译哪些文件

不需要指定头文件 ,引用哪些依赖, 因为编译器会自动找到这些依赖 自动编译

include $(BUILD_SHARED_LIBRARY)

.so

编译后生成的库的类型,如果是静态库.a 配置include $(BUILD_STATIC_LIBRARY)

别的参数

LOCAL_CPP_EXTENSION := cc //指定c++文件的扩展名

LOCAL_MODULE := ndkfoo

LOCAL_SRC_FILES := ndkfoo.cc

LOCAL_LDLIBS += -llog -lvmsagent -lmpnet -lmpxml -lH264Android

//指定需要加载一些别的什么库.

java传递数据给c语言处理完后回来:

4.演示1:

1.建好Android项目:

activity文件:

public class MyNDK1Activity extends Activity {
   static{
	   System.loadLibrary("Hello");
   }
	public native String helloFromJNI();   //本地方法
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.i("ndkInfo",helloFromJNI());
        Toast.makeText(this, helloFromJNI(), 1).show();
    }
}

2.新建jni目录
建好Android.mk文件

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE    := libHello
LOCAL_SRC_FILES := Hello.c
 
include $(BUILD_SHARED_LIBRARY)


3.利用cmd中java的javah命令(只是方便,不用就自己写了):

在项目下javah com.wangs.ndk.MyNDK1Activity 生成.h的头文件;此文件在bin目录下,可以复制过来

里面就是c所需要的方法,新建c文件 ,把.h里的方法拿过来再改

4.jdi目录下的.Hello.c文件

#include <string.h>
#include <jni.h>

jstring Java_com_wangs_ndk_MyNDK1Activity_helloFromJNI(JNIEnv *env, jobject javaThis) {

  return (*env)->NewStringUTF(env, "Hello from native code!");

}


5.在cygwin下,进入jni目录下,直行ndk-build命令生成库文件libs和obj文件夹

6.OK搞定,启动Android试试

5.演示:应用3个方法

1.新建android项目

类:DataProvider.java

/**
 * 提供给C的本地方法
 * @author andyu
 *
 */
public class DataProvider {
	public native int add(int x,int y);  //C调用java的方法
	public native String sayHelloInc(String s);
	public native int[] intMethod(int[] inum);
}


Activity类

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
/**
 *  传递数据给c
 * @author andyu
 *
 */
public class MyNDK3Activity extends Activity {
   static{
	   System.loadLibrary("Hello");
   }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        DataProvider dp = new DataProvider();
        int result = dp.add(3, 5);
        String str = dp.sayHelloInc("android java say ");
        int a[]={1,2,3,4,56};
        dp.intMethod(a);
        
        Log.i("nfkInfoJava",result+"");
        Log.i("nfkInfoJava",str);
        Log.i("nfkInfoJava","数据a长度:"+a.length);
        for(int b :a){
        	 Log.i("nfkInfoJava",b+"");
        }
        
    }
}
 

2.新建目录JNI :Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE    := Hello
LOCAL_SRC_FILES := Hello.c
#this is debug logcat 
LOCAL_LDLIBS += -llog   


include $(BUILD_SHARED_LIBRARY)

3.编译native方法所在的类,

javah的头文件:javah com.wangs.ndk.DataProvider

改编成Hello.c文件

#include <string.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "ndkInfo"  //声明logcat的标签
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
//宏定义,使用java中的LogCat

//工具类方法:把java的String to c的String char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr) {  char*   rtn   =   NULL;  //1、获取一个类对象  jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");  //2、构造一个String对象,内容为"GB2312",作为CallObjectMethod方法中的编码字符串  jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");  //3、获取对象或者接口实例的方法ID  jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B");  //4、调用Call<type>Method来invoke方法getBytes(String charsetName),获取jbyteArray对象  jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);  //5、返回jbyteArray对象的元素数量  jsize   alen   =   (*env)->GetArrayLength(env,barr);  //6、返回一个jbyte指针对象  jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);  if(alen   >   0)  {   rtn   =   (char*)malloc(alen+1);         //new   char[alen+1];   memcpy(rtn,ba,alen);   rtn[alen]=0;  }  (*env)->ReleaseByteArrayElements(env,barr,ba,0);

 return rtn; }

JNIEXPORT jint JNICALL Java_com_wangs_ndk_DataProvider_add (JNIEnv *env, jobject jobject, jint x, jint y){ LOGI("this value from c..%ld",x+y); return x+y; } JNIEXPORT jstring JNICALL Java_com_wangs_ndk_DataProvider_sayHelloInc (JNIEnv * env, jobject obj, jstring s){ char* a = "hello"; char* rtn = NULL; rtn = Jstring2CStr(env,s); //char *mystr="Hello from native code!"; LOGI("string %s",rtn); LOGI("END"); return (*env)->NewStringUTF(env, strcat(rtn,a)); //strcat方法把java传过来的连接到一起返回 } JNIEXPORT jintArray JNICALL Java_com_wangs_ndk_DataProvider_intMethod (JNIEnv * env, jobject obj, jintArray arr){ int len= (*env)->GetArrayLength(env,arr); LOGI("LEN=%d\n",len); jint * elems=(*env)->GetIntArrayElements(env,arr,NULL); jint temp=0; int i=0; for (;i<len;i++) { temp=elems[i]+10; //原来值加上10后返回 (*env)->SetIntArrayRegion(env,arr,i,1,&temp); } return arr; }


4.cgywin到jni目录下执行的ndk-build命令,生成库;刷新项目

5.OK了。android application试试


C调用java的方法:

1.提供给C的方法类

*
 */
public class DataProvider {
	public native void callCCode();   //用来调c代码,后写程序实例化DataProvider,在C中调用java方法
	public void hellofromjava(){
		System.out.println("hello from java");
	}
	public int add(int x,int y){
		int result = x + y;
		System.out.println("xy相加的结果:"+result);
		return result;
	}
	public void printString(String s){
		System.out.println("c call print :"+ s);
	}
}


2.Activity类

/**
 *  传递数据给c
 * @author andyu
 *
 */
public class MyNDK4Activity extends Activity {
   static{
	   System.loadLibrary("Hello");
   }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DataProvider dp = new DataProvider();
        dp.callCCode();
    }
}


3.javah命令对本地方法生成头文件提供方法给.C文件

#include <string.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "ndkInfo"  //声明logcat的标签
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
//宏定义,使用java中的LogCat

//java命令 javap -s com.wangs.ndk.DataProvider 打印方法签名
JNIEXPORT void JNICALL Java_com_wangs_ndk_DataProvider_callCCode
  (JNIEnv * env, jobject obj){
    char* className="com/wangs/ndk/DataProvider"; //声明的类的全路径
    jclass clazz;
    clazz = (*env)->FindClass(env,className);
	LOGI("HELLO..start");
	if (clazz == 0) {
		LOGI("not find class!");
	} else
		LOGI("find class");
	jmethodID java_method = (*env)->GetMethodID(env,clazz,
			"hellofromjava", "()V");

	jmethodID java_method2 = (*env)->GetMethodID(env,clazz,
			"add", "(II)I");
	jmethodID java_method3 = (*env)->GetMethodID(env,clazz,
			"printString", "(Ljava/lang/String;)V");

	if (java_method == 0) {
		LOGI("not find java method!----~");
	} else
		LOGI("FIND JAVA METHOD");
	LOGI("call JAVA METHOD");
	//char * cs= "haha";
	//(*env)->CallVoidMethod(env,obj, java_method,(*env)->NewStringUTF(env,cs));
	(*env)->CallVoidMethod(env,obj, java_method);  //方法在jni.h里定义
	(*env)->CallIntMethod(env,obj, java_method2,4,5);  //方法在jni.h里定义
	(*env)->CallObjectMethod(env,obj, java_method3,"ic haha");  //方法在jni.h里定义
	LOGI("call java");
}


4.Android.mk文件

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE    := Hello
LOCAL_SRC_FILES := Hello.c
#this is debug logcat 
LOCAL_LDLIBS += -llog   


include $(BUILD_SHARED_LIBRARY)


5.ndk-编译。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值