eclipse中JNI与NDK

JNI
  1. 简介:
    Java Native Interface,即java本地接口,本地接口就是指用C和C++开发的接口。
    实际使用中,java需要与本地代码进行交互,因为java具备跨平台的特点,所以java与本地代码交互能力非常弱,所以采用JNI特性增强java与本地代码交互的能力。
    使得java与本地其他类型语言(如c、c++)交互,即在java代码里调用c、c++等语言的代码或c、c++代码调用java代码。
  2. JNI是java调用Native语言的一种特性, JNI是属于java的,与Android没有直接关联。
NDK
  1. 简介
    Native Development Kit
    快速开发c、c++的动态库,并自动将so和应用一起打包成APK即可通过NDK在android中,使用JNI与本地代码(如c、c++)交互。
    在Android的场景下使用JNI即Android开发的功能需要本地代码(c\c++)实现。
  2. NDK是Android的一个开发工具包,NDK是属于Android,与java没有直接关联
NDK与JNI
  1. NDK编译出.so文件,JNI把.so文件放在文件系统的特定位置
  2. JNI用于本地语言与java交互,是Java中的接口;
  3. 使用NDK与JNI开发java+cpp的cocos2dx工程,然后用gradle构建工具构建出apk包
如何在eclipse中使用JNI:

1. java工程:用native声明C/C++方法,导入lib库

public class Native {
    static{
        System.loadLibrary("HelloJava");
    }
    public static native String getString();
}

注意这里"HelloJava"是你新建的c/c++文件名,不要多余写东西。现在我们定义了一个类是Native.java,然后我们要把这个类变成头文件。不过谷歌出的android studio 2.2版本以后可以直接新建一个支撑c/c++工程了。这里不先不提。

首先需要将Native.java编译生成一个.class文件。这里要用的javac。不过你也可以直接运行一下。eclipse会主动帮你编译生成.class,打开cmd
在这里插入图片描述
生成的Native.class
在这里插入图片描述
这里注意javac的使用我直接cd到了这个类的目录。

生成.class文件之后,再用jdk另外一个工具生成.h文件javah

同样在cmd中:输入javah -help查看使用帮助
在这里插入图片描述
[options]是可选项目,是必须项目。这个就是我们之前生成的Native.class

现在我们要确定需要加载类的路径,还有输出目录。注意每一段之间的空格,容易出错
在这里插入图片描述
类的后缀不需要写。执行这个指令完成之后会在当前目录下生成对应的.h文件
在这里插入图片描述
在eclipse右键工程名,refresh(f5)以下就会显示出来
在这里插入图片描述
2. jni目录

在工程中新建一个jni目录并且将刚才的.h文件移过来
在这里插入图片描述
新建一个HelloJava.c的.c源文件在这里我们来实现java层中声明的native方法

#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
JNIEXPORT jstring JNICALL Java_com_example_helloc_Native_getString
  (JNIEnv *env, jclass j){
    return (**env).NewStringUTF(env,"hello java!");
}

这个函数名字太复杂太扯淡了。其实jni有一个命名规则,我们现在不关心这个,这个函数名可以直接从之前生成的.h文件复制过来
下面就是.h文件的内容

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

#ifndef _Included_com_example_helloc_Native
#define _Included_com_example_helloc_Native
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_helloc_Native
 * Method:    getString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_helloc_Native_getString
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

这里只有函数声明,复制这个声明,我们只要在jni实现函数体就可以了。具体的编程方式这里先不提,这里只是返回了一个字符串

ndk中已经集成了部分c库。完成之后,我们需要将.c变成linux系统能使用的.so库。这个工作就由ndk来完成,具体如下:

ndk-build指令需要在工程目录下执行才有效果,但是并没有规定在什么子目录下,所有效果都是一样的。该指令会将.c或者c++文件生成对应的.so文件,而且是两份,一份在\project path\obj\local\armeabi,这份比较大,包含有调试信息,不会随着app一起发布。另外一份比较小\ project path \libs\armeabi,这个会随着apk一起发布。编译结果
在这里插入图片描述
生成了各个平台支持的.so文件完成之后工程目录的libs还没有出现.so文件,

需要右键工程refresh(F5)一下就会出现,这里系统会自动添加"lib"前缀。但是注意在java层导入库的时候不要写"libHelloJava"这个要写:

static{

    System.loadLibrary("HelloJava");

}

完成之后执行结果。这是android代码

public class MainActivity extends Activity {
    public Button btnShow;
    public TextView tvShow;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnShow = (Button)findViewById(R.id.btn_show);
        tvShow = (TextView)findViewById(R.id.tv_show);
        btnShow.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                tvShow.setText(Native.getString());
            }
        });
    }
}

结果
在这里插入图片描述
3. 另外执行ndk-build之前需要先编写**.mk**文件。具体如下:

在这里插入图片描述
在jni中新建一个android.mk文件,内容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE    := HelloJava
LOCAL_SRC_FILES := HelloJava.c
#LOCAL_LDLIBS    := -llog -ljnigraphics

include $(BUILD_SHARED_LIBRARY)

具体解释如下:

  • LOCAL_PATH := $(call my-dir)
    Android.mk文件首先必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件。在这个例子中,宏函数my-dir, 由编译系统提供,用于返回当前路径(即包含Android.mk file文件的目录)。

  • include $( CLEAR_VARS)
    CLEAR_VARS由编译系统提供,指定让GNU MAKEFILE为你清除许多LOCAL_XXX变量(例如 LOCAL_MODULE,LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等…), 除LOCAL_PATH。这是必要的,因为所有的编译控制文件都在同一个GNU MAKE执行环境中,所有的变量都是全局的。

  • LOCAL_MODULE := Native
    编译的目标对象,LOCAL_MODULE变量必须定义,以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的,而且不包含任何空格。

  • LOCAL_SRC_FILES := Native.c
    LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的C或C++源代码文件。注意,你不用在这里列出头文件和包含文件,因为编译系统将会自动为你找出依赖型的文件;仅仅列出直接传递给编译器的源代码文件就好。
    注意,默认的C++源码文件的扩展名是.cpp. 指定一个不同的扩展名也是可能的,只要定义LOCAL_DEFAULT_CPP_EXTENSION变量,不要忘记开始的小圆点(也就是.cxx,而不是cxx

  • include $(BUILD_SHARED_LIBRARY)
    BUILD_SHARED_LIBRARY表示编译生成共享库,是编译系统提供的变量,指向一个GNU Makefile脚本,负责收集自从上次调用'include $(CLEAR_VARS)'以来,定义在LOCAL_XXX变量中的所有信息,并且决定编译什么,如何正确地去做。还有BUILD_STATIC_LIBRARY变量表示生成静态库:lib$(LOCAL_MODULE).aBUILD_EXECUTABLE表示生成可执行文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.) 在项目根目录下创建jni目录,下面是要放进去的第一个文件Android.mk LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := main_jni #LOCAL_CFLAGS := LOCAL_SRC_FILES := main.cpp #LOCAL_LDLIBS := include $(BUILD_SHARED_LIBRARY) 2.) 在jni目录创建main.cpp #include using namespace std; #ifdef __cplusplus extern "C" { #endif class Test { public: Test(){}; ~Test(){}; int SomeFunc() { return 20140522; } }; jint Java_com_yxiaolv_testjni_MainActivity_SomeFunc(JNIEnv *env, jobject thiz) //红色部分必须和你java类包名一致 { Test *test = new Test(); return test->SomeFunc(); } #ifdef __cplusplus } #endif //将下面第3.)至第5.)步的代码片段放到eclipse创建android项目时自动产生的MainAcitivity.java就可以了 3.) 在Java Activity代码添加对这个jni的调用 (本例是MainActivity.java ): static { System.loadLibrary("main_jni"); } 4.) 在调用者Activity定义函数 native int SomeFunc(); 5.) 在activity调用 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv = new TextView(this); int i = SomeFunc(); tv.setText( String.valueOf(i) ); setContentView(tv); } //下面的第6.)和第7.)步可以被集成的.cproject 和在.project添加plugin之后一键编译,不用单独起dos窗口了。由于没有找到生成.cproject的工具,只能手写,所以本文不使用该方法,以后找到了好的方法再补充。委屈 6.) 在dos窗口,cd到项目路径下,运行ndk-build 命令,该命令会自动搜索该路径子目录下的native项目,进行编译。 (Note: 编译完成后不要忘记了刷新项目)。 7.) 重新编译和部署项目,就可以看到已经包含了.so的apk运行在目标机上了。 摘自 http://stackoverflow.com/questions/13654678/how-compile-c-project-via-android-ndk 1). 如果不知道怎样安装和使用windows版的NDK,可以参考 http://blog.csdn.net/do_script/article/details/26478583
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值