Android NDK开发入门篇

来源:互联网 发布:软件测试研究 编辑:程序博客网 时间:2024/04/30 13:12

1.NDK简介

NDK(Native Development Kit)“原生”也就是二进制

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


android常用的开发方式是java封装的库,而这些库的底层实现是由C/C++实现,如媒体,图形库等

java调用这样实现就需要用JNI(Java Native Interface)

平时用的也就是google给我们封装的好的库,即便是底层实现用的不是Java,但都有统一的Java接口

 

而NDK的作用是“我们自己写本地代码”(C/C++),自己用JNI封装成Java接口

比如我们想做个计算,二这不是Java的强项,可以用C/C++来写实现,返回一个运算结果就行了

NDKr5已经实现了不用写一行Java代码开发程序了,只不过还是用到了虚拟机,细节被封装隐藏起来了而已

 


对于JNI和NDK很多Android开发初学者没有搞明白这个问题

JNI是Java调用Native机制,是Java语言自己的特性全称为 Java Native Interface,类似的还有微软.Net Framework上的p/invoke,可以让C#或Visual Basic.Net可以调用C/C++的API,所以说JNI和Android没有关系,在PC上开发Java的应用,如果运行在Windows平台使用 JNI是是经常的,比如说读写Windows的注册表。

NDK是Google公司推出的帮助Android开发者通过C/C++本地语言编写应用的开发包,包含了C/C++的头文件、库文件、说明文档和示例 代码,我们可以理解为Windows Platform SDK一样,是纯C/C++编写的,但是Android并不支持纯C/C++编写的应用,同时NDK提供的库和函数功能很有限,仅仅处理些算法效率敏感的 问题,所以Android123推荐初学者学好Java后再学习JNI。

 

 


NDK其实多了一个把.so和.apk打包的工具,这个是很重要的。

而JNI开发并没有打包,只是把.so文件放到文件系统的特定位置。

如果是做应用开发,则需要NDK工具,不然你开发的应用程序怎么给用户用呢?难道帮他重新编译文件系统?

其他至于实现,java调用本地C/C++函数,及其编写方式,我觉得JNI和NDK没有什么区别。

还有一个我个人理解,NDK开发C/C++只能能使用NDK自带的有限的头文件,而使用JNI则可以使用文件系统中带的头文件,比如utils/Log.h

而后者的资源更多,当然NDK正在努力开发中,以便支持更丰富的接口。


 

2.开发环境搭建:
       NDK开发需要安装以下物体:

 在安装时候,选择make、gcc、g++、bash、


安装好后启动cygwin,运行:

看到如下所11示就ok了 (注意:GNU Make要 3.81以上版本)

 \

 


3.NDK的使用
 Ndk下载下来随意解压到一个目录即可(ndk的解压后存放的路径必须不能包括空格或中文,比如这种“D:\Program Files\Android-ndk-windows”在cygwin是不能识别成功的。)

如:D:\AndroidDevelop\NDK\android-ndk-r8b

配置NDK   在D:\AndroidDevelop\cygwin\home   目录下找到.bash_profile打开文件加上:

NDK=/cygdrive/d/AndroidDevelop/NDK/android-ndk-r8b

export NDK

 


配好后重新打开cygwin

输入:

cd  $NDK

 


 

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

 \


输入:  $NKD/ndk-build     验证NDK是否可以使用?

 


如果出现以下信息说明已经配置成功!

 \

 

 

 

 

 

如果出现错误:

 

 \

在Cygwin下用nano或者vim编辑器编辑你的脚本。对于那些已经存在的脚本用dos2unix转化一下。因为Windows下的换行是<LF><CR>,Linux下是<LF>,Mac下是<CR>。

先对你的脚本跑一下     dos2unix    .bash_profile 就行了。


4.关于NDK简单的Demo

 


(1)现在用安装好的NDK来编译一个简单的程序。在NDK的安装目录下新建一个myjni目录,用来存放我们编写Android项目。

进入到Eclipse中新建一个工程JNITest

书写Java代码: com.jun.jnitest  MainActivity.java

package com.jun.jnitest;

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

public class MainActivity extends Activity {
    private TextView tvShow=null;
 //    声明native函数speak(),此函数的实现是在C/C++代码中,通过动态库进行调用
    public native String  speak();
 //    静态代码块,先于构造函数执行,在此会对C/C++代码的库即:*.so文件进行加载
    static{
//        注意最终生成的动态库文件后缀名为.so加载时候不要加上后缀名,而在Linux开发环境中加载动态库时候需要加上后缀,切记这点
        System.loadLibrary("jni");
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        String text=speak();
        tvShow.setText(text);
    }

    private void init() {
        // TODO Auto-generated method stub
        tvShow=(TextView) findViewById(R.id.tv_data);
    }

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
}


⑵ 生成.h头文件,在windows命令行下进入到工程bin/classes目录下执行命令:

      javah -classpath . -d jni com.jun.jnitest.MainActivity

      就会在当前目录下的jni目录下生成我们所需要的头文件

 \

com_jun_jnitest_MainActivity.h: 

#include <jni.h>
#ifndef _Included_com_blueeagle_example_testNDK
#define _Included_com_blueeagle_example_testNDK
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_blueeagle_example_testNDK
 * Method:    stringTestNdk
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jun_jnitest_MainActivity_speak
  (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif


⑶在工程目录下建立Application.mk文件,文件内容

APP_PROJECT_PATH:=$(call my-dir)

APP_MODULES :=jni


⑷把生成的头文件拷贝到工程文件夹下的jni目录中,并新建Android.mk文件文件内容:

LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE :=jni

LOCAL_SRC_FILES :=com_jun_jnitest_MainActivity

include $(BUILD_SHARED_LIBRARY)

 

⑸在jni目录下新建com_jun_jnitest_MainActivity.c,文件内容

#include<stdlib.h>

#include<stdio.h>

#include"com_jun_jnitest_MainActivity.h"//include刚才生成的头文件

jstring JNICALL Java_com_jun_jnitest_MainActivity_speak (JNIEnv *, jobject){

return (*env)->NewStringUTF(env,"Hello word!This is my first NDK program!");

}


⑹到此,我们工程的jni目录下共有三个文件夹

 \

⑺终于,迎来结束的时刻了,我们现在使用cygwin来编译我们的应用程序,在指定应用程序(目录)名称后,NKD编译系统会首先找到目录中的Application.mk文件,根据Application.mk文件的信息,确定该Android共享需要使用的APP_MODULES模块;然后在jni目录中搜索所有Android.mk文件,在找到与APP_MODULES模块匹配的Android.mk文件后,根据Android.mk文件提供的信息编译指定的C/C++源代码文件,形成共享库文件;最后将生产的共享库文件拷贝到Android工程的指定目录中。启动cygwin后,直接输入命令cd $NDK可以进入ndk安装目录,然后进入myjni工程目录,输入命令$NDK/ndk-build ,看到以下信息,看到Install  说明你已经完成所有工作了!

 

 \

 (8)我们刷新下Eclipse  来运行我们的程序!看下图

 \

 

 

5.关于NDK常见的问题
问:NDK 是什么 

1、NDK 是一系列工具的集合。

NDK提供了一系列的工具,帮助开发者快速开发 C (或 C++ )的动态库,并能自动将 so 和 java 应用一起打包成 apk 。这些工具对开发者的帮助是巨大的。
NDK集成了交叉编译器,并提供了相应的 mk 文件隔离 CPU 、平台、 ABI 等差异,开发人员只需要简单修改 mk 文件(指出 “ 哪些文件需要编译 ” 、 “ 编译特性要求 ” 等),就可以创建出 so 。
NDK可以自动地将 so 和 Java 应用一起打包,极大地减轻了开发人员的打包工作。
2、NDK 提供了一份稳定、功能有限的API头文件声明。

Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm )、压缩库( libz )、 Log 库( liblog )。

问:NDK带来什么

1、NDK 的发布,使“Java+C”的开发方式终于转正,成为官方支持的开发方式。

使用NDK ,我们可以将要求高性能的应用逻辑使用 C 开发,从而提高应用程序的执行效率。
使用NDK ,我们可以将需要保密的应用逻辑使用 C 开发。毕竟, Java 包都是可以反编译的。
NDK促使专业 so 组件商的出现。(乐观猜想,要视乎 Android 用户的数量)
2、NDK 将是Android平台支持C开发的开端。

NDK提供了的开发工具集合,使开发人员可以便捷地开发、发布C组件。

0 0
原创粉丝点击