Android NDK开发——环境配置

来源:互联网 发布:mac比较好用的浏览器 编辑:程序博客网 时间:2024/06/06 16:02

以前的NDK开发,需要使用cygwin模拟Linux环境,用ndk-build进行编译,虽然可以配置环境变量大大缩减编译复杂度,但是每次在eclipse改完代码,再用cygwin编译总是怪怪的。而且每次有新工程使用JNI时还要手动新建jni文件夹和Android.mk这些步骤,显得特别繁琐。

而现在,android NDK r7及以上的版本已经集成了Cygwin编译环境,也就是说,我们完全可以抛弃庞大的Cygwin了。使用NDK开发包可以自动为我们准备一切JNI的前奏,下面我们看看在eclipse下如何进行NDK开发。

安装NDK包

由于包太大,只能放在网盘:ndk-r10d-windows-32&64,提取码:93a1。

解压后,在eclipse –> window –> perference –> Android –> NDK标签中指定NDK所在的目录(只需要执行一次)

这里写图片描述

给工程添加JNI支持

在工程上右键 –> Android Tools –> Add Native Support

这里写图片描述

在弹出的对话框中,添加so库的名字

这里写图片描述

如此,eclipse便会自动生成jni文件夹,Android.mk文件和cpp文件。

这里写图片描述

值得一提的是,eclipse为我们自动生成的是C++文件,如果需要C文件,直接改后缀即可,然后注意c和c++指针调用时候的区别,下面会提到。

链接源码

在没有链接源码之前,在eclipse中打开c或者c++文件,会发现很多黄色下划线。

这里写图片描述

而且Ctrl点击还不能看到源码,强迫症患者表示很难接受,下面我们来给强迫症患者治病。

在工程点击右键 –> properties –> C/C++ General –> Paths and Symbols右侧点击add按钮 –> 点击File System –> 选择android-ndk-r9b\platforms\android-19\arch-arm\usr\include, 然后点击OK即可。

这里写图片描述

再回头看看该死的小黄线不见了,ctrl点击还能看见源码了。

编写Java层调用代码

环境配置相当简单,上面已经是全部了,下面我们以HelloJNI项目,示范下NDK开发步骤。第一步肯定是要编写java调用代码了。

package com.example.hellojni;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Toast;public class MainActivity extends Activity {    //1、声明Native方法    public native String javaFromJNI();      //2、使用前要装载so库    static {          System.loadLibrary("HelloJNI");      }      @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MainActivity.this, javaFromJNI(), Toast.LENGTH_LONG).show();            }        });    }}

生成头文件

在C++文件中定义native方法,方法签名规则是:返回值类型 Java_包名_类名_native方法名(JNIEnv* env, jobject obj)

其中这两个参数是必备的,其他参数应该依次排在后面。可以看出规则生成的方法签名比较长,很容易出错,所以我们可以使用javah命令帮我们生成头文件。

这里写图片描述

这里我们要先进入项目的src目录,例如我的目录是:D:\eclipseworkspace\LYGworkspace\HelloJNI_gk\src

使用-encoding utf-8是为了指定编码,因为编译器自动根据windows默认的编码(GBK)编译,如果不加这个,可能会报这个错:

这里写图片描述

如果javah命令不能使用,请先配置JDK环境。

经过上面的javah编译,src目录下就会生成一个h头文件。

这里写图片描述

然后就可以把它粘贴到项目的jni文件夹下,打开看看:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_hellojni_MainActivity */#ifndef _Included_com_example_hellojni_MainActivity#define _Included_com_example_hellojni_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_hellojni_MainActivity * Method:    javaFromJNI * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_hellojni_MainActivity_javaFromJNI  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

可以看到我们在MainActivity中声明的javaFromJNI方法已经被自动生成了,我们只需要引用这个头文件即可。而且这样做,无论是c文件还是c++文件都是通用的,不会出现兼容问题。

编写本地代码

接下来就是整体了,这部分的代码由c或者c++语言编写,可能很多搞android的看着都比较头疼,不过一般这部分都有专人写,我们能看懂就可以了。我们看下helloJNI的这部分代码,还是很简单的:

#include<stdio.h>#include <jni.h>#include "com_example_hellojni_MainActivity.h"jstring Java_com_example_hellojni_MainActivity_javaFromJNI(JNIEnv* env, jobject obj){    return env->NewStringUTF( "Hello JNI, GK!");}

上面是c++写法,如果是c文件,只要稍微改一下语法即可:

return env->NewStringUTF( "Hello JNI, GK!");

改成

return (*env)->NewStringUTF(env, "Hello JNI, GK!");

我们使用NDK开发包时,编写这部分代码时依然可以使用Alt+/进行代码提示:

这里写图片描述

修改Android.mk文件

一个Android.mk 文件用来向编译系统描述你的源代码,是交叉编译器在编译C/C++代码所依赖的配置文件。接下来,我们要修改eclipse为我们自动生成的Android.mk文件。

LOCAL_PATH := $(call my-dir)//mk文件所在路径 include $(CLEAR_VARS)//变量的初始化操作 特点:不会重新初始化LOCAL_PATH的变量  LOCAL_MODULE    := HelloJNI//指定编译后生成的.so文件名LOCAL_SRC_FILES := hello_jni.cpp//指定native代码文件,如果使用了c++库,需要把所有c和h文件都列出来include $(BUILD_SHARED_LIBRARY)//指定native代码编译成动态库.so或者指定编译成静态库.a  

编译

直接Build Project,控制台出现以下提示,编译成功,至此,我们就完成了一次NDK开发之旅。

**** Build of configuration Default for project HelloJNI_gk ****D:\NDK\android-ndk-r10d\ndk-build.cmd all [armeabi] Compile++ thumb: HelloJNI <= hello_jni.cpp[armeabi] SharedLibrary  : libHelloJNI.so[armeabi] Install        : libHelloJNI.so => libs/armeabi/libHelloJNI.so**** Build Finished ****
5 2