初学JNI(一)环境配置及调用流程

1.搭建环境

    安装Cygwin(Cygwin是在Windows平台下模拟Linux环境的工具。)

    安装NDK http://developer.android.com/tools/sdk/ndk/index.html

    配置环境变量:

    1.1.使用Cygwin提供的命令行工具,使用 cd ..命令回到home路径

    1.2.进入/cygdrive路径,找到自己NDK的安装路径,然后复制当前命令行显示的完整路径

    1.3.在Cygwin的etc路径下找到profile文件,在其中的Path中添加上面复制的完整路径,使用冒号分隔。

 

    PS:在ndk-r7版本以后,不再需要安装Cygwin,可以在windows环境下直接使用ndk-build进行交叉编译编译。需要在环境变量中配置NDK的路径,如下:

    在系统变量中新建:

        变量名:NDK_HOME

        变量值:D:\Develop\android-ndk

    在Path中添加:

        %NDK_HOME%,使用分号分隔

    在命令提示符中执行ndk-build,如果出现以下内容,则配置环境变量成功:

Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
D:\Develop\android-ndk\build/core/build-local.mk:130: *** Android NDK: Aborting
   .  Stop.

 

2.调用JNI的流程

    2.1.在Java中定义native方法,该方法需要由C\C++来实现,例如:

        public native String helloFromJNI();

    2.2.在项目路径下建立jni文件夹

    2.3.在jni路径下建立C\C++文件

    2.4.在C\C++文件中定义对应的要事先的方法,需要导入jni.h头文件

    2.5.编写Android.mk文件(可以在NDK的docs路径下找到ANDROID-MK.html,在第75行可以找到实例代码,复制即可),如下:

      LOCAL_PATH := $(call my-dir)

      include $(CLEAR_VARS)

      LOCAL_MODULE    := Hello
     LOCAL_SRC_FILES := Hello.c

      LOCAL_LDLIBS+=-llog
     include $(BUILD_SHARED_LIBRARY)

      Android.mk文件中,各行的解释:

2.5.1.

LOCAL_PATH := $(call my-dir)
    记录Android.mk的文件位置,其中call my-dir,得到绝对路径

2.5.2.

include $(CLEAR_VARS)
    初始化参数信息
    CLEAR_VARS 清空上次参数信息

2.5.3.

LOCAL_MODULE    := Hello
    交叉编译后,生成的可执行文件名称

2.5.4.

LOCAL_SRC_FILES := Hello.c
    参与交叉编译的源文件,需要多个源文件时,使用空格分隔

2.5.5.

include $(BUILD_SHARED_LIBRARY)
    指定交叉编译后,生成的文件类型
    BUILD_SHARED_LIBRARY-动态链接库
    BUILD_STATIC_LIBRARY-静态链接库

   2.6.使用Cygwin命令行,进入jni目录,使用ndk-build命令进行交叉编译(ndk-r7及以上版本不需要使用Cygwin,直接在项目路径下使用ndk-build命令即可进行交叉编译),生成.so文件

   2.7.在Java代码中使用静态方法调用编译生成的库文件,如下:

static {
        System.loadLibrary("Hello");
    }

   2.8.调用native方法,实现JNI调用

3.C\C++中方法的命名

    在Java代码中定义的native方法如下:

public native String helloFromJNI();

    则在C\C++代码中需要命名为:

jstring JNICALL Java_com_chen_jni_demo_MyActivity_helloFromJNI

 

4.方便生成方法名的方式

    进入到工程的bin路径下(jdk1.7则进入src路径),使用javah命令生成.h头文件:

javah com.chen.jni.demo.MyActivity

    生成的.h文件内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_chen_jni_demo_MyActivity */

#ifndef _Included_com_chen_jni_demo_MyActivity
#define _Included_com_chen_jni_demo_MyActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     com_chen_jni_demo_MyActivity
* Method:    helloFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_chen_jni_demo_MyActivity_helloFromJNI
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

    将该文件复制到jni路径下,在C\C++代码中使用

#include "com_chen_jni_demo_MyActivity.h"

    将该文件包含进去。

    此时,方法名可以直接从.h文件中复制

JNIEXPORT jstring JNICALL Java_com_chen_jni_demo_MyActivity_helloFromJNI
  (JNIEnv *, jobject)

 

5.在C\C++中使用Log输出日志

#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

    在C\C++文件汇总,使用以上代码可以调用Log进行输出,此外,还必须在Android.mk文件中添加以下内容:

LOCAL_LDLIBS+=-llog

 

6.使用C++来实现JNI调用

    不同于使用C代码来实现JNI调用,使用C++实现调用时,还需要在jni路径下编写Application.mk文件,内容如下:

APP_ABI:=armeabi
APP_STL := gnustl_static

此时Android.mk文件中的内容如下:

LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := Hello
   LOCAL_SRC_FILES := Hello.cpp
   LOCAL_LDLIBS+=-llog
   include $(BUILD_SHARED_LIBRARY)

 

此时,就可以在*.cpp文件中使用

#include <iostream>
using namespace std;

posted on 2013-08-18 18:08  foolchen  阅读(596)  评论(0编辑  收藏  举报

导航