NDK开发环境搭建以及第一个ndk应用

一、下载NDK

下载Android NDK。下载地址:http://developer.android.com/tools/sdk/ndk/index.html

下载后解压缩到你的工作目录,例如:D:\android-ndk-r9

 二、安装Cygwin与使用NDK编译

由于NDK开发大都涉及到C/C++在GCC环境下编译、运行,所以在Windows环境下,需要用Cygwin模拟Linux编译环境。

下载:

Cygwin的下载地址:http://www.cygwin.com/

点击右上角的“setup.exe”即可下载。

安装:

第一步:运行setup.exe程序,直接点击Next进入下一步。

第二步:选择安装方式。第一次可以采用Direct Connection在线下载安装,如有现成的离线包,可以选择离线安装(Install from Local Directory)。

第三步:选择安装目录。比如D:\Java\Cygwin,注意此目录是指Cygwin最终的安装目录,不是下载文件暂存目录。

第四步:设置本地包暂存路径。暂存目录默认是放到setup.exe的同级目录下,建议放到指定的文件夹,如D:\Cygwin_install_file。安装完成后把这个文件夹打包备份,以后再配置时不用重新下载。

第五步:设置网络连接方式。这个目前河蟹没爬过来,选第一个即可。

第六步:选择下载站点地址。据说国内163站点的速度不错,我也是用的这个。

第七步:等待加载安装项载入,选择安装项。点击Devel-Default,使之变成Devel-Install,展开后可以看到其下的子项被选中了(网上多数教程都说选中某12个包,找起来太坑爹了,直接全下载了吧,全选多了150M左右)。此界面其他设置都不用动。

第八步:等待下载完成。下载完成时间决定于你选择的安装包数量及网络连接速度,安装我安装的版本,约983M,下载完成后会自动安装到上文设置的安装目录,安装也要时间的,总时间较长,去吃个饭没啥问题。

提醒:第四步的备份建议,尽量去做。如果有备份,第二步中选择离线安装。

验证:

运行安装目录下的“Cygwin.bat”,第一次运行时,它会自动创建用户信息,用户信息存放在“.\Cygwin\home”中。

在运行“Cygwin.bat”打开的命令行窗口输入:“cygcheck -c cygwin”命令,会打印出当前Cygwin的版本和运行状态,如果status是ok的话,则cygwin运行正常。

分别输入:“make –v”和,“gcc –v”命令如果检测成功,会有make和gcc相关版本信息打印出来。

设置NDK路径:

在windows的系统环境变量中添加NDK的路径。使用“/cygdrive/d/android-ndk-r9”(“/cygdrive/盘符/android-ndk-r9)这种Linux风格路径 

         运行Cygwin命令行cd $ndk,可以直接使用此环境变量,当然也可以手动的cd到该目录

三、在Eclipse中集成C/C++开发环境CDT

         CDT的安装可以使我们在一个工程中,同时开发基于C/C++的Native代码和基于Java语言的壳,之后的配置还可以使得一次编译两部分代码。

下载:

         下载地址:http://www.eclipse.org/cdt/downloads.php

说明:

Eclipse C/C++ IDE Indigo SR2:是带CDT的Eclipse开发环境。

p2 software repository:在线安装的地址。(似乎被河蟹爬了)

cdt-master-8.0.2.zip:这个是CDT的离线安装包。(推荐使用这个,保留离线包,复用)

离线安装:

         Eclipse -> Help -> Install New Software,点击add。Name:随意,建议使用好记的“CDT_版本”。Location:点击Archive,定位到下载的“cdt-master-8.0.2.zip”文件。

         错误:

如果Location的下面出现“Duplicate location”错误,请到Window -> preferences -> Install/Update -> Avaliable Software Site中找到该条,remove之。

验证:

         安装完成后,在Eclispe中新建一个项目,如果出现了C/C++项目,则表明CDT插件安装成功了。

 

四、安装Sequoyah插件

Sequoyah插件用于设置Android工程对Native开发的支持。

官方网址:http://www.eclipse.org/sequoyah/downloads/

在线安装:

         官网提供了用于在线安装的Update Site地址以及安装包的下载地址。貌似安装包才1M多,在线安装也没被河蟹爬过,直接在线安装了。勾选全部列出的可安装项并完成安装。

Location:http://download.eclipse.org/sequoyah/updates/2.0/

 

注意:

在安装界面不要勾选“Group items by category”复选框,默认是勾选的,出现了列表为空(There are no categorized items)的情况。

 

配置:

         安装完Sequoyah插件后,为Android配置NDK路径。

         在“window –> preferences ->Android -> 本机开发”中添加NDK的路径。

 

验证:

         右键之前建立的“HelloJni”项目,在“Android Tools”选项中包含“Add Native Support…”选项即成功。

五、第一个NDK程序

新建一个TestNDK的AndroidProject

1.写一个java类

TestNDK.java

package com.example.testndk;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;

public class TestNDK extends Activity {
/*

表明程序开始运行的时候会加载testNDK, static区声明的代码会先于onCreate方法执行。如果程序中有多个类,而且如果TestNDK这个类不是你应用程序的入口,那么testNDK(完整的名字是lib testNDK.so)这个库会在第一次使用TestNDK这个类的时候加载。*/

static{ System.loadLibrary("testNDK"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv=(TextView) findViewById(R.id.tv); tv.setText(new TestNDK().fun1()); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; }
/*

可以看到这两个方法的声明中有 native 关键字, 这个关键字表示这两个方法是本地方法,也就是说这两个方法是通过本地代码(C/C++)实现的,在java代码中仅仅是声明。

用eclipse编译该工程,生成相应的.class文件,这步必须在下一步之前完成,因为生成.h文件需要用到相应的.class文件。暂时不考虑报错信息。*/

public native String fun1(); public native String fun2(); }

2.在C/C++文件编写之前,需要利用javah这个工具生成相应的.h文件,然后根据这个.h文件编写相应的C/C++代码。

进入到刚才建立的testNDK工程目录中,查看工程文件:AndroidManifest.xml  assets  bin  default.properties  gen  res  src并新建一个jni的文件夹后就可以进行.h文件的生成了。

       在工程目录下执行: javah -classpath bin -d jni com.example.testndk.TestNDK

这里-classpath表示之前编译生成的.class文件;-d jni表示生成的.h文件存放的目录;com.example.testndk.TestNDK则是完整的类名。

       现在可以再jni目录下看到多了一个.h文件:com_example_testndk_testNDK.h;打开后,可以看到.h的内容

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

#ifndef _Included_com_example_testndk_TestNDK
#define _Included_com_example_testndk_TestNDK
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_testndk_TestNDK
 * Method:    fun1
 * Signature: ()V
 */
JNIEXPORT jstring JNICALL Java_com_example_testndk_TestNDK_fun1
(JNIEnv *, jobject) ;

/*
 * Class:     com_example_testndk_TestNDK
 * Method:    fun2
 * Signature: ()V
 */
JNIEXPORT jstring JNICALL Java_com_example_testndk_TestNDK_fun2
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif


 

上面代码中的JNIEXPORT 和 JNICALL 是jni的宏,在android的jni中不需要,当然写上去也不会有错。

函数名比较长但是完全按照:java_pacakege_class_mathod 形式来命名。

也就是说:

TestNDK.java中fun1() 方法对应于 C/C++中的 Java_com_example_testndk_TestNDK_fun1() 方法

TestNDK.java中fun2() 方法对应于 C/C++中的 Java_com_example_testndk_TestNDK_fun2() 方法

注意下其中的注释:

Signature: ()Ljava/lang/String;

()Ljava/lang/String;

()表示函数的参数为空(这里为空是指除了JNIEnv *, jobject 这两个参数之外没有其他参数,JNIEnv*, jobject是所有jni函数必有的两个参数,分别表示jni环境和对应的java类(或对象)本身),

Ljava/lang/String; 表示函数的返回值是java的String对象。

3.编写C/C++文件

#include <string.h>
#include <jni.h>

jstring
Java_com_example_testndk_TestNDK_fun1( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello JNI from Baron!");
}


这里只是实现了Java_com_example_testndk_TestNDK_fun1方法,而Java_com_example_testndk_TestNDK_fun2 方法并没有实现,因为在testNDK.java中只调用了stringTestNdk ()方法,所以stringTestNdk 2()方法没有实现也没关系,不过建议最好还是把所有java中定义的本地方法都实现了。

Java_com_example_testndk_TestNDK_fun1函数只是简单的返回了一个内容为 "Hello JNI from Baron!" 的jstring对象(对应于java中的String对象)。

testNDK.c文件就已经编写好了,这时的.h文件已经没有用了。        

 

4.编译生成相应的库

首先需要编写Android.mk文件

 

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := testNDK
LOCAL_SRC_FILES := testNDK.c
include $(BUILD_SHARED_LIBRARY)


 

这个Androd.mk文件很短,下面我们来逐行解释下:

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 := testNDK

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

注意:编译系统会自动产生合适的前缀和后缀,换句话说,一个被命名为'hello-jni'的共享库模块,将会生成'libhello-jni.so'文件。

重要注意事项:

如果你把库命名为‘libtestNDK’,编译系统将不会添加任何的lib前缀,也会生成libfoo.so,这是为了支持来源于Android平台的源代码的Android.mk文件,如果你确实需要这么做的话。

LOCAL_SRC_FILES := testNDK.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).a, BUILD_EXECUTABLE 表示生成可执行文件。

 

以上步骤完成之后就可以进行如下操作了

五、JNI编译环境配置

第一步:转换工程。点击“文件 -> 新建 -> 其他”(快捷键:Ctrl+N)。选择“C/C++”下的“Convert to a C/C++ Project(Adds C/C++ Nature)”。进入“下一步”。

 

         第二步:选中你刚才建的“TestNDK”工程,下面左边选“Makefile project”右边选“Cygwin GCC”。确定后提示的“透视图”不清楚是什么,点击“是”即可。

 

         第三步:在“TestNDK”工程上右键,选择“属性”。配置“C/C++ Build”和“C/C++ General ->  Paths and Symbols”。

         C/C++ Build:点击“C/C++ Build”,在右边的“Builder Settings”中去掉默认勾选的“Use default build command”复选框。设置Build command为你的ndk解压后ndk-build文件的路径

         C/C++ General ->  Paths and Symbols:在Includes下add新的GNU C依赖路径。此“HelloJni”工程需要“D:\android-ndk-r9\platforms\android-8\arch-arm\usr\include”即可,以后根据不同项目选择不同的依赖库。 

 完成以上步骤点击运行就可以看到如下效果了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值