• 初学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:Developandroid-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:Developandroid-ndkuild/core/build-local.mk:130: *** Android NDK: Aborting
       .  Stop.

    2.调用JNI的流程

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

            public native String helloFromJNI();

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

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

        2.4.在CC++文件中定义对应的要事先的方法,需要导入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.CC++中方法的命名

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

    public native String helloFromJNI();

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

    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路径下,在CC++代码中使用

    #include "com_chen_jni_demo_MyActivity.h"

        将该文件包含进去。

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

    JNIEXPORT jstring JNICALL Java_com_chen_jni_demo_MyActivity_helloFromJNI
      (JNIEnv *, jobject)

    5.在CC++中使用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__)

        在CC++文件汇总,使用以上代码可以调用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;

  • 相关阅读:
    JavaScript之MV*模式
    JavaScript之命名空间模式 浅析
    设计模式漫谈
    JavaScript之作用域与闭包详解
    JavaScript数据检测
    Code Conventions for the JavaScript Programming Language
    Javascript之对象的继承
    多线程,进程,协程用法
    scrapy_redis 实现多进程配置部分代码
    自己设计代理IP池
  • 原文地址:https://www.cnblogs.com/chenchong/p/3266221.html
Copyright © 2020-2023  润新知