Native Activities and Applications:
本地活动和应用程序:
-----------------------------------
I. Overview
I. 概述
===========
The Android SDK provides a helper class, NativeActivity,
that allows you to write a completely native activity.
Android SDK 提供一个 NativeActivity 辅助类,允许你写一个完整的本地活动。
With a native activity, it is possible to write a completely native application.
因为有了一个本地活动,编写一个完整的本地应程序成为了可能。
NativeActivity handles the communication between the Android framework and your native code,
so you do not have to subclass it or call its methods.
NativeActivity 处理 Android 框架和你的本地代码之间的通讯,
所以你不必继承它或调用它的方法。
All you need to do is declare your application to be native in
your AndroidManifest.xml file and begin creating your native application.
全部需要你做的是在你的 AndroidManifest.xml 文件中声明你的应用程序为本地,
并且开始创建你的本地应用程序。
Native activities do not change the fact that
Android applications still run in their own virtual machine,
sandboxed from other applications.
本地活动不能改变的事实是 Android 应用程序依然运行在它们自己的虚拟机中,从而对其它程序沙箱化。
Because of this, you can still access Android framework APIs through the JNI.
据此,你仍旧可以通过 JNI 访问 Android 框架 API 。
There are, however, native interfaces to access things
such as sensors, input events, and assets that you can use.
不过,本地接口你可以用来访问诸如:传感器、输入事件和资产。
注:android开发中可以使用 res/raw 和 assets 文件夹来存放不需要系统编译成二进制的文件,例如字体文件等,
这两个文件夹有很多相同的地方,例如都可以把文件夹下的东西原封不动的拷贝到应用程序目录下,
但是两个文件夹也有一些不同的地方:
1.首先就是访问方式不同,res/raw 文件夹不能有子文件夹,
读取 android 资源下的文件必须在 res 下建一个 raw 文件夹放入一个文本文件 readme.txt
可以使用 InputStream is = getResource().openRawResource( R.raw.readme ); 的方式获取到,
2.而 assets 文件夹可以自己创建文件夹,并且文件夹下的东西不会被 R.java 文件索引到,
即 Android SDK 不会为目录 assets 下的文件生成资源 ID ,必须使用 AssetsManager 类进行访问,
放在/assets的目录机构是什么样的使用 AssetManager 访问时也是采用同样的文件结构。
InputStream is = getAssets().open( "read_asset.txt" );
另外,一些低版本的 android 系统对 res/raw 和 assets 文件夹资源大小有限制
(<1M,其实 res/raw 和 assets 文件夹下的文件在 android 系统底层处理机制是一样的),
android2.2好像放宽(或者取消)了这个限制(至少可以存放 >10M ,具体没有测试。)
For more information about what is supported, see the <ndk_root>/docs/STABLE-APIS.HTML.
关于支持的更多信息,看 <ndk_root>/docs/STABLE-APIS.HTML 。
If you are developing a native activity,
you should still create your projects with Eclipse or the "android create project" command.
如果你是正在开发一个本地活动,你将依旧用 Eclipse 或 android create project 命令来创建你的工程。
You still build and package native applications with the usual Android build tools,
so the build system can only build Android projects that have the correct structure.
你仍然使用往常的 Android 生成工具生成且打包本地应用程序,
所以生成系统可以仅仅生成有正确结构的 Android 工程。
Using the android tool or Eclipse helps ensure that.
使用 Android 工具或 Eclipse 有助于确保这一点。
The Android NDK provides you with two choices to implement your native activity:
Android NDK 提供你两个选择来实现你的本地活动:
- The native_activity.h header defines the native version of the NativeActivity class.
native_activity.h 头文件定义了本地版本的 NativeActivity 类。
It contains the callback interface and data structures that
you need to create your native activity.
它包含创建你的本地活动所需的 回调接口 和 数据结构。
Because the main thread of your application handles the callbacks,
your callback implementations must not be blocking.
因为你的应用程序的主线程处理回调,你的回调实现必须不能出现阻塞。
If they block,
you might receive ANR (Application Not Responding) errors
because your main thread will be unresponsive until the callback returns.
如果它们阻塞的话,你可能收到 ANR(应用程序没响应)错误,因为你的主线程直到回调返回前将是无反应的。
Read the comments in the
<ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_activity.h file
for more information.
阅读
<ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_activity.h
文件中的注释了解更多信息。
- The android_native_app_glue.h file defines a static helper library
built on top of the native_activity.h interface.
android_native_app_glue.h 头文件定义的一个静态辅助库是构建在 native_activity.h 接口之上的。
It spawns another thread to handle things such as callbacks or input events.
它产生另一个线程来处理诸如:回调或输入事件之类的事。
This prevents any callbacks from blocking your main thread and adds some flexibility
in how you implement the callbacks,
so you might find this programming model a bit easier to implement.
这预防了任何回调阻塞你的主线程并且在你如何实现回调方面增加了一些灵活性。
The <ndk_root>/sources/android/native_app_glue/android_native_app_glue.c source is also available to you,
so you can modify the implementation if you need.
<ndk_root>/sources/android/native_app_glue/android_native_app_glue.c 源文件你同样是可以得到的,
因此如果你需要可以修改它的实现。
Read the comments in the
<ndk_root>/sources/android/native_app_glue/android_native_app_glue.h file
for more information.
阅读
<ndk_root>/sources/android/native_app_glue/android_native_app_glue.h
文件中的注释了解更多信息。
II. Using the native-activity.h interface:
II. 使用 native-activity.h 接口:
==========================================
You can use the native-activity.h interface to implement a completely native activity.
你可以使用 native-activity.h 接口来实现一个完整地本地活动。
If you use this interface you must ensure that
your callback implementations do not block the main UI thread.
如果你使用这个接口你必须确保你的回调实现不阻塞主用户界面线程。
For more information on how to use this interface,
see <ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_activity.h.
如何使用这个接口的更多信息,看如下头文件:
<ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_activity.h
You might find it easier to use the native_app_glue static helper library that
handles the callbacks in an event loop in another thread.
你可能发现使用 native_app_glue 静态辅助库在另一个线程中用一个事件循环处理回调更容易些。
See the native-activity sample application for more information on
how to use this static library.
如何使用这个静态库看 native-activity 示例应用程序获得更多信息。
To implement a native activity with the native-activity.h interface:
用 native-activity.h 来实现一个本地活动:
1/ Create a project with the "android create project" command or from Eclipse.
用 android create project 命令或用 Eclipse 创建一个工程。
注:参见《不用 IDE 手工创建、开发、编译、安装 Android 应用程序》
Create a jni/ directory in the project's root directory.
在工程根目录中创建一个 jni 目录。
This directory stores all of your native code.
这个目录保管你的全部本地代码。
2/ Declare your native activity in the AndroidManifest.xml file.
在 AndroidManifest.xml 文件中声明你的本地活动。
An example is shown below:
一个例子是如下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.native_activity"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:label="@string/app_name"
android:hasCode="false">
<activity android:name="android.app.NativeActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<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>
The main things to note are:
主要事情评注如下:
- The android:name attribute of the activity tag must be set to android.app.NativeActivity.
activity 标签的 android:name 属性必须设为 android.app.NativeActivity 。(上例第八行)
It is possible to subclass the NativeActivity, however, so if you do,
specify the name of that class instead.
子类化 NativeActivity 是可允许的,然而,那么如果你做了,指明子类名来作为替换。
- The android:name attribute of the meta-data tag must be in the form of android.app.lib_name
where lib_name is the name of the module without the lib prefix and .so suffix.
meta-data 标签的 android:name 属性值取用 "android.app.lib_name" 这个字符串,
android:value 属性值是模块名不带 lib 前缀和 .so 后缀的名字。(上例第十一行)
"android.app.lib_name" 是 NativeActivity::META_DATA_FUNC_NAME 常量默认值。
详见:http://developer.android.com/reference/android/app/NativeActivity.html#META_DATA_LIB_NAME
meta-data 标签的 android:name 属性值取用 "android.app.func_name" 这个字符串,
android:value 属性值是当启动本地代码时,NativeInstance 寻找的默认函数名(用来取代默认函数 ANativeActivity_onCreate ),
不取代默认函数 ANativeActivity_onCreate 可以不用定义此标签。
"android.app.func_name" 是 NativeActivity::META_DATA_LIB_NAME 常量默认值。
详见:http://developer.android.com/reference/android/app/NativeActivity.html#META_DATA_FUNC_NAME
3/ Create a file for your native activity and implement the ANativeActivity_onCreate() function,
which is called when your native activity starts.
为你的本地活动创建一个文件并实现 ANativeActivity_onCreate() 函数,当你的本地活动启动时被调用。
This function receives a pointer to an ANativeActivity structure,
which contains function pointers to the various callback implementations that
you need to write.
该函数接收一个 ANativeActivity 结构体指针,包含需要你来编写的不同回调实现的函数指针。
Set the applicable callback function pointers in ANativeActivity->callbacks to
the implementations of your callbacks.
在 ANativeActivity->callbacks 里的适当回调函数指针设置为你的回调实现。
4/ Set the ANativeActivity->instance field to the address of any instance specific data that
you want to use.
设置你想要使用的任何实例特定的数据地址给 ANativeActivity->instance 成员变量。
5/ Implement any other things that you want your activity to do upon starting.
实现一些你想要你的活动运行中去做的其它事情。
6/ Implement the rest of the callbacks that you set in ANativeActivity->callbacks.
你设置 ANativeActivity->callbacks 实现回调停止。
For more information on when the callbacks are called,
see the SDK documentation for Activity Lifecycles.
当回调被调用时的更多信息,看 SDK 文档中的活动生命周期。
Remember that your callback implementations must not be blocking,
or you might get ANR (Application Not Responding) errors
because the main UI thread is waiting for the callbacks to return.
记住你的回调实现必须不能阻塞,否则你可能得到 ANR (应用程序没有响应)错误,因为主用户界面线程是在等待回调返回。
7/ Develop the rest of your application.
制订你应用程序的停止。
8/ Create an Android.mk file in the jni/ directory of your project to
describe your native module to the build system.
在你工程的根目录下的 jni 目录中创建一个 Android.mk 文件来为生成系统描述你的本地模块。
An Android.mk file is essentially a snippet of a GNU Make file.
For example:
一个 Android.mk 文件基本上是 GNU Make 文件的片断。例如:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_native_module
LOCAL_SRC_FILES := my_native_code.c
include $(BUILD_SHARED_LIBRARY)
For more information on how to create an Android.mk file and what the variables mean,
see the <ndk_root>/docs/ANDROID-MK.TXT file.
关于如何创建一个 Android.mk 文件和所用变量作用的更多信息,看 <ndk_root>/docs/ANDROID-MK.TXT 文件。
9/ Once you have an Android.mk file, compile your native code using the "ndk-build" command.
一旦你有了一个 Android.mk 文件,编译你的本地代码就可以使用 ndk-build 命令。
cd path/to/project
<ndk_root>/ndk-build
10/ Build and install your Android project as usual,
using Ant or Eclipse.
生成并安装你的 Android 工程照例使用 Ant 或 Eclipse 。
The build automatically packages your native code into the .apk file
if it is present in the jni/ directory.
自动生成打包在你工程的根目录下的 jni 目录中的本地代码到 .apk 文件中。