您的位置:首页 > 移动开发 > Android开发

Android NDK开发入门指引(有源码)

2011-02-16 20:03 393 查看

Android NDK

开发入门指引


前言:

Android
NDK

是一套工具,允许

Android

应用开发者嵌入从

C



C++

源代码文件编译来的本地机器代码到各自的应用软件包中

,

并通过

JNI

进行访问。

Android



1.5

开始支持

NDK.

环境搭建:

NDK

开发需要安装以下物体

:

1.cygwin

(

需要

1.7

以上版本,下载地址:
http://www.cygwin.com
官方明确表示

MSys or Cygwin 1.5 is not
supported),

这个我用的是在线安装方法(并且是全安装,非常大,很耗时)

安装好后启动

cygwin,

运行

:

Make –v

看到如下所示就

ok



(

注意

:GNU Make



3.81

以上版本

)



2.NDK

(android-ndk-r4b)

,此文档只针对

r4b

版进行说明

, ndk

可以到官方网

http://developer.android.com

上进行下载,

但这个网站已被

zf

和协,我是在这里下载:
http://d131.d.iask.com/fs/800/1/c1631bdc5eaf7b8309db9cb23311693035788482/zip/android-ndk-r4b-windows.zip


如下载不了,直接向我要吧

.

Ndk

下载下来随意解压到一个目录即可

(

路径中不能有空格

)



: D:/android/android-ndk-r4b

然后为

cygwin

配好我们的

ndk PATH

环境



cygwin

用户路径

C:/cygwin/home/huangdingwu (

请替换相应用户名

)

打开

.bash_profile

在文件末尾加上:

ANDROID_NDK_ROOT=/cygdrive/d/android/android-ndk-r4b

export ANDROID_NDK_ROOT

PATH=${ANDROID_NDK_ROOT}:${PATH}

配好后重新打开

cygwin

输入:

Ndk-build

如出现如下提示表示路径已配好:



3.eclipse +
android sdk

(

这个



大家应该都已经安装好了

)

4.windows



Jdk

安装配置

第一步:下载

JDK

  

JDK



Java Developement Kit

的缩写,包括

Java

编译器和运行时环境

j2re



可以从

SUN Java

站点下载
http://java.sun.com/javase/downloads/index.jsp http://www6.software.ibm.com/dl/idpe/idpe-p?S_TACT=104AHW02
或它的前一面:
http://www-106.ibm.com/developerworks/java/jdk/eclipse/
第二步:安装

JDK

  直接运行

JDK

的安装程序,选择一个安装目录,按照安装向导即可轻松完成

JDK

的安装。如需了解安装细节,请参考

Java 2 SDK
Installation Notes for Microsoft Windows



第三步:设置环境变量

JAVA_HOME=<JDK

安装目录

>

Path=<



Path>;%JAVA_HOME%/bin;%JAVA_HOME%/jre/bin

(注意其实没有等号)

本人使用的是

jdk-6-windows-i586.exe

默认安装路径

C:/Program Files/Java/jdk1.6.0



JAVA_HOME=C:/Program
Files/Java/jdk1.6.0

第四步:编译一个

Java

程序

  请用任何文本编辑器输入以下内容并保存为

Hello.java

文件(只能保存为

Hello.java

,不能使用别的文件名),请严格注意大小写:

public class Hello

{

public static void main(String[] args)

{

System.out.println("Hello,
world.");

}

}

  然后打开控制台,切换到存放

Hello.java

的目录下,输入:

javac Hello.java

  如果编译通过,屏幕上没有任何显示。否则,屏幕上会输出出错信息,请仔细检查源代码。

第五步:运行一个

Java

程序

  打开控制台,切换到存放

Hello.class

的目录下,然后输入:

java Hello (

注意大小写啊

!)

  稍等几秒钟,屏幕输出:

Hello,
world.

  说明运行成功!

如果不成功可能环境变量不正确

简单的

NDK Demo

程序

好了,环境已搭建好,

现在我们开始建立一个简单的

ndk

程序来体验下整个

ndk

开发流程

:

第一步:首先我们在eclipse

中新建一个工程,工程名这里是NdkPassNormalData



在工程

中新建一个java

类:CallNativeDemo.java

内容如下:

package



com.jiubang.Demo.Ndk.PassNormalData;

public



class



CallNativeDemo {

static



{

System.loadLibrary

(

"NdkPassDataDemo"

);

//

注意库文件名,对于

NdkPassDataDemo

系统会在该类初始化时加载

//libNdkPassDataDemo.so



,

切记勿画蛇添足加上前面的

lib



.so

扩展名

}

public



native



int



Sum(

int



a ,

int



b); //

加上

native

表示该方法由

.so

实现

public



native



String StrCat(String str1 , String str2);

}

编写好该

java

文件后,先编译,然后用

javah

生成

ndk

中我们需要的

c

头文件

:

进入到工程的

bin

目录下输入:

javah

-jni
com.jiubang.Demo.Ndk.PassNormalData.CallNativeDemo

然后会在当前目录下生成com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo.h

文件

内容大概如下:

/* DO NOT EDIT THIS FILE - it is
machine generated */

#include <jni.h>

/* Header for class
com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo */

#ifndef
_Included_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo

#define
_Included_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class:

com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo

* Method:

Sum

* Signature: (II)I

*/

JNIEXPORT jint JNICALL
Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_Sum

(JNIEnv *, jobject, jint, jint);

/*

* Class:

com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo

* Method:

StrCat

* Signature:
(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL
Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_StrCat

(JNIEnv *, jobject, jstring, jstring);

#ifdef __cplusplus

}

#endif

#endif

第二步:在我们新的工程中加一个名为:jni

的文件夹。这个文件夹就是放原生态c/c++

的源码的地方,我们make

的时候cygwin

就是编译这个文件夹的。

第三步:在jni

文件夹里新建一个Android.mk

文件。注意,后缀为.mk ,

且文件夹一定要小写

Android.mk

的内容为:

LOCAL_PATH := $(call my-dir) <---------

默认的,不需要更改

include $(CLEAR_VARS)
<--------

默认的,不需要更改

LOCAL_MODULE := native
<--------

在java

类引用时的名称

LOCAL_SRC_FILES := myNative.c <------

在jni

文件夹下的
c/c++

的名称

include $(BUILD_SHARED_LIBRARY) <--

默认的,不需要更改

LOCAL_PATH := $(call my-dir)

<---------

返回当前路径

include $(CLEAR_VARS)

<--------

清除先前定义的环境变量

LOCAL_MODULE := NdkPassDataDemo

<--------



java

类引用时的名称

LOCAL_CPP_EXTENSION := cpp

LOCAL_SRC_FILES := Fun.cpp

<------

需要编译的源文件

LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib –llog

<--



log

要用到的库,这里暂时不大明白为什么库名是这样



include
$(BUILD_SHARED_LIBRARY)

<--

这里指的是动态库

第四步:在jni

文件夹里新建一个

Fun.cpp

的文件。这个文件就是c/c++

文件。

Fun.cpp

的内容为:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <android/log.h>

#include "com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo.h"

//

对应

public



native



int



Sum(

int



a ,

int



b)

的实现

jint JNICALL
Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_Sum(JNIEnv* aEnv,
jobject aThis, jint aParamA, jint aParamB)

{

int
sum = 0;

__android_log_print(ANDROID_LOG_INFO
, "Ndk_PassNormalData" , "CallNativeDemo_Sum Coming");

sum
= aParamA + aParamB;

FILE*
file = fopen("/sdcard/hello.txt","w+");

if
(file != NULL)

{

fputs("HELLO
WORLD!/n", file);

fflush(file);

fclose(file);

}

__android_log_print(ANDROID_LOG_INFO
, "Ndk_PassNormalData" , "CallNativeDemo_Sum Leaving");

return
sum;

}

//

对应

public



native



String
StrCat(String str1 , String str2)

实现

jstring JNICALL
Java_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_StrCat(JNIEnv *aEnv,
jobject aThis, jstring aStr1, jstring aStr2)

{

__android_log_print(ANDROID_LOG_INFO
, "Ndk_PassNormalData" , "CallNativeDemo_StrCat Coming");

const
char* str1 = aEnv->GetStringUTFChars(aStr1 , 0);

const
char* str2 = aEnv->GetStringUTFChars(aStr2 , 0);

//char* str1 = (char*)(*aEnv)->GetStringUTFChars(aEnv
,aStr1 , 0);

//char* str2 =
(char*)(*aEnv)->GetStringUTFChars(aEnv ,aStr2 , 0);

int str1_len = strlen(str1);

int str2_len = strlen(str2);

// char* pszRet =
malloc(str1_len + str2_len + 1);

char*
pszRet = new char[str1_len + str2_len + 1];

strcpy(pszRet,
str1);

strcat(pszRet,
str2);

//jstring
jstrRet = (*aEnv)->NewStringUTF(aEnv, pszRet);

jstring jstrRet = aEnv->NewStringUTF(pszRet);

// free(pszRet);

delete pszRet;

__android_log_print(ANDROID_LOG_INFO ,
"Ndk_PassNormalData" , "CallNativeDemo_StrCat Leaving");

return jstrRet;

}

然后就可以开始编译了

:

打开

cygwin,

进入到工程的

jni

目录,然后执行 ndk-build



有看到

Install



OK



然后会发现工程目录下会多了一个

lib



obj

的目录

最后在

android

工程里加上调用这些

ndk

本地方法的代码:

CallNativeDemo nativeDemo = new CallNativeDemo();
int value = nativeDemo.Sum(10, 20);
String str = nativeDemo.StrCat("who", "are you");
TextView v = (TextView)findViewById(R.id.textview1);
v.setText(str);


运行,得到结果:



更多的

jni

数据传递处理相关资料参见:

http://andilyliao.javaeye.com/blog/494255

http://blog.csdn.net/sunyujia/archive/2008/05/03/2371557.aspx

NDK

示例开发参考:

http://blog.csdn.net/GEOLO/archive/2010/10/20/5953941.aspx

本教程工程下载:
http://download.csdn.net/source/3224679
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: