参照链接: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-编译。