[AIR] AIR 应用程序的调用和终止
本节讨论几种对已安装的 Adobe® AIR® 应用程序进行调用的方法,以及关闭运行中的应用程序的选项和注意事项。
有关调用和终止 AIR 应用程序的快速介绍和代码示例,请参阅 Adobe Developer Connection 上的以下快速入门文章:
应用程序调用
在用户(或操作系统)执行以下操作时,将调用 AIR 应用程序:
从桌面解释程序启动该应用程序。
使用该应用程序作为命令行解释程序中的命令。
打开某类型文件而该应用程序是此类型文件的默认打开程序。
(Mac OS X) 单击停靠任务栏中的该应用程序图标(无论应用程序当前是否正在运行)。
选择从安装程序启动该应用程序(在新安装过程结束时,或者在双击已安装应用程序的 AIR 文件之后)。
当已安装版本指示其自身正在处理应用程序更新(通过在应用程序描述符文件中加入<customUpdateUI>true</customUpdateUI>声明)时,开始更新 AIR 应用程序。
(iOS) 从 Apple 推送通知服务 (APNs) 接收通知。
通过 URL 调用应用程序。
访问承载了将调用com.adobe.air.AIR launchApplication()方法(该方法可为 AIR 应用程序指定识别信息)的 Flash 标志或应用程序的网页。(要使浏览器调用成功,应用程序描述符还必须包含<allowBrowserInvocation>true</allowBrowserInvocation>声明。)
每当调用 AIR 应用程序时,AIR 都会通过单一 NativeApplication 对象调度类型为invoke的 InvokeEvent 对象。若要给应用程序留出时间来初始化自身并注册事件侦听器,将对invoke事件进行排队而非将其丢弃。一旦侦听器已注册,就会传送所有排队的事件。
若要接收invoke事件,请调用 NativeApplication 对象 (NativeApplication.nativeApplication)的addEventListener()方法。当某个事件侦听器为invoke事件进行注册后,该事件侦听器还会接收到在注册前发生的所有invoke事件。在对addEventListener()的调用返回后不久,将以短时间间隔一次调度一个排队的invoke事件。如果在此过程中发生了新的invoke事件,则可能会在一个或多个排队的事件之前调度该事件。通过该事件队列可处理在初始化代码执行之前发生的任何invoke事件。请记住,如果在执行后期(在应用程序初始化之后)添加一个事件侦听器,该事件侦听器仍将会接收自应用程序启动以来发生的所有invoke事件。
仅启动 AIR 应用程序的一个实例。当再次调用某个已经运行的应用程序时,AIR 将向该正在运行的实例调度一个新的invoke事件。AIR 应用程序负责响应invoke事件并采取适当的动作(例如,打开一个新的文档窗口)。
InvokeEvent对象包含任何传递给该应用程序的参数,以及已从中调用该应用程序的目录。如果该应用程序是由于文件类型关联而被调用,则文件的完整路径将包含在命令行参数中。同样,如果该应用程序是由于某个应用程序升级而被调用,则会提供升级 AIR 文件的完整路径。
当在一次操作中打开多个文件时,在 Mac OS X 中将调度一个 InvokeEvent 对象。每个文件都包括在arguments数组中。 在 Windows 和 Linux 中将为每个文件调度一个单独的 InvokeEvent 对象。
应用程序可通过以下方法处理invoke事件:即向其 NativeApplication 对象注册侦听器,
NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvokeEvent);
然后定义事件侦听器:
var arguments:Array;
var currentDir:File;
public function onInvokeEvent(invocation:InvokeEvent):void {
arguments = invocation.arguments;
currentDir = invocation.currentDirectory;
}
捕获命令行参数
与 AIR 应用程序调用关联的命令行参数是在由 NativeApplication 对象调度的 InvokeEvent 对象中进行传送的。InvokeEventarguments属性包含在调用 AIR 应用程序时由操作系统传递的参数数组。如果这些参数包含相对文件路径,则通常可以使用currentDirectory属性来解析路径。
除非用双引号引起来,否则传递给 AIR 程序的参数会视为以空白分隔的字符串:
参数 |
Array |
tick tock |
{tick,tock} |
tick "tick tock" |
{tick,tick tock} |
"tick" “tock” |
{tick,tock} |
\"tick\" \"tock\" |
{"tick","tock"} |
InvokeEvent 对象的currentDirectory属性包含一个表示应用程序启动时所在目录的 File 对象。
如果调用某应用程序是由于要打开该应用程序所注册类型的文件,则该文件的本机路径将以字符串的形式包含在命令行参数中。(您的应用程序负责打开该文件或对其执行预定操作。)同样,如果已对应用程序进行编程使其能实现自我更新(而非依赖于标准 AIR 更新用户界面),则当用户双击某个 AIR 文件(该文件包含具有匹配应用程序 ID 的应用程序)时,将会包含该 AIR 文件的本机路径。
使用currentDirectoryFile 对象的resolve()方法可访问该文件:
if((invokeEvent.currentDirectory != null)&&(invokeEvent.arguments.length > 0)){
dir = invokeEvent.currentDirectory;
fileToOpen = dir.resolvePath(invokeEvent.arguments[0]);
}
此外,还应验证参数是否的确是文件的路径。
示例:调用事件日志
下面的示例演示如何为invoke事件注册侦听器以及如何处理该事件。该示例会记录所有接收到的调用事件并显示当前目录和命令行参数。
ActionScript 示例
package
{
import flash.display.Sprite;
import flash.events.InvokeEvent;
import flash.desktop.NativeApplication;
import flash.text.TextField; public class InvokeEventLogExample extends Sprite
{
public var log:TextField; public function InvokeEventLogExample()
{
log = new TextField();
log.x = 15;
log.y = 15;
log.width = 520;
log.height = 370;
log.background = true; addChild(log); NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onInvoke);
} public function onInvoke(invokeEvent:InvokeEvent):void
{
var now:String = new Date().toTimeString();
logEvent("Invoke event received: " + now); if (invokeEvent.currentDirectory != null)
{
logEvent("Current directory=" + invokeEvent.currentDirectory.nativePath);
}
else
{
logEvent("--no directory information available--");
} if (invokeEvent.arguments.length > 0)
{
logEvent("Arguments: " + invokeEvent.arguments.toString());
}
else
{
logEvent("--no arguments--");
}
} public function logEvent(entry:String):void
{
log.appendText(entry + "\n");
trace(entry);
}
}
}
Flex 示例
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical"
invoke="onInvoke(event)" title="Invocation Event Log">
<mx:Script>
<![CDATA[
import flash.events.InvokeEvent;
import flash.desktop.NativeApplication; public function onInvoke(invokeEvent:InvokeEvent):void {
var now:String = new Date().toTimeString();
logEvent("Invoke event received: " + now); if (invokeEvent.currentDirectory != null){
logEvent("Current directory=" + invokeEvent.currentDirectory.nativePath);
} else {
logEvent("--no directory information available--");
} if (invokeEvent.arguments.length > 0){
logEvent("Arguments: " + invokeEvent.arguments.toString());
} else {
logEvent("--no arguments--");
}
} public function logEvent(entry:String):void {
log.text += entry + "\n";
trace(entry);
}
]]>
</mx:Script>
<mx:TextArea id="log" width="100%" height="100%" editable="false"
valueCommit="log.verticalScrollPosition=log.textHeight;"/>
</mx:WindowedApplication>
用户登录时调用 AIR 应用程序
通过将 NativeApplicationstartAtLogin属性设置为true,可以将 AIR 应用程序设置为在当前用户登录时自动启动。设置后,每当该用户登录时该应用程序都将自动启动。除非该设置更改为false、用户通过操作系统手动更改该设置或者卸载了该应用程序,否则该应用程序将始终在登录时启动。登录时启动是一种运行时设置。该设置仅适用于当前用户。必须安装该应用程序以将startAtLogin属性成功设置为true。如果该属性是在未安装应用程序时设置的,则会引发错误(例如,通过 ADL 启动该应用程序时)。
若要确定应用程序是自动启动还是用户操作的结果,可以检查 InvokeEvent 对象的reason属性。如果该属性的值等于InvokeEventReason.LOGIN,则应用程序为自动启动。对于其他调用路径,reason属性设置如下:
InvokeEventReason.NOTIFICATION(仅限 iOS)— 已通过 APNs 调用应用程序。有关 APNs 的详细信息,请参阅使用推送通知。
InvokeEventReason.OPEN_URL— 该应用程序已被其他应用程序或系统调用。
InvokeEventReason.Standard— 所有其他情况。
要访问reason属性,您的应用程序必须面向 AIR 1.5.1 或更高版本(通过在应用程序描述符文件中设置正确命名空间值)。
以下简化的应用程序利用 InvokeEvent reason 属性来确定在发生 invoke 事件时如何响应。如果 reason 属性为“login”,则应用程序仍在后台运行。否则,它将显示主要应用程序。采用此方式的应用程序通常在登录时启动(从而可以执行后台处理或事件监控),并打开窗口以响应用户触发的 invoke 事件。
package {
import flash.desktop.InvokeEventReason;
import flash.desktop.NativeApplication;
import flash.display.Sprite;
import flash.events.InvokeEvent; public class StartAtLogin extends Sprite
{
public function StartAtLogin()
{
try
{
NativeApplication.nativeApplication.startAtLogin = true;
}
catch ( e:Error )
{
trace( "Cannot set startAtLogin:" + e.message );
} NativeApplication.nativeApplication.addEventListener( InvokeEvent.INVOKE, onInvoke );
} private function onInvoke( event:InvokeEvent ):void
{
if( event.reason == InvokeEventReason.LOGIN )
{
//do background processing...
trace( "Running in background..." );
}
else
{
this.stage.nativeWindow.activate();
}
}
}
}
从浏览器调用 AIR 应用程序
使用浏览器调用功能,网站可启动要从浏览器启动的已安装 AIR 应用程序。仅在应用程序描述符文件将allowBrowserInvocation设置为true时,才允许浏览器调用:
<allowBrowserInvocation>true</allowBrowserInvocation>
当该应用程序通过浏览器调用时,该应用程序的 NativeApplication 对象将会调度 BrowserInvokeEvent 对象。
若要接收 BrowserInvokeEvent 事件,请在 AIR 应用程序中调用 NativeApplication 对象 (NativeApplication.nativeApplication) 的addEventListener()方法。当某个事件侦听器针对 BrowserInvokeEvent 事件进行注册时,该事件侦听器还将接收在注册前发生的所有 BrowserInvokeEvent 事件。在对addEventListener()的调用返回后将调度这些事件,但并不一定会在注册后可能接收到的其他 BrowserInvokeEvent 事件之前调度。这样就可处理在初始化代码执行之前(如从浏览器首次调用应用程序时)已发生的 BrowserInvokeEvent 事件。请记住,如果在执行后期(在应用程序初始化之后)添加一个事件侦听器,它仍然会接收到自应用程序启动以来发生的所有 BrowserInvokeEvent 事件。
BrowserInvokeEvent 对象包含以下属性:
属性 |
说明 |
---|---|
arguments |
要传递给应用程序的参数(字符串)数组。 |
isHTTPS |
浏览器中的内容是否使用 https URL 方案。如果是,则为 (true,否则为 (false)。 |
isUserEvent |
浏览器调用是否生成用户事件(如鼠标单击)。在 AIR 1.0 中,它始终设置为true;AIR 需要与浏览器调用功能有关的用户事件。 |
sandboxType |
浏览器中内容的沙箱类型。定义的有效值与可用于Security.sandboxType属性的值相同,可以是以下值之一:
|
securityDomain |
浏览器中的内容的安全域,如"www.adobe.com"或"www.example.org"。仅对于远程安全沙箱中的内容(来自网络域的内容)设置此属性,而不对位于本地或应用程序安全沙箱中的内容设置此属性。 |
如果使用浏览器调用功能,请务必考虑安全性问题。网站启动 AIR 应用程序时,它可通过 BrowserInvokeEvent 对象的arguments属性发送数据。请在任何敏感操作(例如文件或代码加载 API)中谨慎使用此数据。风险级别取决于应用程序处理数据的方式。如果只希望某个特定网站调用该应用程序,则该应用程序应检查 BrowserInvokeEvent 对象的securityDomain属性。也可以要求调用该应用程序的网站使用 HTTPS,这样就可通过检查 BrowserInvokeEvent 对象的isHTTPS属性进行验证。
应用程序应验证传入的数据。例如,如果某个应用程序要求传入指向某个特定域的 URL,则该应用程序应验证 URL 确实指向该域。这样就能够阻止攻击者欺骗该应用程序向其发送敏感数据。
任何应用程序都不应使用可能指向本地资源的 BrowserInvokeEvent 参数。例如,应用程序不应基于从浏览器传递的路径创建 File 对象。如果从浏览器传递的将是远程路径,则该应用程序应确保路径不使用file://协议替代远程协议。
应用程序终止
终止应用程序最快的方法是调用 NativeApplication exit() 方法。在应用程序没有要保存的数据或没有要清理的外部资源时,此方法非常适用。调用exit()将关闭所有窗口,然后终止该应用程序。但是,若要允许窗口或应用程序的其他组件中断该终止进程(也许要保存重要数据),请在调用exit()之前调度适当的警告事件。
另一种妥善关闭应用程序的方法是提供单一执行路径,而不考虑关闭进程的启动方式。用户(或操作系统)可以通过以下方式触发应用程序终止:
在NativeApplication.nativeApplication.autoExit为true的情况下关闭最后一个应用程序窗口。
从操作系统中选择应用程序退出命令;例如,用户从默认菜单中选择退出应用程序命令。(这种情况仅适用于 Mac OS;Windows 和 Linux 并不通过系统镶边提供应用程序退出命令。)
关闭计算机。
当采用上述方式之一通过操作系统执行退出命令时,NativeApplication 将调度exiting事件。如果没有侦听器取消exiting事件,则任何打开的窗口都将关闭。每个窗口都会先调度一个closing事件,然后调度一个close事件。如果任何窗口取消closing事件,则关闭进程将会停止。
如果需要考虑应用程序的窗口关闭顺序,则可侦听来自 NativeApplication 的exiting事件并自行决定以适当的顺序关闭窗口。例如,如果您拥有带有工具调色板的文档窗口,则可能需要运用此方法。如果系统关闭了调色板而用户却决定取消退出命令以保存某些数据,这可能会带来不便,甚至更糟糕的情形。在 Windows 中,收到exiting事件的唯一时间是在关闭最后一个窗口之后(当 NativeApplication 对象的autoExit属性设置为true时)。
若要在所有平台上提供一致的行为,而不考虑退出顺序是通过操作系统镶边、菜单命令还是通过应用程序逻辑启动的,请遵守用于退出应用程序的以下良好做法:
1. 始终先通过 NativeApplication 对象调度exiting事件,然后再调用应用程序代码中的exit()并检查应用程序的其他组件是否没有取消该事件。
public function applicationExit():void {
var exitingEvent:Event = new Event(Event.EXITING, false, true);
NativeApplication.nativeApplication.dispatchEvent(exitingEvent);
if (!exitingEvent.isDefaultPrevented()) {
NativeApplication.nativeApplication.exit();
}
}
2. 侦听来自NativeApplication.nativeApplication对象的应用程序exiting事件,并在处理函数中关闭任何窗口(首先调度closing事件)。在所有窗口都已关闭后执行任何所需的清理任务,例如保存应用程序数据或删除临时文件。在清理期间仅使用同步方法以确保在应用程序退出之前能完成清理任务。
如果窗口关闭的顺序无关紧要,则可以遍历NativeApplication.nativeApplication.openedWindows数组并依次关闭每个窗口。如果顺序的确 很重要,则需提供一种以正确顺序关闭窗口的方法。
private function onExiting(exitingEvent:Event):void {
var winClosingEvent:Event;
for each (var win:NativeWindow in NativeApplication.nativeApplication.openedWindows) {
winClosingEvent = new Event(Event.CLOSING,false,true);
win.dispatchEvent(winClosingEvent);
if (!winClosingEvent.isDefaultPrevented()) {
win.close();
} else {
exitingEvent.preventDefault();
}
} if (!exitingEvent.isDefaultPrevented()) {
//perform cleanup
}
}
3. Windows 应始终通过侦听自己的closing事件来处理自己的清理任务。
4. 在应用程序中仅使用一个exiting侦听器,因为调用时间较早的处理函数无法知道随后的处理函数是否将取消exiting事件(依赖于执行顺序将是不明智的做法)。
[AIR] AIR 应用程序的调用和终止的更多相关文章
- GO学习-(37) 使用Air实现Go程序实时热重载
使用Air实现Go程序实时热重载 今天我们要介绍一个神器--Air能够实时监听项目的代码文件,在代码发生变更之后自动重新编译并执行,大大提高gin框架项目的开发效率. 为什么需要实时加载? 之前使用P ...
- 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案
方案特点: 在网页程序或Java程序中调用接口实现短信猫收发短信的解决方案,简化软件开发流程,减少各应用系统相同模块的重复开发工作,提高系统稳定性和可靠性. 基于HTTP协议的开发接口 使用特点在网页 ...
- iOS程序中调用系统自带应用(短信,邮件,浏览器,地图,appstore,拨打电话,iTunes,iBooks )
在网上找到了下在记录下来以后方便用 在程序中调用系统自带的应用,比如我进入程序的时候,希望直接调用safar来打开一个网页,下面是一个简单的使用:
- Asp反向代理程序,调用远程站点全站数据,一款脚本级反向代理程序.
前些天临时写的一脚本级反向代理程序,用法很简单,设置好目标站地址,然后放到你网站根目录:index.asp,再将404页面自定义为:index.asp,即可. 由于暂时没有 url 替换需要,所以没有 ...
- Java程序中调用Python脚本的方法
在程序开发中,有时候需要Java程序中调用相关Python脚本,以下内容记录了先关步骤和可能出现问题的解决办法. 1.在Eclipse中新建Maven工程: 2.pom.xml文件中添加如下依赖包之后 ...
- Unity开发Android应用程序:调用安卓应用程序功能
开发环境: Eclipse3.4 + adt12 + jdk6 + AndroidSDK2.2 Unity3.4 + windows7 测试设备: HTC Desire HD 本文要涉及到的几个重点问 ...
- 发布在IIS上的Web程序,调用服务器的COM组件
场景大致是这样的,在工厂中分布着许多的PDA点,这些PDA点都要进行实时的扫描--打印操作.实现方法是采用网络打印机,然后服务器安装驱动,管理着所有的打印机.然后服务器,发布一个WebService, ...
- Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)
文章目录: 1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Ap ...
- 存储过程系列之存储过程sql数据库调用和程序代码调用
1.存储过程,无参数的存储过程 创建无参数存储存储过程 Create Procedure DCEMREMR_TEMPLATEAs SELECT TOP 10 [FILENAME],[FILETITLE ...
随机推荐
- C - 搜索
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status Descr ...
- C++学习笔记31:术语翻译
reference:引用 dereference:引领,好于"解引用" type:型式,好于"类型" int:整数型式,简称整型 class:类型式,简称类型 ...
- 《一个 Go 程序系统线程暴涨的问题》结论
原文地址:https://zhuanlan.zhihu.com/p/22474724 作者的结论没写好,我来说两句.. 结论: Docker swarm自己有个函数,叫setTcpUserTimeou ...
- Xamarin Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy
Android.Views.WindowManagerBadTokenException: Unable to add window -- token android.os.BinderProxy@ ...
- scrollView中可以自由滚动的listview
直接在scrollView中写listview等可滚动控件会出现子控件高度计算的问题,为了解决这个问题,找到的方案是重写listview中的onmeasure方法: @Override public ...
- web安全之xss
xss:跨站脚本攻击,攻击者,把一段恶意代码镶嵌到web页面,,用户浏览页面时,嵌入页面的恶意代码就会执行,从而到达攻击用户的目的. 重点在于脚本,javascript和actionscript ...
- 学习 Local Sensitive Hash
1. 最近邻法的应用 1.1 Jaccard 相似集 如何定义相似:即相关属性交集的大小,越大则越相似.我们给相似一个数学上的定义:Jaccard 相似集. 集合 \(S\) 与集合 \(T\) 的 ...
- odoo-10.0 create database 失败
在初始化数据库的界面点击[create database] create database 失败 报错如下 2017-01-05 20:15:18,529 4652 INFO ? werkzeug: ...
- 关于CSS初步入门简述1
关于CSS的简介可以自行百度,本篇只考虑内容 首先关于CSS会由浅入深,写在前面的有很多不严谨,只是为了引出后文所写.不过如果谬误较大,敬请指正! 1.大部分的代码要写在之中 简单的例子: <b ...
- LINUX测试环境部署manggo(六)
安装配置manggo 复制安装包mongodb-linux-x86_64-2.6.5.tgz到/usr/local/目录下,或者如果有网络可以直接使用wget命令下载安装包到/usr/local目录下 ...