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

来源:互联网 发布:mac最新版本 编辑:程序博客网 时间:2024/06/10 10:18

Android NDK开发入门指引

 

前言:

       AndroidNDK是一套工具,允许Android应用开发者嵌入从CC++源代码文件编译来的本地机器代码到各自的应用软件包中,并通过JNI进行访问。Android1.5开始支持NDK.

 

环境搭建:

       NDK开发需要安装以下物体:

1.cygwin (需要1.7以上版本,下载地址:http://www.cygwin.com官方明确表示MSys or Cygwin 1.5 is notsupported), 这个我用的是在线安装方法(并且是全安装,非常大,很耗时)

安装好后启动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
  JDKJava 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:/ProgramFiles/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  -jnicom.jiubang.Demo.Ndk.PassNormalData.CallNativeDemo

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

内容大概如下:

/* DO NOT EDIT THIS FILE - it ismachine generated */

#include <jni.h>

/* Header for classcom_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 JNICALLJava_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 JNICALLJava_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 JNICALLJava_com_jiubang_Demo_Ndk_PassNormalData_CallNativeDemo_Sum(JNIEnv* aEnv,jobject aThis, jint aParamA, jint aParamB)

{

 

    intsum = 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("HELLOWORLD!/n", file);

       fflush(file);

       fclose(file);

    }

 

 

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

    returnsum;

}

 

 

// 对应public native StringStrCat(String str1 , String str2)实现

jstring JNICALLJava_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");

 

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

    constchar* 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);

 

    //jstringjstrRet = (*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


 

有看到InstallOK

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

 

最后在android工程里加上调用这些ndk本地方法的代码:

 

       

运行,得到结果:


 

更多的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

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子吐还拉稀怎么办 宝贝拉肚子又吐怎么办 小孩子发烧呕吐拉肚子怎么办 小孩受凉呕吐拉肚子怎么办 一周岁宝宝发烧怎么办 宝宝吃了吐怎么办 儿子喝水都吐怎么办 宝宝吐奶拉肚子怎么办 怀孕吐的厉害怎么办 孩子一直呕吐怎么办啊 仓鼠宝宝拉稀了怎么办 2岁有点拉稀怎么办 婴儿吃米粉腹泻怎么办 小儿胃寒呕吐怎么办 孩子突然一直吐怎么办 宝宝呕吐并发烧怎么办 宝宝发烧呕吐拉稀怎么办 小孩发高烧还吐怎么办 二个多月的宝宝拉肚子怎么办 宝宝肚子着凉吐怎么办 孩子胃着凉呕吐怎么办 一岁受凉呕吐怎么办 孩子着凉了呕吐怎么办 小孩受凉呕吐腹泻怎么办 宝宝胃受寒呕吐怎么办 一岁半宝宝受寒呕吐怎么办 治小儿反复发烧怎么办 海洋宝宝吃下去怎么办 两岁儿童拉肚子怎么办 14天宝宝拉肚子怎么办 小孩不消化引起发烧怎么办 宝宝胃胀呕吐怎么办 小儿胃胀不消化怎么办 4岁小儿腹胀怎么办 两岁半的宝宝吐怎么办 月子宝宝闹人怎么办 宝宝一周岁拉肚子怎么办 一岁幼儿呕吐怎么办 孩子受凉呕吐拉肚子怎么办 5岁儿童呕吐怎么办 小孩发烧老是吐怎么办