创建原生代码
原生扩展的核心是原生代码,它充当着您的应用程序与您希望控制的功能之间的第一层。在本示例中,原生代码将控制震动马达,使用 ActionScript 3发送和接受信息。您将自行编写功能来控制震动马达,还将使用Adobe AIR提供的Java API来向ActionScript 3发送和从其接受数据。 但是,在开始编码和使用库之前,您必须设置您的构建环境。 使用Flash Builder 4.6设置一个Android开发环境因为您将编写原生Android代码,您需要一个可操作Android SDK的开发环境。如果您还没有,请依照本指南开头包含的链接安装和配置Android SDK。完成此过程后,您将修改Flash Builder以创建和编译Android项目: - 打开Flash Builder并转到Install New Software(在OS X上为Flash Builder > Window > Install New Software)。(如果有必要,关闭并使用管理特权重新启动Flash Builder。)
- 在Work with框中输入Google的公共ADT软件存储库的路径:https://dl-ssl.google.com/android/eclipse/。单击Add并将存储库命名为Google ADT。单击OK添加存储库。
- Flash Builder将下载一组可用软件。安装所有开发人员工具,包括Android DDMS、Android开发工具、Android历史查看器和Android Traceview。单击Next两次,阅读EULA并决定是否同意,等待包安装。一些Android包包含未签名的内容,即使这样您也应该继续安装。
- 在提示时重新启动Flash Builder。
- 您需要将Flash Builder指向您的Android SDK的位置。转到Window > Preferences(在OS X上为Flash Builder > Preferences)并单击Android。单击Browse并选择您的Android SDK的根位置(比如C:\Users\dan\Programs\android-sdk)。如果您缺少Android SDK的任何组件,您将收到一个指令要求运行Android SDK管理器并安装它们。选择最新版本的SDK并单击OK。
- 单击Window > Android SDK and AVD Manager。
- 转到Available Packages并选择最新的Google Inc.包,以确保您拥有最新的Android SDK和API包。您可能还希望安装USB驱动程序,具体取决于您的设备。
- 关闭此窗口。您现在应该能够单击File > New Project,查看并输入Android Project的信息。完成之后,Flash Builder就已正确配置。
连接并测试您的Android设备您可能急于了解编写代码的具体细节,但如果现在确认您的电话能够连接并经过了Android SDK的识别,将在以后省掉不少麻烦。 - 连接您的Android设备
- 在设备上,转到Settings > Applications > Development并确保勾选了"USB Debugging" 复选框,确认开发模式已启用。
- 如果有必要,单击操作您计算机上允许安装驱动程序的对话框。在Windows上,您可能希望选择位于android_sdk\usb_driver文件夹中的驱动程序。
- 打开一个命令提示符或终端,运行"adb devices"。
- 您应该看到列出了您的设备ID。如果没有,请查阅在线指南,使adb可处理您的电话。如果该命令生成"command not found"或类似错误,请将android_sdk\tools文件夹的位置添加到您的系统PATH变量,并再试一次。
创建一个新Android项目我们现在必须在Flash Builder中创建一个新Android项目,要求链接器查找随AIR SDK提供的Java API JAR文件。 - 在Flash Builder中,转到File > New > Project。
- 选择Android Project并单击Next。
- 将项目命名为HelloANENative。
- 标注项目位置(如果愿意,您也可以更改该位置)。
- 确保为您的构建目标选择了一个最新的Android SDK。如果没有看到您想要的目标,返回到前面的步骤以将Android SDK安装在Eclipse中,或者更新SDK以包含您想要的API和目标。本教程的剩余部分将假设您选择了Android 2.3.3或更新版本,但这应该不会影响下面的任何指令。
- 输入包名称com.<您的域>.example.android.helloANE。例如com.yourDomain.example.android.helloANE。
- 单击Finish。
- Flash Builder将为您创建一个HelloANENativeActivity.java文件。使用包资源管理器打开它。
- 在包资源管理器中右键单击HelloANENative项目,单击Properties。
- 单击Java Build Path,然后单击Libraries。
- 您现在必须添加Java API,以便连接ActionScript 3。单击Add External JARs。
- 找到并选择FlashRuntimeExtensions.jar文件(该文件的路径类似于:C:\...\Adobe Flash Builder 4.5\sdks\4.5.2\lib\android\)
- 单击OK解除项目属性对话框。
您还有一项项目配置任务:设置应用程序,以拥有使用设备的震动控件的权限。 - 打开AndroidManifest.xml文件。您应该看到Android Manifest Permissions屏幕。
- 单击Add并选择Uses Permission,然后单击OK。
- 在Attributes for Uses Permission下,选择android.permission.VIBRATE。
- 选择HelloANENative Manifest文件。
您已执行了这一步,所以如果您决定创建原生测试案例,您的原生代码将拥有运行所需的必要权限。尽管本教程没有介绍它,在继续编写ActionScript 3之前测试原生代码可能很有帮助——尤其是对于更高级的原生扩展。 什么是扩展上下文?现在您的Android项目已正确配置,您必须开始添加在ActionScript和您的原生Java代码之间建立桥梁的结构。这些结构中的第一个是一个扩展上下文。扩展上下文负责包含最多3个基于原生扩展的项目(另请参见Oliver Goldman的文章Extending Adobe AIR)): - 原生函数到ActionScript可饮用的名称的映射。这允许ActionScript代码调用特定的原生函数,是原生扩展的核心部分。
- 一个ActionScript对象的引用,它在原生代码与您的AIR应用程序之间共享。
- 原生代码结构的引用,它仅可从原生代码访问。
现在您的原生扩展可以拥有多个扩展上下文,您应该基于功能将它们分开。在本例中,您仅需要一个上下文,它将提供一个映射来访问Android震动功能。 创建一个震动扩展上下文接下来您将创建一个新VibrationExtensionContext类。 - 在包资源管理器中,右键单击src.com.yourDomain.example.android.helloANE包并选择New > Class。
- 将包设置为com.yourDomain.example.android.helloANE.extensions。
- 将名称设置为VibrationExtensionContext。
- 将超类设置为com.adobe.fre.FREContext。您可以使用Browse按钮选择此类。这是Adobe提供来使原生扩展桥生效的AIR Java API。
- 单击Finish创建新类。
您将看到已为您创建了两个函数:public void dispose()和public Map<String, FREFunction> getFunctions()。您可能已猜到,getFunctions()必须返回字符串(在您的ActionScript 3代码中引用和任何FREFunction类(您接下来将定义)之间的一个键值对映射。Adobe提供的API为您提供了以缩写词FRE(表示Flash 运行时扩展)开头的类和函数。
创建函数映射在您的原生扩展中定义函数的第一步是创建一个新Map用于返回。在getFunctions()类中,添加:
- @Override
- public Map<String,FREFunction> getFunctions()
- {
- Map<String, FREFunction> functionMap = new HashMap<String, FREFunction>();
- return functionMap;
- }
复制代码这创建一个空HashMap,但它如果是空,显然不是很有用。您将映射3个键值对,每个键值对将定义一个实现FREFunction接口的类: - functionMap.put("initMe", new VibrationInitFunction());
- functionMap.put("isSupported", new VibrationSupportedFunction());
- functionMap.put("vibrateMe", new VibrationVibrateFunction());
复制代码 三个函数中的第一个:VibrationInitFunction您已定义了三个函数。接下来,您将它们编写为实现FREFunction接口的类。您将从VibrationInitFunction开始,它被调用时将在您的VibrationExtensionContext中设置一个将在以后用于震动设备的类。 - 右键单击包资源管理器中的一个包,选择New > Class。
- 将包设置为 com.yourDomain.example.android.helloANE.extensions,将名称设置为VibrationInitFunction。
- 保留Superclass为一个java.lang.Object,向Interfaces框添加一个新条目:com.adobe.fre.FREFunction。
- 单击Finish。
请注意,你可以通过使用Eclipse的代码生成功能完成以上的步骤:点击你希望创建的类(本例中是VibrationInitFunction),敲击Ctrl –1打开代码提示窗口,然后选择 "创建VibrationInitFunction类 "。这样编辑器就可以自动帮你创建类代码了。 您将看到,已在您的VibrationInitFunction中为您定义了一个函数:call(),它接受两个参数:一个FREContext和一个 FREObject[]数组。默认情况下,这两个参数定义为arg0和arg1,但您可以为它们提供更具描述性的名称。将call()函数定义更改为类似以下形式:
- public FREObject call(FREContext context, FREObject[] passedArgs)
复制代码当调用此函数时,第一个参数将是您的VibrationExtensionContext的引用,第二个参数将是ActionScript 3代码传递的所有参数(如果有)的数组。这将对您的VibrationVibrateFunction很重要,它将基于该数组中的第一个参数设置持续时间。 现在,您的init函数将使用传入的FREContext对象来获取VibrationExtensionContext,然后获取它所属的 Android活动。使用此活动引用,它然后将能够检索名为Context.VIBRATOR_SERVICE的全局Android系统服务,该服务将允许您控制震动马达。您将此系统服务存储在您的VibrationExtensionContext中包含的一个新变量中,您稍后将创建它: - 在VibrationInitFunction的call()函数中,添加以下代码来从传入的FREContext获取VibrationExtensionContext:
- VibrationExtensionContext vbc = (VibrationExtensionContext)context;
复制代码
- 您现在可以使用VibrationExtensionContext getActivity()函数抓取活动。在FREContext类中包含此函数的目的是为了支持常见任务,比如您需要抓取上下文的活动,进而拥有我们需要的SystemService的路径。
- Activity a = vbc.getActivity();
复制代码
- 您现在可以调用a.getSystemService(),传入全局Context.VIBRATOR_SERVICE的引用。这将返回一个类型为 Vibrator的对象。您需要一个可用于整个扩展上下文的位置来存储此引用,所以将它放在一个位于VibrationExtensionContext 内的新变量vb中:
- vbc.vb = (Vibrator)a.getSystemService(Context.VIBRATOR_SERVICE);
复制代码
- 您现在应该打开VibrationExtensionContext类,向该类添加一个名为vb的公共变量:
- public Vibrator vb = null;
复制代码现在,您已创建了一个原生代码结构的引用vb Vibrator类,它可供可引用您的VibrationExtensionContext的任何类访问。 您完成的VibrationInitFunction看起来应该类似于:
- public class VibrationInitFunction implements FREFunction
- {
- @Override
- public FREObject call(FREContext context, FREObject[] passedArgs)
- {
- VibrationExtensionContext vbc = (VibrationExtensionContext)context;
- Activity a = vbc.getActivity();
- vbc.vb = (Vibrator)a.getSystemService(Context.VIBRATOR_SERVICE);
- return null;
- }
- }
复制代码您已学习了如何:创建一个实现FREFunction的类,理解从ActionSscript 3传入的参数,通过FREContext参数传入您的扩展上下文,而且您已看到扩展的一种常见的初始化任务。 接下来您必须实现在Map<String, FREFunction> getFunctions()函数中实现的其他两个FREFunction。 三个函数中的第二个:VibrationSupportedFunction您前面定义的第二个函数是VibrationSupportedFunction。您在getFunctions()返回的HashMap中已表明,此函数可使用ActionScript 3字符串isSupported调用。此函数的创建非常类似于VibrationInitFunction,但它将向您展示如何在一个FREObject 内返回一个布尔值。 - 右键单击包资源管理器中的一个包,单击New > Class。
- 选择com.yourDomain.example.android.helloANE.extensions作为包,将此类命名为VibrationSupportedFunction,正如前面的HashMap中提供的值所期望的。
- 选择FREFunction作为此类将实现的一个接口。
- 单击Finish创建该类。
- 将此类的参数分别从arg0和arg1更改为context和passedArgs。
- 您将希望返回一个FREObject作为call()函数中的结果,现在创建并返回该结果。您还想要您的VibrationExtensionContext的引用,所以通过转换上下文参数来创建它:
- FREObject result = null;
- VibrationExtensionContext vbc = (VibrationExtensionContext)context;
- // ...
- return result;
复制代码
- 此函数的逻辑将如下所示:
- VibrationInitFunction函数已调用,因此应该设置vbc.vc。
- vbc.vc是否非空?如果非空,结果应该为true。
- 如果vbc.vc为空,我们可以合理地推断初始化失败,以及此平台不支持震动。结果应该设置为false。
创建以下if语句:
- if (vbc.vb == null)
- {
- result = FREObject.newObject(false);
- }
- else
- {
- result = FREObject.newObject(true);
- }
复制代码
8.还有一项任务:在FREObject上调用newObject()可能导致抛出一个FREWrongThreadException异常。您会将您的if 语句放在一个try catch代码块中,以处理此不测事件。
您完成的call()函数现在看起来应该类似于:
- @Override
- public FREObject call(FREContext context, FREObject[] passedArgs)
- {
- FREObject result = null;
- VibrationExtensionContext vbc = (VibrationExtensionContext)context;
- try
- {
- if (vbc.vb == null)
- {
- // Not supported
- result = FREObject.newObject(false);
- }
- else
- {
- // Supported
- result = FREObject.newObject(true);
- }
- }
- catch (FREWrongThreadException fwte)
- {
- fwte.printStackTrace();
- }
- return result;
- }
复制代码您现在有了3个原生扩展函数中的第二个:VibrationSupportedFunction。当被ActionScript 3字符串isSupported调用时,此函数将检查VibrationExtensionContext"context"中的变量vb是否为非空。它将基于此条件返回值为true或false的FREObject,将捕获一个可能由FREObject的静态newObject()函数抛出的 FREWrongThreadException。 三个函数中的第三个:VibrationVibrateFunction您必须实现的最后一个原生扩展函数执行您的原生扩展的核心职责:它允许AIR应用程序震动设备的马达指定的持续时间。
- 在包资源管理器中,右键单击一个包并选择New > Class。
- 选择com.yourDomain.example.android.helloANE.extensions作为包,将类命名为VibrationVibrateFunction。
- 将类实现命名为com.adobe.fre.FREFunction。
- 单击Finish创建该类。
- 在函数定义中,将arg0重命名为context,将arg1重命名为passedArgs。
- 创建一个名为result的空FREObject。
- 将上下文变量转换一个名为code>vbc的VibrationExtensionContext变量。您将使用此变量访问Vibrator对象vbc.vb。
我们现在已准备好访问第一个传入的参数FREObject,尝试将它设置为一个整数。如果数据格式奇怪,可能会抛出一个异常并且您将获取该异常。您的call()函数现在看起来应该类似于:
- @Override
- public FREObject call(FREContext context, FREObject[] passedArgs)
- {
- FREObject result = null;
- VibrationExtensionContext vbc = (VibrationExtensionContext)context;
- try
- {
- // Vibrate the device
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- return result;
- }
复制代码 8.在try { // ... }代码块内,我们将尝试抓取passedArgs数组中的第一个元素作为FREObject:
- FREObject fro = passedArgs[0];
复制代码 9.我们现在可以在这个FREObject上调用getAsInt();来创建一个int:
- int duration = fro.getAsInt();
复制代码 10.最后,在我们的vb Vibrator变量上调用Android原生震动函数,传入持续时间:
- vbc.vb.vibrate(duration);
复制代码您现在已成功创建了3个原生函数,将它们映射到了getFunctions()提供的HashMap中的字符串,创建执行您的原生扩展所需的所有操作所必要的原生逻辑。这样就完成了VibrationExtensionContext的创建,它是您的原生扩展需要的唯一的扩展上下文。 创建主要扩展类您已创建了您的原生扩展需要的一个且是唯一一个扩展上下文,但您还未创建我们的扩展的主要类。幸运的是,添加此类很简单,我们所需做的就是创建一个名为VibrationExtension的类,它实现FREExtension接口。 FREExtesion接口定义initialize、dispose和createContext函数,它们允许挂钩到一个原生扩展的生命周期中。尽管为我们提供了3个函数,我们仅需要自定义一个:createContext函数。此函数必须返回一个FREContext。幸运的是,您已创建了您自己的 VibrationExtensionContext,可以简单地返回此类的一个实例。
|