Android NDK rb5 文档之本地活动和应用程序

AndroidGA 2015-11-24

NativeActivitiesandApplications:

本地活动和应用程序:

-----------------------------------

I.Overview

I.概述

===========

TheAndroidSDKprovidesahelperclass,NativeActivity,

thatallowsyoutowriteacompletelynativeactivity.

AndroidSDK提供一个NativeActivity辅助类,允许你写一个完整的本地活动。

Withanativeactivity,itispossibletowriteacompletelynativeapplication.

因为有了一个本地活动,编写一个完整的本地应程序成为了可能。

NativeActivityhandlesthecommunicationbetweentheAndroidframeworkandyournativecode,

soyoudonothavetosubclassitorcallitsmethods.

NativeActivity处理Android框架和你的本地代码之间的通讯,

所以你不必继承它或调用它的方法。

Allyouneedtodoisdeclareyourapplicationtobenativein

yourAndroidManifest.xmlfileandbegincreatingyournativeapplication.

全部需要你做的是在你的AndroidManifest.xml文件中声明你的应用程序为本地,

并且开始创建你的本地应用程序。

Nativeactivitiesdonotchangethefactthat

Androidapplicationsstillrunintheirownvirtualmachine,

sandboxedfromotherapplications.

本地活动不能改变的事实是Android应用程序依然运行在它们自己的虚拟机中,从而对其它程序沙箱化。

Becauseofthis,youcanstillaccessAndroidframeworkAPIsthroughtheJNI.

据此,你仍旧可以通过JNI访问Android框架API。

Thereare,however,nativeinterfacestoaccessthings

suchassensors,inputevents,andassetsthatyoucanuse.

不过,本地接口你可以用来访问诸如:传感器、输入事件和资产。

注:android开发中可以使用res/raw和assets文件夹来存放不需要系统编译成二进制的文件,例如字体文件等,

这两个文件夹有很多相同的地方,例如都可以把文件夹下的东西原封不动的拷贝到应用程序目录下,

但是两个文件夹也有一些不同的地方:

1.首先就是访问方式不同,res/raw文件夹不能有子文件夹,

读取android资源下的文件必须在res下建一个raw文件夹放入一个文本文件readme.txt

可以使用InputStreamis=getResource().openRawResource(R.raw.readme);的方式获取到,

2.而assets文件夹可以自己创建文件夹,并且文件夹下的东西不会被R.java文件索引到,

即AndroidSDK不会为目录assets下的文件生成资源ID,必须使用AssetsManager类进行访问,

放在/assets的目录机构是什么样的使用AssetManager访问时也是采用同样的文件结构。

InputStreamis=getAssets().open("read_asset.txt");

另外,一些低版本的android系统对res/raw和assets文件夹资源大小有限制

(<1M,其实res/raw和assets文件夹下的文件在android系统底层处理机制是一样的),

android2.2好像放宽(或者取消)了这个限制(至少可以存放>10M,具体没有测试。)

Formoreinformationaboutwhatissupported,seethe<ndk_root>/docs/STABLE-APIS.HTML.

关于支持的更多信息,看<ndk_root>/docs/STABLE-APIS.HTML。

Ifyouaredevelopinganativeactivity,

youshouldstillcreateyourprojectswithEclipseorthe"androidcreateproject"command.

如果你是正在开发一个本地活动,你将依旧用Eclipse或androidcreateproject命令来创建你的工程。

YoustillbuildandpackagenativeapplicationswiththeusualAndroidbuildtools,

sothebuildsystemcanonlybuildAndroidprojectsthathavethecorrectstructure.

你仍然使用往常的Android生成工具生成且打包本地应用程序,

所以生成系统可以仅仅生成有正确结构的Android工程。

UsingtheandroidtoolorEclipsehelpsensurethat.

使用Android工具或Eclipse有助于确保这一点。

TheAndroidNDKprovidesyouwithtwochoicestoimplementyournativeactivity:

AndroidNDK提供你两个选择来实现你的本地活动:

-Thenative_activity.hheaderdefinesthenativeversionoftheNativeActivityclass.

native_activity.h头文件定义了本地版本的NativeActivity类。

Itcontainsthecallbackinterfaceanddatastructuresthat

youneedtocreateyournativeactivity.

它包含创建你的本地活动所需的回调接口和数据结构。

Becausethemainthreadofyourapplicationhandlesthecallbacks,

yourcallbackimplementationsmustnotbeblocking.

因为你的应用程序的主线程处理回调,你的回调实现必须不能出现阻塞。

Iftheyblock,

youmightreceiveANR(ApplicationNotResponding)errors

becauseyourmainthreadwillbeunresponsiveuntilthecallbackreturns.

如果它们阻塞的话,你可能收到ANR(应用程序没响应)错误,因为你的主线程直到回调返回前将是无反应的。

Readthecommentsinthe

<ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_activity.hfile

formoreinformation.

阅读

<ndk_root>/platforms/android-9/arch-arm/usr/include/android/native_activity.h

文件中的注释了解更多信息。

-Theandroid_native_app_glue.hfiledefinesastatichelperlibrary

builtontopofthenative_activity.hinterface.

android_native_app_glue.h头文件定义的一个静态辅助库是构建在native_activity.h接口之上的。

Itspawnsanotherthreadtohandlethingssuchascallbacksorinputevents.

它产生另一个线程来处理诸如:回调或输入事件之类的事。

Thispreventsanycallbacksfromblockingyourmainthreadandaddssomeflexibility

inhowyouimplementthecallbacks,

soyoumightfindthisprogrammingmodelabiteasiertoimplement.

这预防了任何回调阻塞你的主线程并且在你如何实现回调方面增加了一些灵活性。

The<ndk_root>/sources/android/native_app_glue/android_native_app_glue.csourceisalsoavailabletoyou,

soyoucanmodifytheimplementationifyouneed.

<ndk_root>/sources/android/native_app_glue/android_native_app_glue.c源文件你同样是可以得到的,

因此如果你需要可以修改它的实现。

Readthecommentsinthe

<ndk_root>/sources/android/native_app_glue/android_native_app_glue.hfile

formoreinformation.

阅读

<ndk_root>/sources/android/native_app_glue/android_native_app_glue.h

文件中的注释了解更多信息。

II.Usingthenative-activity.hinterface:

II.使用native-activity.h接口:

==========================================

Youcanusethenative-activity.hinterfacetoimplementacompletelynativeactivity.

你可以使用native-activity.h接口来实现一个完整地本地活动。

Ifyouusethisinterfaceyoumustensurethat

yourcallbackimplementationsdonotblockthemainUIthread.

如果你使用这个接口你必须确保你的回调实现不阻塞主用户界面线程。

Formoreinformationonhowtousethisinterface,

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

Youmightfinditeasiertousethenative_app_gluestatichelperlibrarythat

handlesthecallbacksinaneventloopinanotherthread.

你可能发现使用native_app_glue静态辅助库在另一个线程中用一个事件循环处理回调更容易些。

Seethenative-activitysampleapplicationformoreinformationon

howtousethisstaticlibrary.

如何使用这个静态库看native-activity示例应用程序获得更多信息。

Toimplementanativeactivitywiththenative-activity.hinterface:

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

1/Createaprojectwiththe"androidcreateproject"commandorfromEclipse.

用androidcreateproject命令或用Eclipse创建一个工程。

注:参见《不用IDE手工创建、开发、编译、安装Android应用程序》

Createajni/directoryintheproject'srootdirectory.

在工程根目录中创建一个jni目录。

Thisdirectorystoresallofyournativecode.

这个目录保管你的全部本地代码。

2/DeclareyournativeactivityintheAndroidManifest.xmlfile.

在AndroidManifest.xml文件中声明你的本地活动。

Anexampleisshownbelow:

一个例子是如下所示:

<manifestxmlns:android="http://schemas.android.com/apk/res/android"

package="com.example.native_activity"

android:versionCode="1"

android:versionname="1.0">

<uses-sdkandroid:minSdkVersion="8"/>

<applicationandroid:label="@string/app_name"

android:hasCode="false">

<activityandroid:name="android.app.NativeActivity"

android:label="@string/app_name"

android:configChanges="orientation|keyboardHidden">

<meta-dataandroid:name="android.app.lib_name"

android:value="native-activity"/>

<intent-filter>

<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

</application>

</manifest>

Themainthingstonoteare:

主要事情评注如下:

-Theandroid:nameattributeoftheactivitytagmustbesettoandroid.app.NativeActivity.

activity标签的android:name属性必须设为android.app.NativeActivity。(上例第八行)

ItispossibletosubclasstheNativeActivity,however,soifyoudo,

specifythenameofthatclassinstead.

子类化NativeActivity是可允许的,然而,那么如果你做了,指明子类名来作为替换。

-Theandroid:nameattributeofthemeta-datatagmustbeintheformofandroid.app.lib_name

wherelib_nameisthenameofthemodulewithoutthelibprefixand.sosuffix.

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/CreateafileforyournativeactivityandimplementtheANativeActivity_onCreate()function,

whichiscalledwhenyournativeactivitystarts.

为你的本地活动创建一个文件并实现ANativeActivity_onCreate()函数,当你的本地活动启动时被调用。

ThisfunctionreceivesapointertoanANativeActivitystructure,

whichcontainsfunctionpointerstothevariouscallbackimplementationsthat

youneedtowrite.

该函数接收一个ANativeActivity结构体指针,包含需要你来编写的不同回调实现的函数指针。

SettheapplicablecallbackfunctionpointersinANativeActivity->callbacksto

theimplementationsofyourcallbacks.

在ANativeActivity->callbacks里的适当回调函数指针设置为你的回调实现。

4/SettheANativeActivity->instancefieldtotheaddressofanyinstancespecificdatathat

youwanttouse.

设置你想要使用的任何实例特定的数据地址给ANativeActivity->instance成员变量。

5/Implementanyotherthingsthatyouwantyouractivitytodouponstarting.

实现一些你想要你的活动运行中去做的其它事情。

6/ImplementtherestofthecallbacksthatyousetinANativeActivity->callbacks.

你设置ANativeActivity->callbacks实现回调停止。

Formoreinformationonwhenthecallbacksarecalled,

seetheSDKdocumentationforActivityLifecycles.

当回调被调用时的更多信息,看SDK文档中的活动生命周期。

Rememberthatyourcallbackimplementationsmustnotbeblocking,

oryoumightgetANR(ApplicationNotResponding)errors

becausethemainUIthreadiswaitingforthecallbackstoreturn.

记住你的回调实现必须不能阻塞,否则你可能得到ANR(应用程序没有响应)错误,因为主用户界面线程是在等待回调返回。

7/Developtherestofyourapplication.

制订你应用程序的停止。

8/CreateanAndroid.mkfileinthejni/directoryofyourprojectto

describeyournativemoduletothebuildsystem.

在你工程的根目录下的jni目录中创建一个Android.mk文件来为生成系统描述你的本地模块。

AnAndroid.mkfileisessentiallyasnippetofaGNUMakefile.

Forexample:

一个Android.mk文件基本上是GNUMake文件的片断。例如:

LOCAL_PATH:=$(callmy-dir)

include$(CLEAR_VARS)

LOCAL_MODULE:=my_native_module

LOCAL_SRC_FILES:=my_native_code.c

include$(BUILD_SHARED_LIBRARY)

FormoreinformationonhowtocreateanAndroid.mkfileandwhatthevariablesmean,

seethe<ndk_root>/docs/ANDROID-MK.TXTfile.

关于如何创建一个Android.mk文件和所用变量作用的更多信息,看<ndk_root>/docs/ANDROID-MK.TXT文件。

9/OnceyouhaveanAndroid.mkfile,compileyournativecodeusingthe"ndk-build"command.

一旦你有了一个Android.mk文件,编译你的本地代码就可以使用ndk-build命令。

cdpath/to/project

<ndk_root>/ndk-build

10/BuildandinstallyourAndroidprojectasusual,

usingAntorEclipse.

生成并安装你的Android工程照例使用Ant或Eclipse。

Thebuildautomaticallypackagesyournativecodeintothe.apkfile

ifitispresentinthejni/directory.

自动生成打包在你工程的根目录下的jni目录中的本地代码到.apk文件中。

相关推荐