NDK编程指导:概念

来源:互联网 发布:淘宝服装外景拍摄 编辑:程序博客网 时间:2024/05/24 05:38

开始

本指导适合:

  • 熟悉本地化编程概念,并且开发Android应用程序的人员。
  • 工作环境是Eclipse和ADT,其他除非另有说明。


介绍

这部分提供了NDK工作的高级解释。Android NDK是一个工具集,允许你嵌入C或C++本地代码到你得Android的程序中。在Android的程序中使用本地代码对程序原来说是非常有用的:

在app不同平台下提供接口。

使用其他人创建的类库或者创建自己的类库供他人使用。

在某些情况下增加性能,特别是密集型的计算比如说游戏。

重要提示:Android NDK仅可以被使用到Android1.5(API-3)或更高的版本之后。NDK仅支持系统非常有限的本地APIs的头文件和Android平台支持的类库。一个Android系统镜像包含很多本地共享类库,你应该考虑一下具体的实现,因为发布的不同平台之间可能有细微的变化。还有一些NDK不支持的类库,不要指望依赖他是可以用的,反之,OTA系统升级之后可能破坏掉。


进程

这部分主要介绍在为Android编译本地应用的时候用到的一些主要组成部分,并且继续描述编译和打包的流程。

主要组件

当你编译你的app的时候你应该了解下列组成:

ndk-build:ndk-build脚本启动ndk核心的编译脚本。脚本主要内容为:动态探测你开发系统和项目文件,来决定编译出什么;生成二进制文件;拷贝二进制文件到你的程序工程路径。

更多信息请查看ndk-build指导部分。

Java:就是项目的java文件,Android编译进程将编译.dex(Dalvik Executable,Dalvik可执行)文件,再Android系统的Dalvik虚拟机运行的就是这。即使你没有写java文件,它也会生成一个包含本地组成的.dex文件。

当开发java部分的时候,通过native关键字来表明实现的是一个本地代码。例如,下面的方法声明告诉编译器它的具体实现在一个本地类库中:

public native int add(int  x, int  y);

Native shared libraries(本地共享类库):NDK从本地代码中编译类库或者说.so文件。

提示:如果两个类库中有相同名的实现方法,将会报错。

Native static libraries(本地静态类库):NDK也能编译静态类库或者.a文件。这些类库你可以链到其他类库。

Java Native Interface(JNI,java本地接口):JNI是java和C++相互通讯的一个接口。具体信息请参见Java本地借口规范。

Application Binary Interface(ABI,应用二进制接口):ABI定义了你的应用机器码在运行时如何与系统如何交互。NDK编译的.so文件就对应着这些ABI。不同的ABIs对应着不同的架构,NDK包含的ABI架构有ARMEABI(默认)、MIPS、x86。更多查看支持的ABI介绍。

Manifest:如果你的app没有java代码,那么你就必须要在Manifest中声明NativeActivity。关于NativeActivity的相关介绍,请参考后面介绍的“native-active.h”接口部分。


提示:下面两项仅适用于使用AndroidNDK提供的toolchains工具作为独立的交叉编译工具。

Android.mk:你必须在jni文件夹下创建Android.mk文件。ndk-build脚本要检查这个文件中包含的module名称定义、包含的源文件,编译的参数、链接的类库等。更多详细信息查看Android.mk的介绍。

Application.mk:Application.mk文件创建时可选的。文件主要是列举和描述你的app需要的一些模块。主要包括:用来编译到指定平台的ABIs;Toolchain工具;包含的标准类库(静态或动态的STLport,或者系统默认)。更多的介绍在Application.mk部分介绍。



流程

开发一个Android本地化的app具体流程如下:

1.设计app。设计哪一部分在java中实现,哪一部分在本地代码中实现。

提示:你可能会找到控制显示和UI的Android Java框架来避免使用Java。

2.创建一个Android app项目。

3.如果你正在写仅本地的app,在AndroidManifest.xml文件中要声明NativeActivity类。你可以通过Android Manifest编辑器或者手动编辑AndroidManifest.xml文件。具体编辑请参考Native Activity介绍。

4.创建一个Android.mk文件来描述本地类库,包括名字、标志、链接的类库和在JNI文件夹中要被编译的源文件。

5.可选:创建一个Application.mk文件,配置指定的ABIs、Toolchain、debug/release模式、STL(标准模版库)。下列的配置都是默认的,如果有不同你需要重新制定:

  • ABI: armeabi
  • Toolchain: GCC 4.6
  • Mode: Release
  • STL: system
6.把本地代码放到项目的jni文件夹下。

7.用ndk-build编译本地类库(.so or .a)。

8.编译java部分,生成.dex可执行文件。

9.打包每一样东西到apk文件,包括.so、.dex、和其他app运行所需要的文件。

需要注意的是在Eclipse中可以单独操作从7到9步。


本地Activities和Applications

Android SDK提供了一个帮助类,就是NativeActivity,允许你写一个完全的native activity。NativeActivity能处理Android层和本地代码的交互,所以你不必子类化它或者调用它的方法。你需要做的就是在AndroidManifest.xml文件中声明它,然后创建你的本地应用。

一个使用了NativeActivity的Android应用程序仍然运行在其他程序沙箱中的自己的虚拟机中。因此,你可以通过JNI使用Android层的APIs。在某些情况下,像传感器、输入事件和assets资源,你可以使用NDK提供的本地接口,而不必通过跨JNI调用。有关更多信息,请参阅STABLE-APIS.HTML

无论你开发的是否为一个本地activity,我们建议你通过android常用的构建工具。这样有助于编译和Android应用程序打包的结构正确。

Android NDK提供了两种选择实现你的本地activity:

native_activity.h头文件定义了NativeActivity类的版本。它包含了你要创建的activity的回调接口和数据结构。因为你创建的应用的主线程处理回调必须是非阻塞的。如果是阻塞的,由于主线程回调返回之前没有回复,就会导致你可能收到ANR(Application Not Responding,应用程序无响应)错误。

在native_avtivity.h接口之上,android_native_app_glue.h头文件定义了一个辅助类库。它创建另一个线程,在线程中事件循环来处理像回调或者输入事件。通过把这些事件放到单独的线程来阻止任何一个回调阻塞主线程。

<ndk_root>/sources/android/native_app_glue/android_native_app_glue.c源文件仍然可用,你可以修改他的实现。

更多关于他的使用,在实例native-activity中去练习。进一步的说明也在<ndk_root>/sources/android/native_app_glue/android_native_app_glue.h文件的注释中。


native-activity.h接口的使用

用native-activity.h实现一个本地activity:

1.创建一个jni/目录在你的项目根目录下。这个目录放了你所有的本地代码。

2.在AndroidManifest.xml中声明你的activity。

因为你的应用没有java代码,所以要设置android:hasCodefalse

<application android:label="@string/app_name" android:hasCode="false">

activity的标签android:name必须设置为android.app.NativeActivity

<activity android:name="android.app.NativeActivity" android:label="@string/app_name"

提示:你可以创建NativeActivity的子类,然后把NativeActivity换成子类的名称。

meta-data标签的android:value属性用来指定包含应用入口的共享类库的名称(省略类库的lib前缀和.so后缀)。

          <meta-data android:name="android.app.lib_name"            android:value="native-activity" />            <intent-filter>              <action android:name="android.intent.action.MAIN" />              <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>          </activity>        </application>      </manifest>
3.创建一个nativeactivity文件,实现ANativeActivity_onCreate()方法,当activity启动的时候应用就会调用此方法。此方法类似于在C/C++中的main方法,接受一个ANativeActivity结构的指针,其中包含了各种各样你需要实现的回调指针。设置合适的回调指针ANativeActivity->;callbacks来设置你的回调实现。

4.设置ANativeActivity->;instance为有你想用的数据的实例的地址。

5.实现其他activity启动要实现的功能。

6.实现在ANativeActivity->;callbacks中设置的其他的回调。更多回调被调用的信息,请参阅SDK文档中Activity的生命周期。

7.实现程序其他的实现。

8.在你项目的jni/文件下创建Android.mk文件,描述本地模块和编译系统等。更多文件内容介绍查看,Android.mk介绍。

9.Android.mk文件创建完成之后,用ndk-build命令编译你的本地代码。

$ cd <path>/<to>/<project>$ <ndk>/ndk-build

10.使用Ant或Eclipse,编译、安装你的应用。如果你的本地代码在jni路径下,编译脚本将动态将你的.so文件打包进APK。


更多native-activity.h使用信息,请查看<ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_a ctivity.h注释。

0 0
原创粉丝点击