参照链接:http://blog.youkuaiyun.com/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-编译。