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");
    }
}

运行后效果

源码下载:

TestHelloWorld.zip(C实现)

posted on 2012-09-18 17:48  alex_wongh  阅读(2338)  评论(0编辑  收藏  举报