1,准备工作之环境搭建,见Android环境搭建
2,新建android项目,项目名TestHelloWorld,项目保存位置D:\Users\wanghu\workspace\helloworld,然后点击next
3,选择SDK版本(我这选的是4.0.3)点next
4.配置项目的包名与入口Activity如下,点finish完成创建
5.1)在包名"com.bravestarr.testnative"下新建"SayHello"类,如下图,然后点击finish
5.2)SayHello.java类代码如下:
package com.bravestarr.testnative; public class SayHello { public native void say(); public native String getStringFromJNI(); }
5.3)dos窗口下按如下命令操作,cd到项目的class目录D:\Users\wanghu\workspace\helloworld\bin\classes
通过javah命令针对java编译出的class文件,生成C/C++的头文件,下面javah的意思是生成SayHello.class对应的C/C++的头文件,执行javah命令后自动会在classes的目录下生成一个com_bravestarr_testnative_SayHello.h文件,该文件代码如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_bravestarr_testnative_SayHello */ #ifndef _Included_com_bravestarr_testnative_SayHello #define _Included_com_bravestarr_testnative_SayHello #ifdef __cplusplus extern "C" { #endif /* * Class: com_bravestarr_testnative_SayHello * Method: say * Signature: ()V */ JNIEXPORT void JNICALL Java_com_bravestarr_testnative_SayHello_say (JNIEnv *, jobject); /* * Class: com_bravestarr_testnative_SayHello * Method: getStringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_bravestarr_testnative_SayHello_getStringFromJNI (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
5.4)根目录新建名为jni的文件夹,如下图,然后将5.3中生成的com_bravestarr_testnative_SayHello.h头文件剪切到jni文件夹中,并新建sayhello.c文件实现头文件中的方法
sayhello.c文件源码(C实现)如下:
sayhello.cpp文件源码(C++实现,源码同"sayhello.c")
/* * sayhello.c * * Created on: 2012-9-17 * Author: wanghu */ #include "com_bravestarr_testnative_SayHello.h" //若想在C/C++中使用android的Log功能,则引入"log.h"头文件 #include "log.h" #include <stdio.h> JNIEXPORT void JNICALL Java_com_bravestarr_testnative_SayHello_say (JNIEnv * env, jobject obj){ LOGI("Hello World~~~"); return; } JNIEXPORT jstring JNICALL Java_com_bravestarr_testnative_SayHello_getStringFromJNI (JNIEnv * env, jobject obj){ LOGI("here will return a String 'Hello World'"); jstring newstring = (*env)->NewStringUTF(env,"Hello World"); const char* str= (*env)->GetStringUTFChars(env, newstring ,NULL);//使用GetStringUTFChars方法将"Hello World"转成UTF-8格式的string的对象str (*env)->ReleaseStringUTFChars(env, newstring, str);//释放str对象的空间,如果不显示的调用的话,JVM中会一直保存该对象,不会被垃圾回收器回收,因此就会导致内存溢出 return newstring; }
"log.h"头文件内容如下:
#include <android/log.h> #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "bravestarr", __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "bravestarr", __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "bravestarr", __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "bravestarr", __VA_ARGS__)
5.5)jni文件夹中新建Android.mk文件,内容如下,其中注释的LOCAL_SRC_FILES := sayhello.cpp为C++的实现
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #LOCAL_MODULE表示生成的动态库名为sayhello LOCAL_MODULE := sayhello #LOCAL_SRC_FILES表示使用到的类 LOCAL_SRC_FILES := sayhello.c #LOCAL_SRC_FILES := sayhello.cpp LOCAL_LDLIBS := -lm -llog -ljnigraphics include $(BUILD_SHARED_LIBRARY)
6.编译库文件(*.so),见以前发布的一篇文章“Android环境搭建(含NDK的配置与使用)”中的“NDK的使用”部分(注意:如果直接使用Cygwin进行编译,需要在jni目录新建一个Application.mk文件),编译成动态库*.so文件后,会自动生成一个NUL文件,可以使用Cygwin进行删除,先通过cd进入到项目目录中,然后使用rm删除文件,如下
Application.mk文件内容如下:
APP_PLATFORM := android-15
编译前:
编译后:
7.修改TestHelloWorldActivity,代码如下
package com.bravestarr.testnative; import android.app.Activity; import android.os.Bundle; public class TestHelloWorldActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); SayHello hello = new SayHello(); hello.say(); System.out.println(hello.getStringFromJNI()); } static{ System.loadLibrary("sayhello"); } }
运行后效果
源码下载: