1.安装
1.下载NDK,注意下载的是r4版本
http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip
2.下载完成后解压到某一目录,我的是在
zhangweia@ubuntu:~/android/android-ndk-r4b$pwd
/home/zhangweia/android/android-ndk-r4b
zhangweia@ubuntu:~/android/android-ndk-r4b$echo $HOME
/home/zhangweia
3.配置NDK的环境变量
zhangweia@ubuntu:~/android/android-ndk-r4b$vi ~/.bashrc
在打开的文件末尾添加:
NDK=$HOME/android/android-ndk-r4b/
export NDK
执行下面的命令,保存环境便利,然后查看是否生效:
zhangweia@ubuntu:~/android/android-ndk-r4b$source ~/.bashrc
zhangweia@ubuntu:~/android/android-ndk-r4b$echo $NDK
/home/zhangweia/android/android-ndk-r4b/
4.编译例子。
进入NDK 的例子目录samples/hello-jni,然后在该目录下执行$NDK/ndk-build,编译成功后会在该目录多生成2个子目录libs,obj目录
然后打开eclipse ,添加存在的hello-jni工程 ,运行则
2.HelloNDk
bin/Hello.c
#include <string.h> #include <jni.h> /* This is a trivial JNI example where we use a native method * to return a new VM String. See the corresponding Java source * file located at: * * apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java */ jstring Java_com_su_testjni_HelloJniActivity_stringFromJNI(JNIEnv* env, jobject thiz) { return (*env)->NewStringUTF(env, "Hello from JNI !"); }
/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.su.testjni; import android.app.Activity; import android.widget.TextView; import android.os.Bundle; public class HelloJniActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /* * Create a TextView and set its content. the text is retrieved by * calling a native function. */ TextView tv = new TextView(this); tv.setText(stringFromJNI()); setContentView(tv); } /* * A native method that is implemented by the 'hello-jni' native library, * which is packaged with this application. */ public native String stringFromJNI(); /* * This is another native method declaration that is *not* implemented by * 'hello-jni'. This is simply to show that you can declare as many native * methods in your Java code as you want, their implementation is searched * in the currently loaded native libraries only the first time you call * them. * * Trying to call this function will result in a * java.lang.UnsatisfiedLinkError exception ! */ public native String unimplementedStringFromJNI(); /* * this is used to load the 'hello-jni' library on application startup. The * library has already been unpacked into * /data/data/com.example.hellojni/lib/libhello-jni.so at installation time * by the package manager. */ static { System.loadLibrary("hello-jni"); } }
# Copyright (C) 2009 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni 这里是jni库将来的名字 源码同名就可以 LOCAL_SRC_FILES := hello-jni.c c源码 include $(BUILD_SHARED_LIBRARY)
3.java和c之间 数据交换
android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=Hello
LOCAL_SRC_FILES :=Hello.c
#liblog.so libGLESv2.so
LOCAL_LDLIBS += -llog //添加log
include $(BUILD_SHARED_LIBRARY)
制作头文件:
cd到bin目录然后javah com.test.testndkdata.DataProvider 含有nativte的方法
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class cn_itcast_ndk3_DataProvider */ #ifndef _Included_cn_itcast_ndk3_DataProvider #define _Included_cn_itcast_ndk3_DataProvider #ifdef __cplusplus extern "C" { #endif /* * Class: cn_itcast_ndk3_DataProvider * Method: add * Signature: (II)I */ JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add__II (JNIEnv *, jobject, jint, jint); /* * Class: cn_itcast_ndk3_DataProvider * Method: sub * Signature: (II)I */ JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_sub (JNIEnv *, jclass, jint, jint); /* * Class: cn_itcast_ndk3_DataProvider * Method: add * Signature: (CC)C */ JNIEXPORT jchar JNICALL Java_cn_itcast_ndk3_DataProvider_add__CC (JNIEnv *, jobject, jchar, jchar); /* * Class: cn_itcast_ndk3_DataProvider * Method: sayHelloInC * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC (JNIEnv *, jobject, jstring); /* * Class: cn_itcast_ndk3_DataProvider * Method: intMethod * Signature: ([I)[I */ JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod (JNIEnv *, jobject, jintArray); /* * Class: cn_itcast_ndk3_DataProvider * Method: byteMethod * Signature: ([B)[B */ JNIEXPORT jbyteArray JNICALL Java_cn_itcast_ndk3_DataProvider_byteMethod (JNIEnv *, jobject, jbyteArray); #ifdef __cplusplus } #endif #endif然后是c代码:
#include<stdio.h> #include<jni.h> #include "cn_itcast_ndk3_DataProvider.h"; #include <android/log.h> #include<malloc.h> #define LOG_TAG "System.out.c" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) /** * 返回值 char* 这个代表char数组的首地址 * Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串 */ char* Jstring2CStr(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = (*env)->FindClass(env,"java/lang/String"); //String jstring strencode = (*env)->NewStringUTF(env,"GB2312"); // 得到一个java字符串 "GB2312" jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312"); jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312"); jsize alen = (*env)->GetArrayLength(env,barr); // byte数组的长度 jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE); if(alen > 0) { rtn = (char*)malloc(alen+1); //"\0" memcpy(rtn,ba,alen); rtn[alen]=0; } (*env)->ReleaseByteArrayElements(env,barr,ba,0); // return rtn; } JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_add (JNIEnv * env, jobject obj , jint x, jint y){ LOGD("x=%d",x); LOGD("y=%d",y); return x+y; } JNIEXPORT jstring JNICALL Java_cn_itcast_ndk3_DataProvider_sayHelloInC (JNIEnv * env, jobject obj, jstring jstr ){ //在c语言中 是没有java的String char* cstr = Jstring2CStr(env, jstr); LOGD("cstr=%s",cstr); // c语言中的字符串 都是以'/0' 作为结尾 char arr[7]= {' ','h','e','l','l','o','\0'}; strcat(cstr,arr); LOGD("new cstr=%s",cstr); return (*env)->NewStringUTF(env,cstr); } /**env java 虚拟机 结构体c实现的指针 包含的有很多jni方法 *jobject obj 代表的是调用这个c代码的java对象 代表的是DataProider的对象 */ JNIEXPORT jintArray JNICALL Java_cn_itcast_ndk3_DataProvider_intMethod (JNIEnv * env , jobject obj , jintArray arr){ //1.知道数组的长度 //2.操作这个数组里面的每一个元素 int len = (*env)->GetArrayLength(env,arr); LOGD("shuzu len =%d",len); // jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); jint* intarr = (*env)->GetIntArrayElements(env,arr,1); int i =0; //c99 for(;i<len;i++){ //*(intarr+i) += 10; LOGD("intarr[%d]=%d", i, intarr[i]); intarr[i]+= 10; } // void (*ReleaseIntArrayElements)(JNIEnv*, jintArray, // jint*, jint); // // (*env)->ReleaseIntArrayElements(env,arr,intarr,0); // c语言释放掉 刚才申请的内存空间 return arr; } /** * 代表的是调用c代码 的class类 * jclass DataProvider 类 */ JNIEXPORT jint JNICALL Java_cn_itcast_ndk3_DataProvider_sub (JNIEnv * env, jclass clazz, jint x, jint y){ LOGD("x=%d",x); LOGD("y=%d",y); return x-y; }
然后是dataprovider代码
package com.test.testndkdata; import android.R.integer; public class DataProvider { public native int add(int a, int b); public native String sayHello(String s); public native int[] ints(int[] nums); }
所有代码
http://dl.vmall.com/c0hivk447p