adobe air.dll没有被指定在windows上运行怎么解决

重新安装了一次显卡驱动,好了之后却发现打开不少软件都弹出一个错误,提示:“c:windowssystem32aticfx32.dll 没有被指定在windows上运行,或者它包含错误。请尝试使用原始安装媒体重新安装程序,或联系您的系统管理员或软件供应商以获取支持。” 这个该如何解决呢?方法其实很简单: 1、下载文件aticfx32.dll,版本号为8.17.10.8; 下载地址:/share/link?shareid=&uk=2
问题描述:在安装新版本的adobe air时,碰到问题,提示“安装 Adobe AIR 时出错。管理员可能不允许安装此软件。请与管理员联系。”,想到控制面板把老版本的卸载了再来装,结果air卸载也卸载不掉。在网上查来查去,结果发现是电脑的windows installer 服务没启动,就到电脑管理中去启动windows installer服务,结果windows installer 也无法启动。 解决办法:使用记事本编写installer.reg文件,内容如下: Windows Re
Air是Adobe公司出品的跨操作系统的运行时库,通过它开发者可利用现有的Web开发技术(Flash,Flex,HTML,Javas cript,Ajax)来构建富Internet应用程序并部署为桌面应用程序。很久前我装了Adobe AIR,因为Flash应用程序是用这个带起来的,相当于一个支持库一样的东西。 看到有新版3.5了,于是打算更新下,但是非常苦逼,更新安装还有卸载的时候都提示: “卸载 Adobe AIR 时出错。管理员可能不允许卸载此软件。请与管理员联系。” 很郁闷
其实通俗的讲Adobe Air就是一个平台,这个平台提供一些软件接口,想开发软件的人员用这些接口和其他的编程技术可以开发出来一些软件,而这些开发出来的软件只有在安装有Adobe Air的电脑上可以运行。你看看你电脑上有没有必须依靠Adobe Air才能运行的软件,如果没有,可以卸掉他,现在基于Adobe Air的软件不是很多,一般有的也可以找其他软件代替的。 我们再来看看一般的专业解释: Adobe Integrated Runtime (AIR) 是一个跨操作系统的运行时,利用现有的Web开发
Adobe Integrated Runtime (AIR) 是一个跨操作系统的运行时,利用现有的Web开发技术(Flash,Flex,HTML,JavaScript,Ajax)来构建富Internet应用程序并部署为桌面应用程序。 AIR 支持现有的Web技术如Flash,Flex,HTML,JavaScript和AJAX,可以用你最熟练的技术来开发您所见过的最具用户体验的RIA程序,例如,一个AIR程序可以使用如下一种或多种组合技术构建: Flash / Flex / Actio
Adobe AIR是什么? 这是Adobe开发的一个平台软件,是针对网络与桌面应用的结合所开发出来的技术,可以不必经由浏览器而对网络上的云端程式做控制。如果你安装AIR的软件,比如新浪微博AIR,就必须安装Adobe AIR,所有AIR软件都是基于Adobe AIR的。最大的有点就是它的跨平台,涵盖各个主流系统啊。
解决办法一: 开始——运行——msconfig——启动——把加载项***.dll的那个勾去掉,重启电脑,通常到这就可以了,如果还弹出来再进行第二步。 (03) 解决办法二: 开始——运行——regedit,在下面的位置删除相应键值: HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Run HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersio
CnsMin.DLL文件是安装了网络实名插件后,Windows系统目录中添加的一个文件。 出现问题的原因可能是由于该文件的丢失或者损坏导致,而电脑启动的时候,这个插件会自动启动,所以会出现这样的问题。 解决方法:可以重新安装这个实名插件或者点击电脑左下角的开始,然后选择运行选项,在弹出的窗口中输入“msconfig”命令并回车,之后在启动选项中将“CnsMin”禁止即可。
大家都认为Linux 默认是安全的,我大体是认可的(这是个有争议的话题)。Linux默认确实有内置的安全模型。你需要打开它并且对其进行定制,这样才能得到更安全的系统。Linux更难管理,不过相应也更灵活,有更多的配置选项。 对于系统管理员而言,让产品的系统更安全,免于骇客和黑客的攻击,一直是一项挑战。本文将介绍25个有用的技巧和窍门 ,帮助你让Linux系统更加安全。希望下面的这些技巧和窍门可以帮助你加强你的系统的安全。 1. 物理系统的安全性 配置BIOS,禁用从CD/DVD、外部设备、软驱启
1、 IPCONFIG ipconfig 实用程序和它的等价图形用户界面——windows 95/98 中的winipcfg 可用于显示当前的tcp/ip配置的设置值。这些信息一般用来检验人工配置的tcp/ip设置是否正确。但是,如果你的计算机和所在的局域网使用了动态主机配置协议(dynamic hostconfiguration protocol,dhcp——windows nt 下的一种把较少的ip 地址分配给较多主机使用的协议,类似于拨号上网的动态ip分配),这个程序所显示的信息也
图1:ZaReason的MediaBox。 几乎任何Linux都能成为出色的媒体服务器系统,因为它占用资源少、运行又稳定,所以你可以使用自己最熟悉的任何一个版本的Linux。任何Ubuntu变种版本(Ubuntu、Xubuntu和Lubuntu等)都特别适合作为媒体服务器系统,因为它们让用户很容易获得限制的编解码器。我在一个ZaReason MediaBox系统上运行Xubuntu。这个简单的系统可用于播放电影和音乐。它不是数字录像机(DVR),它也不需要电视调谐器,因为我没有任何广播电视。不需
回顾今年初的CES 2013电子大展,我们似乎很难记起都有什么新产品发布,基本上就是一堆产品混在一起,缺乏令人印象深刻的部分。而笔记本产品则更为严重,在展会中放眼望去,只是一堆外形相似、售价1000美元以上的Windows 8超极本。 而在这种混乱的情况下,联想ThinkPad Helix可以称得上是鹤立鸡群。这款采用了平板/笔记本二合一混合式设计的产品,在通常状况下是一款平板,而安装到附带电池的键盘底座后,又变成了一款超极本。当然,它拥有较高的硬件配置,并运行完整版的Windows 8
在5月5日,Windows 7 RC最终开放官方公众下载。而这被上传至BT网络中都有超过一个星期了,MSDN和订阅了TechNet的开发者们在先 前早上也已经允许下载。但这些群体构成的用户就是第一时间看到Windows 7 RC发布的那一少部分人。对于早前放弃下载和苦苦等待的人来说,这无疑 是个好消息。与 此同时,我已经收集了安装Windows 7的一些好与坏的信息。在过去的一周里我已经在多种不同的系统中安装并升级了RC——笔记本和台式机,有些附带 了兼容的触摸屏板,有些则无;有些附带了电视
大家都认为Linux 默认是安全的,我大体是认可的(这是个有争议的话题)。Linux默认确实有内置的安全模型。你需要打开它并且对其进行定制,这样才能得到更安全的系统。Linux更难管理,不过相应也更灵活,有更多的配置选项。 对于系统管理员而言,让产品的系统更安全,免于骇客和黑客的攻击,一直是一项挑战。本文将介绍25个有用的技巧和窍门 ,帮助你让Linux系统更加安全。希望下面的这些技巧和窍门可以帮助你加强你的系统的安全。 1. 物理系统的安全性 配置BIOS,禁用从CD/DVD、
大家都认为Linux 默认是安全的,我大体是认可的(这是个有争议的话题)。Linux默认确实有内置的安全模型。你需要打开它并且对其进行定制,这样才能得到更安全的系统。Linux更难管理,不过相应也更灵活,有更多的配置选项。 对于系统管理员而言,让产品的系统更安全,免于骇客和黑客的攻击,一直是一项挑战。本文将介绍25个有用的技巧和窍门 ,帮助你让Linux系统更加安全。希望下面的这些技巧和窍门可以帮助你加强你的系统的安全。 1. 物理系统的安全性 配置BIOS,禁用从CD/DVD、外部设备、软驱启
64位的Windows并不是简单地把所有东西都编译成64位就万事大吉的。关于64位的CPU应该做成什么样子,Intel和AMD曾有各自的打算。AMD的回答直接了当:新的64位处理器,应该能在提高更高处理能力的同时,保持对32位应用程序的兼容性。而Intel则希望借此机会,把下一代的处理器,设计得更完美。于是,就有了AMD的x86-64(后被称为amd64)的处理器和Intel的IA-64(安腾)处理器。和amd64不一样的是,安腾处理器并没有很好地提供对32位应用程序的支持。具体信息,读者在网上
Ping概述: Ping 是Windows系列自带的一个可执行命令。利用它可以检查网络是否能够连通,可以很好地帮助我们分析判定网络故障。该命令只有在安装了 TCP/IP 协议后才可以使用。Ping命令的主要作用是通过发送数据包并接收应答信息来检测两台计算机之间的网络是否连通。当网络出现故障的时候,可以用这个命令来预测故障和确定故障地点。Ping命令成功只是说明当前主机与目的主机之间存在一条连通的路径。如果不成功,则考虑:网线是否连通、网卡设置是否正确、IP地址是否可用等。 需要注意的是:成功地与
在Adobe中国官方宣布5月19号正式发布中文版时,在韩国某网站上出现了亚区版本下载,下载地址来自Adobe官方。包含简繁韩三语,大师版无一例外也出现了简繁韩三语下载。最主要的是下载速度超快!!请使用迅雷等下载软件下载!注意,一个是运行程序,一个是压缩包,两个都要下! 先放几个常用的: Adobe Photoshop CS5 http://trials2./AdobeProducts/PHSP/12/win32/Photoshop_12_LS3.exe http:/
更轻、更薄、更快…… 有两类企业常年乐此不疲地这么形容自己的新产品,一类是卫生巾,另一类是苹果。 10月17日凌晨,苹果公司在加州总部召开新品发布会,推出iPad Air 2、iPad mini 3及新iMac一体机。iPad Air 2相对上代更轻薄并加入指纹识别,而新iMac则采用5K分辨率屏幕。 没有太多改变的,则是iPad mini 3,这款在此次发布会上只花了约29秒就一笔带过的产品,前代iPad mini2在2013年销量曾高达4000万。但是Piper Jaffray公司分析师Ge
Nexus向来是Android平台发展的标杆,协调和拉动OEM厂商快速发展。自首款Nexus One设备之后HTC再度与谷歌携手共同推出了Nexus 9平板设备,无论定位还是规格都将对苹果iPad产生巨大冲击,下面让我们以规格参数的方式来对比这两款设备。 尺寸: HTC和谷歌无疑尝试在mini版本和全尺寸版本之间找到了平衡点,Nexus 9在尺寸比较适中。相比较而言要比iPad Air 2短5%,窄9%。 在厚度方面iPad Air 2得到进一步压缩,厚度仅仅只有6.1mm,相比较Nexus 9您所在的位置:
&Adobe AIR(AIR运行库)18.0.0.96简体中文版
Adobe AIR(AIR运行库)18.0.0.96简体中文版
Adobe AIR(AIR运行库)软件介绍
点击查看大图
  adobe air(Adobe Integrated Runtime)(AIR运行库)是一个跨操作系统的运行时,利用现有的Web开发技术(Flash、Flex、HTML、JavaScript、Ajax)来构建富Internet应用程序并部署为桌面应用程序。adobe air支持现有的Web技术如Flash,Flex,HTML,JavaScript和AJAX,可以用你最熟练的技术来开发您所见过的最具用户体验的RIA程序。 &adobe air (AIR运行库)应用程序可以是: &&& * 基于Flash 或 Flex:应用程序根内容(理解为容器)为Flash/Flex (SWF) &&& * 基于Flash 或 Flex 的HTML 或 PDF。应用程序的根内容为基于Flash/Flex (SWF) 的HTML&&& * 基于HTML,应用程序根内容为HTML,JS,CSS &&& * 基于HTML的Flash/Flex或PDF,应用程序根内容为基于HTML 的Flash/Flex (SWF) 或 PDF
Adobe AIR(AIR运行库)下载地址
系统软件小分类
1323399次下载
42703次下载
322804次下载
15213次下载
35121次下载
28283次下载
230311次下载
51326次下载
275832次下载
25643次下载
1323399次下载
792329次下载
559627次下载
494645次下载
428184次下载
425326次下载
419931次下载
419480次下载
333004次下载
323909次下载
热门关键字
微信扫一扫关注下载吧公共帐号专业的QQ下载站 本站非腾讯QQ官方网站
官方网址:
adobe air下载15.0.0.289 官方版
软件大小:17.8M
软件语言:中文
更新时间:
软件类别:免费/常用软件
软件性质:PC软件
软件厂商:
运行环境:WinAll
软件等级:
本类热门软件
软件简介软件截图相关软件相关文章
Adobe AIR 是air应用程序运行时环境,安装后可以在Android平台上运行air应用。它是一款独立的客户端应用软件,可在不受浏览器的限制下独立运行Flash程序。!最为便捷的是用户无需安装APK在手机上就可立刻运行相应的AIR
更新:14-10-29&&大小:15.0MM&&类别:其他软件
评分:10.0
国外一种老牌的聚合聊天软件最近异常火热,它叫Miranda IM. 通过安装丰富的插件可以令Miranda IM (下简称为MIM)
支持例如QQ、ICQ、AIM、MSN、Jabber (gtalk使用的协议) 、Yahoo、Gadu-Gadu、Netsend以及其他一些聊天
更新:13-09-12&&大小:3.6MM&&类别:网络聊天
V3.30 快乐无极版QQ 是快乐无极QQ2008系列最后的一个版本。如无特殊情况不会再发布有关于2008的版本。有什么问题都可以进入快乐无极论坛进行讨论,如果问题普遍存在将会以升级补丁的形式解决。
更新:09-01-22&&大小:23.6MM&&类别:QQ下载
=======================================================
特别声明:
腾讯QQ版权归深圳市腾讯计算机系统有限公司所有,
本版只为方便用户使用之辅助性工具,请勿用于非法用途!
==============================
更新:08-12-23&&大小:17.5MM&&类别:QQ下载
全新的好友操作体验&
&更丰富的好友状态展示,手机在线一目了然;更多的好友操作展示,尽在一键式操作中完成。
便捷的聊天信息提取&
&重要的信息绝对不会遗漏,便捷的提取QQ消息中的电话或其
更新:08-06-20&&大小:462KBM&&类别:手机QQ
[M][ftc=FFFFFF]過&去&、&终究&&成&為[B][ffg,#CCFF7]&回忆&[/ft][/B],深&藏&&心底。[/ft]
I&change&in&a&memory&at&
 在即将登场的QQ2006 Beta3中,我们的《QQ音速》的游戏资料也出现在QQ的客户端啦!以后我们可以轻易的在QQ上查看到自己的《QQ音速》资料,还可以查看我们好友的《QQ音速》资料耶。嘻嘻!如果没玩过《QQ音速》的朋友
在即将登场的QQ2006beta3中,《QQ音速》的游戏资料将出现在QQ的客户端。
  红钻、蓝钻、QQ堂、幻想、QQ宠物……都在我们的QQ上显示着特别的网游资料,那么,怎么可以少了我们《QQ音速》呢!
  将登场的QQ2006b
你会用QQ邮箱来发邮件吗?可能绝大多数人都会摇头。不稳定、容量小、功能少成了它被用户遗弃的主要原因。现在我来悄悄告诉你,如今的QQ邮箱升级了,功能也是今非夕比,看过它的新功能后,你没有理由不爱上它。
QQ2006Beta1刚发布不久,QQ2006Beta2又即将发布了,不过依发布时间来看,这么短的时间内应该不会有太多的新功能。
1、活动时间:3月30日~4月20日。
2、活动期间,所有红钻贵族均可认领红钻贵族专属音乐场景。每
多语言版,支持简、繁体中文界面。
下载地址Android版Mac版
adobe air下载
15.0.0.289 官方版
Adobe AIR for Android 下载 15.0.0.349 安卓版
Adobe AIR for Mac 16.0.0.245 官方版
其他版本下载
想必很多单机游戏玩家都听过无主之地,这款传奇永恒由盛大出品,延续传奇经典制作。最东哥洛克辅助是一款绿色纯净的洛克王国免费新版itools支持安卓系统,打通双平台,安卓《美人三国》是由聚位网络潜心多年研发、欢知名苹果设备管理软件iTools终于上线越狱助灵域人物造型Q版可爱,采用2D动画技术渲染,最终幻想14神灯插件是由17173神灯插件为FF1风暴英雄强势来世,178大脚插件特别制作了风300英雄变身坦克,动漫、科幻再结合刮出不一
本类月下载排行
12345678910由于我们已经推出了AIR 2,我想这将是回顾我在过去几个月编写的所有 AIR 代码的一个绝佳时机,我会精选一些最佳代码段和概念在社区内分享。本文介绍了我用来提高 AIR 应用程序的性能、可用性及安全性,并使开发流程更加迅速简便的十大技巧:
最近,我编写了一套电子邮件通知应用程序,叫做&MailBrew。MailBrew 可监控 Gmail 和 IMAP 帐户,随后便会在新邮件到来时,发出低吼般的通知并释放警报。由于该应用程序旨在随时就您收到的新电子邮件进行通知,因此,显然它必须一直运行,而由于它始终运行,所以必须在内存使用方面非常谨慎(见图 1)
图 1.&MailBrew 初始化时会消耗一些内存,并在每次检查邮件时消耗少量内存,但总会回归原来的内存量。
由于运行时会自动进行垃圾回收,作为 AIR 开发人员,您不必刻意管理内存,但是这并不意味着您不用为此担心。事实上,AIR 开发人员仍须对创建新的对象进行谨慎考虑,尤其保留参考内容,从而使它们不会遭到清除。下列秘诀将有助于您保持较低而稳定的 AIR 应用程序内存使用率:
务必移除事件侦听器
记得处理您的 XML 对象
编写您自己的dispose() 函数
采用 SQL 数据库
介绍您的应用程序
务必移除事件侦听器
您从前可能听说过这种做法,但是值得重复的是:&当您处理完引发事件的对象后,请移除所有事件侦听器,以便能够进行垃圾回收。
下面是一些来自我编写的一款名为&&的应用程序(简化)代码,阐释添加和移除事件侦听器的正确方法:
private function onDownloadPlugin():void {
var req:URLRequest = new URLRequest(someUrl);
var loader:URLLoader = new URLLoader();
loader.PLETE, onRemotePluginLoaded);
loader.addEventListener(IOErrorEvent.IO_ERROR, onRemotePluginIOError);
loader.load(req); }private function onRemotePluginIOError(e:IOErrorEvent):void {
var loader:URLLoader = e.target as URLL
loader.PLETE, onRemotePluginLoaded);
loader.removeEventListener(IOErrorEvent.IO_ERROR, onRemotePluginIOError);
this.showError("Load Error", "Unable to load plugin: " + e.target, "Unable to load plugin"); }
private function onRemotePluginLoaded(e:Event):void {
var loader:URLLoader = e.target as URLL
loader.PLETE, onRemotePluginLoaded);
loader.removeEventListener(IOErrorEvent.IO_ERROR, onRemotePluginIOError);
this.parseZipFile(loader.data); }
另一种技巧是创建具备事件侦听器功能的变量,以便事件侦听器能够轻松地进行自我删除,就像这样:
public function initialize(responder:DatabaseResponder):void {
this.aConn = new SQLConnection();
var listener:Function = function(e:SQLEvent):void
aConn.removeEventListener(SQLEvent.OPEN, listener);
aConn.removeEventListener(SQLErrorEvent.ERROR, errorListener);
var dbe:DatabaseEvent = new DatabaseEvent(DatabaseEvent.RESULT_EVENT);
responder.dispatchEvent(dbe);
var errorListener:Function = function(ee:SQLErrorEvent):void
aConn.removeEventListener(SQLEvent.OPEN, listener);
aConn.removeEventListener(SQLErrorEvent.ERROR, errorListener);
dbFile.deleteFile();
initialize(responder);
this.aConn.addEventListener(SQLEvent.OPEN, listener);
this.aConn.addEventListener(SQLErrorEvent.ERROR, errorListener);
this.aConn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, this.encryptionKey); }
记得处理您的 XML 对象
在 Flash Player 10.1 和 AIR 1.5.2 中,我们为名为&&的系统类增加了静态函数,从而确保取消对所有 XML 对象节点的引用,并且立即可供进行垃圾回收。如果您的应用程序可解析 XML 对象,请务必确保在您完成 XML 对象解析后调用此函数。如果您不使用System.disposeXML()函数,您的 XML 对象将可能会循环引用,从而将会阻止它进行垃圾回收。
下面是解析 Gmail 生成的 XML 源的一些代码的简化版本:
var ul:URLLoader = e.target as URLL var response:XML = new XML(ul.data); var unseenEmails:Vector.&EmailHeader& = new Vector.&EmailHeader&(); for each (var email:XML in response.PURL::entry) {
var emailHeader:EmailHeader = new EmailHeader();
emailHeader.from = email.PURL::author.PURL::
emailHeader.subject = email.PURL::
emailHeader.url = email.PURL::link.@
unseenEmails.push(emailHeader); } var unseenEvent:EmailEvent = new EmailEvent(EmailEvent.UNSEEN_EMAILS); unseenEvent.data = unseenE this.dispatchEvent(unseenEvent); System.disposeXML(response);
编写您自己的 dispose() 函数
如果您要为具有多个类别的大型应用程序编写媒介,养成添加 "dispose" 函数的习惯是个好主意。事实上,您可能想要创建一个名为&IDisposable&的界面,来执行这一操作。dispose()&函数旨在确保对象不会具有阻止其进行垃圾回收的任何引用。至少,&dispose()&函数应将所有类级别变量设置为空值。当具有采用&IDisposable的代码时,应在完成时调用其&dispose()&函数。在大多数情况下,此操作并非绝对,因为通常这些引用无论如何都会进行垃圾回收(假设代码中不存在错误),但是明确地将引用设置为空值以及刻意调用dispose()&函数,具有以下两项非常重要的好处:
它将迫使您思考如何分配内存的问题。如果您针对所有类别编写dispose()函数,您可能很少会留意可能阻止对象进行清除的实例引用(这样可能会导致内存泄露)。
它使垃圾回收流程更加简便。如果所有实例均已明确地设置为空值,垃圾回收器便能够更加轻松高效地回收内存。如果您的应用程序会定期扩大规模(与MailBrew从多个不同的帐户查找新邮件时相同),在完成该操作后,您甚至可能会想要调用函数。
下面是直接执行内存管理的一些 MailBrew 代码的简化版本:
private function finishCheckingAccount():void {
this.disposeEmailService();
this.accountData = null;
this.currentAccount = null;
this.newUnseenEmails = null;
this.oldUnseenEmails = null;
System.gc(); }
private function disposeEmailService():void {
this.emailService.removeEventListener(EmailEvent.AUTHENTICATION_FAILED, onAuthenticationFailed);
this.emailService.removeEventListener(EmailEvent.CONNECTION_FAILED, onConnectionFailed);
this.emailService.removeEventListener(EmailEvent.UNSEEN_EMAILS, onUnseenEmails);
this.emailService.removeEventListener(EmailEvent.PROTOCOL_ERROR, onProtocolError);
this.emailService.dispose();
this.emailService = null; }
采用 SQL 数据库
保存 AIR 应用程序数据有多种不同的方法:
本地共享对象
EncryptedLocalStore
对象序列化
SQL 数据库
这些方法中的每一种均具有其自身的优缺点(优缺点阐释不在本文的阐述范围之内)。采用 SQL 数据库的其中一个优点在于,它有助于您的应用程序保持较低的内存使用率,而不会从平面文件向存储器加载大量数据。例如,如果您将该应用程序数据存储在数据库中,您便能够仅在必要时选择所需的数据,然后在使用完毕后轻松地将数据从存储器中移除。
MP3 播放器应用程序就是一个很好的例子。如果您要将所有用户曲目相关数据以 XML 文件进行存储,但用户只想搜寻特定艺人或某一流派的曲目,您可能要同时将所有曲目存入存储器,但仅向用户显示该数据的一个子集。利用 SQL 数据库,您可以非常迅速地精确选择用户想要寻找的曲目,并将您的存储使用率降至最低。
介绍您的应用程序
无论您多么善于进行内存管理,或者您的应用程序多么简便,在发布之前进行介绍都是一个很好的主意。Flash Builder 探查器介绍不在本文的讨论范围之内(探查器运用既是一门艺术也是一门科学),但是如果您真的要构建一套功能良好的 AIR 应用程序,您还必须对其进行认真介绍。
由于应用程序耗费的 CPU 量精确地具体于应用程序的功能,因此难以提供有关各种 AIR 应用程序 CPU 使用率的一般性诀窍,但有一种通用方式,可降低所有 AIR 应用程序的 CPU 使用率:在应用程序不活跃时,降低应用程序的帧速率。
Flex 框架内置帧速率限制。WindowedApplication 级&&属性可指示应用程序不活跃时采用的帧速率,因此如果您要使用 Flex,请将此属性设置为相应的低值(如 1)。
但是,在编写 MailBrew 时我发现,有时帧速率限制可能稍微复杂一些。MailBrew 有两套通知系统,在新邮件到来时发出低吼般的通知(见图 2),以逐步采用 alpha tween 操作清除它们。当然,这些通知甚至在应用程序不活跃时也会出现,并且需要设定一个适当的帧速率,以便顺利地淡入淡出。因此,我不得不关闭 Flex 框架速率限制机制,编写一套自己的规则。
图 2.MailBrew 通知淡入与淡出,因此在应用程序停用时,帧速率须至少为 24。
本通知是说明 MailBrew 如何就新邮件向您发出通知的测试通知。
点击通知取消当前通知,然后点击"X"取消所有等待发布的通知。
我采用的技巧是在我的 ModelLocator 类中指定应用程序的默认帧速率。如果您采用,则处理方法类似;如果您不采用上述框架,ModelLocator 仅仅代表 MVC 框架模型的类别。该常量按照下列方法进行定义:
public static constDEFAULT_FRAME_RATE:uint = 24;
然后,我采用下列方式侦测应用程序的激活和停用事件
this.nativeApplication.addEventListener(Event.ACTIVATE, onApplicationActivate); this.nativeApplication.addEventListener(Event.DEACTIVATE, onApplicationDeactivate);
我还采用下列方式定义 ModelLocator 的可绑定变量:
[Bindable] public varframeRate:
如果管理帧速率的应用程序部分发生变更,则利用&&采用下列方式侦测&frameRate变量变更:
ChangeWatcher.watch(ModelLocator.getInstance(), "frameRate", onFrameRateChange);
现在,只要该代码的任何一部分变更 ModelLocator 的&frameRate&变量,便会调用onFrameRateChange&函数:
private function onFrameRateChange(e:PropertyChangeEvent):void {
this.stage.frameRate = ml.frameR }
最后,当应用程序激活或遭到停用时,我会采用下列方式,相应地更新帧速率:
private function onApplicationActivate(e:Event):void {
this.ml.frameRate = ModelLocator.DEFAULT_FRAME_RATE; }
private function onApplicationDeactivate(e:Event):void {
this.ml.frameRate = 1; }
所有此类基础设施均可让我做到以下几点:
仅通过变更ModelLocator的frameRate变量,即可在代码的任何位置变更应用程序帧速率。
在应用程序不活跃时(在后台,或在应用程序主窗口关闭后),降低帧速率。
在显示通知前,将帧速率恢复至DEFAULT_FRAME_RATE指定的值,然后在通知淡出后再将其降低。
编写您自己的帧速率限制框架比使用Flex的内建帧速率限制框架复杂得多,但是如果您需要更大的灵活性(不含双关语意),而同时您仍然想要使您的应用程序在不活跃时保持低 CPU 使用率,便值得进行额外的时间投资。
如上所述,有几种方法可以保存 AIR 应用程序数据,每种方法均有其各自的优缺点。但是,如果您想要安全地存储数据,则有下列三种最佳选择:
EncryptedLocalStore类
加密 SQL 数据库
如果您仅需要存储用户名和密码,我会建议您采用EncryptedLocalStore (ELS) 类。但是,如果您想要存储大量数据,您可能会想要使用加密数据库(AIR 提供全面支持的加密数据库),或者自行加密,以及将加密数据保存到磁盘上。(由于加密管理指导不在本文的讨论范围之内,因此我假设您采用加密数据库。)
采用 ELS 的奇妙之处在于,您并不需要密码或者口令加密或解密数据,这样便使您的应用程序更加实用。例如,针对服务存储用户名和密码并不会带来任何好处,如果您还不得不提示他们输入其他密码或口令解密原始凭据。所以,在您必须加密超出 ELS 容量的更多数据时,如何才能提供用户采用 ELS 时同样的美妙体验呢?
解决方法是做到以下几点:
生成适当的随机密码。
采用EncryptedLocalStore存储密码。
使用密码生成密码安全数据库关键字。
利用生成的关键字加密和解密数据库。
这可能看起来很复杂,但幸运的是,您所需的绝大多数代码已经编写完毕。让我们进一步了解一下每个步骤。
生成随机密码
下列代码是我编写的一组函数,用于生成无法猜测的随机密码:
private static const POSSIBLE_CHARS:Array = ["abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ","","~`!@#$%^&*()_-+=[{]}|;:'\"\\,&.&/?"];
private function generateStrongPassword(length:uint = 32):String {
if (length & 8) length = 8;
var pw:String = new String();
var charPos:uint = 0;
while (pw.length & length)
var chars:String = POSSIBLE_CHARS[charPos];
var char:String = chars.charAt(this.getRandomWholeNumber(0, chars.length - 1));
var splitPos:uint = this.getRandomWholeNumber(0, pw.length);
pw = (pw.substring(0, splitPos) + char + pw.substring(splitPos, pw.length));
charPos = (charPos == 3) ? 0 : charPos + 1;
private function getRandomWholeNumber(min:Number, max:Number):Number {
return Math.round(((Math.random() * (max - min)) + min)); }
既然您已经具备随机密码,便可以进行存储。
存储您的随机密码
安全存储您将用来生成数据库加密密钥密码的最佳方式是采用 EncryptedLocalStore 类方法。&易于使用;不过,我通常采用&&项目取而代之。采用 as3preferenceslib 的优势在于,我可以利用相同的 API 存储所有应用程序首选项。在幕后,as3preferenceslib 利用 ELS 存储您出于安全原因指定的数据。该代码如下所示:
var ml:ModelLocator = ModelLocator.getInstance(); var prefs:Preference = ml. var databasePassword:String = prefs.getValue(PreferenceKeys.DATABASE_PASSWORD); if (databasePassword == null) {
databasePassword = this.generateStrongPassword();
ml.prefs.setValue(PreferenceKeys.DATABASE_PASSWORD, databasePassword, true); // The third argument indicates secure storage
ml.prefs.save(); }
生成密码安全数据库关键字
生成密码安全加密密钥十分复杂,但幸运的是,我们具备供您完成此操作的代码。我采用位于&&的 EncryptionKeyGenerator。
通过将您的随机密码与特定的用户帐户及特定的计算机相关联,利用 EncryptionKeyGenerator 将您的加密数据安全性提高一个层次。换句话说,即使有人发现了您的随机密码,除非他们具备用户的计算机并以用户身份登录,否则不会产生任何效果。
采用 EncryptionKeyGenerator 时,不要存储返回的密码密钥,这一点至关重要;恰恰相反,您可存储用于查看用途的密码,然后生成随选密码密钥。下列代码将演示正确方法:
// Get the databasePassword from the Preference object using the code shown above, then... var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator(); var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(databasePassword); // Now use the encryptionKey to encrypt and decrypt your database.
加密与解密您的数据库
既然您已经具备密码安全数据库密钥,您唯一要做的就是在创建数据库连接时输入密钥。下列代码示例(由于缺乏事件侦听器,因此经过简化)说明了加载加密数据库文件及建立数据库连接的方法:
var keyGenerator:EncryptionKeyGenerator = new EncryptionKeyGenerator(); var encryptionKey:ByteArray = keyGenerator.getEncryptionKey(databasePassword); var dbFile:File = File.applicationStorageDirectory.resolvePath("myEncryptedDatabase.db"); var aConn:SQLConnection = new SQLConnection(); aConn.openAsync(dbFile, SQLMode.CREATE, null, false, 1024, this.encryptionKey);
在主窗口关闭后仍然继续运行的应用程序,时常被称作"无头"应用程序。许多应用程序在 Mac 及 Windows 系统上采用这种范例,一些应用程序(即时通信和电子邮件客户端,例如)极少"最小化到系统托盘"(见图 3)。
图 3.&MailBrew 最小化到 Windows 系统托盘。
可将 AIR 应用程序设计为在应用程序主窗口关闭后退出,或者它们也可作为无头应用程序运行。让您的应用程序在应用程序主窗口关闭后继续运行的最简便方法是,将&NativeApplication的autoExit&属性设置为"假",如下所示:
private function onApplicationComplete():void {
NativeApplication.nativeApplication.autoExit = false; }
如果你准备采用 Flex 框架,则您还可以利用&WindowedApplicatio&标签的autoExit&属性设置此属性,如下所示:
&s:WindowedApplication
xmlns:fx="/mxml/2009"
xmlns:s="library:///flex/spark"
xmlns:mx="library:///flex/halo"
xmlns:c="ponents.*"
width="500" height="400" minWidth="500" minHeight="400"
showStatusBar="false" backgroundFrameRate="-1"
autoExit="true"
applicationComplete="onApplicationComplete();"&
由于您已经成功阻止应用程序在应用程序主窗口关闭后退出,您必须在用户再次需要使用时(或许是它们点击停靠或系统托盘图标时),重新打开应用程序主窗口。设计您的应用程序支持此类互动的最简便方式是,将您的主要应用程序界面作为&NativeWindow的子级置于其自身的组件中。下列代码显示了在主应用程序隐藏或最小化到系统托盘后,重新打开主应用程序的跨平台方法:
private function onApplicationComplete():void {
NativeApplication.nativeApplication.autoExit = false;
if (NativeApplication.supportsDockIcon)
NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, onShowWindow);
else if (NativeApplication.supportsSystemTrayIcon)
SystemTrayIcon(NativeApplication.nativeApplication.icon).addEventListener(ScreenMouseEvent.CLICK, onShowWindow);
}}private function onShowWindow(e:Event):void {
var mainApplicationUI:MainApplicationUI = new MainApplicationUI();
mainApplicationUI.open(true); }
编写无头应用程序的另一种方法是,不关闭您的应用程序主窗口,而是仅将其隐藏。这种方法不需要您将 NativeWindow 的&autoExit属性设置为"假" ,这是因为您并没有真正关闭应用程序主窗口,但是需要您编写代码阻止该窗口关闭,并将其&visilibity属性设置为"&假",如下所示:
private function onWindowClosing(e:Event):void {
e.preventDefault();
this.visible = false;
ml.frameRate = 1; }
恢复您的应用程序主窗口的方法与上述方法类似,但并非创建新的主要应用程序界面实例,您只需将您的应用程序&NativeWindow.visibility&属性再次设置为"真&",如下所示:
private function onShowWindow(e:Event):void
this.visible =
ml.frameRate = ModelLocator.DEFAULT_FRAME_RATE;
this.nativeWindow.activate();
我认为,拖动主应用程序&visibility&属性的方法是较为简易的方式,并在绝大多数情况下均可发挥作用。这种方法唯一不能奏效的情况是,在您想要用户像在&&等应用程序中那样,能够打开多个主要应用程序界面实例的情况下。
为了使无头应用程序能够保持某种可视状态,它们往往利用 Mac 停靠功能或者 Windows 系统托盘功能的优势。这些图标为用户提供了一种恢复应用程序主窗口的方式,并且也为应用程序提供了一种为最终用户传递信息的方式。AIR 不会提供叠加应用程序图标上的文本信息的 API,但是会有动态生成位图,以及更新停靠或系统托盘的应用程序图标的 API(见图 4)。
图 4.&叠加多封未读邮件的 MailBrew 停靠图标。
下列代码是取自 MailBrew 的一个示例,用来说明如何向停靠图标上添加文本和图形,以便用户能够一目了然地看到未读邮件的数量(见图 4)。类似的方法也可用于系统托盘图标,但系统托盘图标仅为 16 方形像素,因而难以在其上叠加太多文本。Windows 7 可支持更多富于表现力的任务栏图标,未来我们计划支持新型 API。
// If we're on Windows, return. This icon wouldn't look very good in the system tray. if (NativeApplication.supportsSystemTrayIcon) return;
var unseenCount:uint = getUnreadMessageCount(); // Function for counting the number of unread messages. var unreadCountSprite:Sprite = new Sprite(); unreadCountSprite.width = 128; unreadCountSprite.height = 128; unreadCountSprite.x = 0; unreadCountSprite.y = 0; var padding:uint = 10; // Use FTE APIs to get the best looking text. var fontDesc:FontDescription = new FontDescription("Arial", "bold"); var elementFormat:ElementFormat = new ElementFormat(fontDesc, 30, 0xFFFFFF); var textElement:TextElement = new TextElement(String(unseenCount), elementFormat); var textBlock:TextBlock = new TextBlock(textElement); var textLine:TextLine = textBlock.createTextLine(); textLine.x = (((128 - textLine.textWidth) - padding) + 2); textLine.y = 32; unreadCountSprite.graphics.beginFill(0xE92200); unreadCountSprite.graphics.drawEllipse((((128 - textLine.textWidth) - padding) - 3), 2, textLine.textWidth + padding, textLine.textHeight + padding); unreadCountSprite.graphics.endFill(); unreadCountSprite.addChild(textLine); var shadow:DropShadowFilter = new DropShadowFilter(3, 45, 0, .75); var bevel:BevelFilter = new BevelFilter(1); unreadCountSprite.filters = [shadow, bevel]; var unreadCountData:BitmapData = new BitmapData(128, 128, true, 0x); unreadCountData.draw(unreadCountSprite); // The Dynamic128IconClass referenced below is embedded. var appData:BitmapData = new Dynamic128IconClass().bitmapD
appData.copyPixels(unreadCountData, new Rectangle(0, 0, unreadCountData.width, unreadCountData.height),
new Point(0, 0),
null, null, true); var appIcon:Bitmap = new Bitmap(appData); // If you do want to change the system tray icon on Windows, as well, add a 16x16 icon to the array below. InteractiveIcon(NativeApplication.nativeApplication.icon).bitmaps = [appIcon];
随着人们将越来越多的数据转移至云中,本地访问和缓存该类数据的桌面应用程序也将变得日益重要起来。Adobe AIR 是编写这些类型应用程序的理想平台,理由如下:
广泛的协议支持。您可以在运行时间本身及第三方ActionScript库之间,采用您想要采用的任何协议,交换桌面客户端与 Web 服务数据 & 或者在 HTTP 或 TCP 套接字上轻松地编写您自己的协议。
多平台支持。由于 Web 本身就是跨平台发挥作用,如果您打算在 Web 服务上编写桌面客户端,这也使得它具有跨平台的特性。
支持&Web&技术。由于 AIR 支持 Web 技术,您可以利用同样的工具和技术,构建您的 Web 应用程序采用的桌面客户端。
在 Web 服务上编写桌面客户端面临的其中一项挑战在于,确定网络连接。即使采用 WiFi 扩散及 3G(很快将会演进为 4G)等高速无线数据协议,事实上,我们仍然无法一直保持连接。因此,依赖网络连接的应用程序需要寻求一种确切了解它们是否处于连接状态的方法。
我们首次尝试解决这个问题,引发了 NativeApplication 类的&&事件。每当网络开始连接或我们最初认为足以连接但断开时,都会触发 NETWORK_CHANGE 事件。不过,我们很快便意识到,这些信息不足以让开发人员了解他们是否能够获取特定的服务。
例如,网络连接会随着 VPN 连接的打开或关闭、虚拟机启动或停止、无线网络进入或超出范围、电缆插入或拔出等条件影响而连接或断开。并且当然,有时无法预测应用程序服务将在何处驻留;它们可能位于公共互联网、防火墙后,或者甚至在本地计算机上。最后,即使您能够确定可以获取服务,也无法保证在您需要访问时该服务能够实时响应。所有 这些因素都向我们表明,我们需要更加全面的 API,以及有关如何使用它们的一些最佳实践做法。
我发现,桌面客户端应用程序一般分为两类:访问一系列已知服务(Twitter 和 Facebook 客户端,例如)的应用程序,以及访问任意数量的不可预见服务的应用程序(RSS 聚合器、电子邮件或 IM 客户端等)。根据我的经验,分别处理这两种类型的应用程序的连接变更将会十分有效。
访问一系列已知服务的应用程序
如果您了解您的应用程序需要访问哪些 Web 服务,则监控其可用性的最简便方式是采用&&类(或者&,如果您使用 TCP 而不是 HTTP)。URLMonitor 类一般会定期对一组特定的 URL 进行民意测验,从而让您了解任何状态变更,如下列代码所示:
private var urlMonitor:URLM
private function onCreationComplete():void {
var req:URLRequest = new URLRequest("/myservice");
this.urlMonitor = new URLMonitor(req, [200, 304]); // Acceptable status codes
this.urlMonitor.pollInterval = 60 * 1000; // Every minute
this.urlMonitor.addEventListener(StatusEvent.STATUS, onStatusChange);
this.urlMonitor.start(); }
private function onStatusChange(e:Event):void {
if (this.urlMonitor.available)
// Everything is fine.
// Service is not available.
// Consider alerting the user.
访问任意服务的应用程序
如果您并不知道您的应用程序将要访问哪些服务,因为服务须由用户配置(与电子邮件客户端的情况类似),或者您并不了解您的应用程序将要访问多少项服务(与 RSS 聚合器的情况类似),则采用URLMonitor&并不可行。事实上,应用程序访问的服务越是不可预见,则越是难以确定服务是否可供访问。例如,即使您的应用程序意识到其公共互联网连接不可靠,可能仍然需要在防火墙后聚合 RSS 源;或者,即使您的应用程序发现根本不存在可供使用的网络连接,可能依然要访问本地计算机上运行的服务。由于网络连接变得越来越难以预测和度量,在很多情况下,最好的方式只是尝试建立连接,并在连接失败时报告错误。
MailBrew 就是一个很好的例子。由于 MailBrew 能够配置访问任意数量的电子邮件账户,因此在尝试连接之前,并不存在任何一种可靠方法,供应用程序了解是否真的能够获取服务。所以,该应用程序通过执行下列操作,适当地处理网络错误:
注册指示某些部分发生错误的任何事件(IOErrorEvent,&HTTP_RESPONSE_STATUS_EVENT等)。
如果发现连接问题,请更新指定服务无法访问的数据库标志。
& 更新通知用户服务不可用的用户界面。在图 5 中,我的两个 Gmail 账户均可访问,因为我建立了外界网络连接,但是我的 Adobe 账户无法访问,因为我并未登录 VPN。
注意:即使您采用URLMonitor检查您的服务可用性,您也不能依赖它,这是因为在监视器上次检查到您的应用程序到需要进行访问这段时间期间,服务很可能不再有效。因此,您必须一直侦听可能指示连接问题的相应事件,并适当地处理所有问题。
图 5.如果出现连接错误,则帐户名称变为红色,并且用户可以选择打开错误信息窗口。
网络连接可能十分复杂,但是应用程序须以直观、内容丰富的方式展现给最终用户,这一点至关重要。采用上述两种方法须保证您的应用程序在任何情况下均正常运转,无论连接多么不可靠或者难以预测。
所有应用程序开发人员都明白,编写代码是一个高度重复性过程。这项工作的流程通常是编写一些代码,运行应用程序进行测试,然后重复几十、几百,甚至几千次,重复次数取决于应用程序规模的大小。
如果您的应用程序将要访问外部服务,但是,事实上,由于可能受到速率限制(在 Twitter 或 IM 客户端的情况下),此流程可能会十分复杂,或者访问远程服务可能会大幅降低这一过程的速度(当平均超过数百次重复时)。我采用下列两种方法管理这些类型的方案:测试模式和调试模式。
当我编写其中一套初期移动 AIR 应用程序(TweetCards)时,我很快意识到,在每次重复时从 Twitter 中抓取数据无法形成规模。这不仅会减慢开发速度,而且我也可能会受到速度限制(即由于我连接过于频繁,Twitter 会在某段时间拒绝我的请求),因而在我未建立网络连接时,将无法在该应用程序上开展工作(我编写了一些长途飞行编码)。
图 6.&以"测试模式"运行且带有假数据的 TweetCards。
答案是创建测试模式,从而在输入凭据字段的用户名和密码均为"测试"时进行启用(见图 6)。下列代码演示了这一概念:
private function onSaveAccountInfo(e:MouseEvent = null):void {
var username:String = this.usernameInput.
var password:String = this.passwordInput.
var ml:ModelLocator = ModelLocator.getInstance();
ml.testMode = (this.usernameInput.value == "test" && this.passwordInput.value == "test");
ml.credentials = {"username":this.usernameInput.value, "password":this.passwordInput.value};
ml.currentScreen = Screen.READ_SCREEN; }
当应用程序处于测试模式,而不是向 Twitter 发出数据请求时,我生成了我自己的测试数据:
private function getTweets():void {
var ml:ModelLocator = ModelLocator.getInstance();
if (ml.testMode)
this.createTestData();
this.queryTwitter();
其结果是,数据将瞬间加载,而我不必向 Twitter 发出任何请求便可测试我的应用程序。
我在编写 MailBrew 时探索出的另一种方法是,为我的应用程序构建"调试"模式。调试模式这一需求是我编写代码在应用程序启动时检查用户的电子邮件账户的瞬间产生。从那以后, 每当我想要测试应用程序的组件 & 甚至小到一个按钮的位置 & 我都要向多项电子邮件服务发出请求,这样便开始放慢我的开发速度。下列代码就是解决方法:
private function onApplicationComplete():void {
// If we're running from ADL, put the app in debug mode.
ModelLocator.debugMode = Capabilities.isD }
问题解决了。自那时起,从 ADL 运行 MailBrew 时,便不再发送 CheckMailEvent。同时还有其他一些额外的好处。举例来说,我决定从 ADL 运行程序时,不再采用新的整体误差处理 AIR 2 功能,因此我将下列代码行:
this.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
if (!ModelLocator.debugMode) this.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
最后,当从 ADL 调用时,&及&&等某些 API 将引发运行异常,这是因为它们在开发和测试环境下无法发挥作用。如果您的应用程序中采用任何一种这些 API,将它们置于检查调试模式条件下将会是一个好主意。
注意:&请注意,我在其中一个位置采用Capabilities.isDebugger&设置debugMode全局标志的基本架构,而不是在我想要检查模式的所有位置均采用&Capabilities.isDebugger&这样做的优点在于,我可以轻松地变更标准,决定应用程序在一个位置是否处于&debugMode&模式。例如,我可能决定利用命令行参数支持让应用程序进入调试模式,因此安装版本也可能进入调试模式,以供测试。
当我们确定可以为 AIR 应用程序编写通知系统后,我们意识到,我们还需要寻求一种方法来检测用户是否真的在计算机前操作,以便该应用程序了解实际显示这些通知是否有意义。例如,如果用户并不能实际看到或听到通知,则 MailBrew 持续显示和播放通知将毫无意义。
我们通过在 NativeApplication 类上采用&&和&&事件的方式解决了这一问题。这些事件在注册时,将会告知应用程序用户何时开始一直处于空闲状态,以及他们又是何时返回计算机。下列代码显示了一个简单的例子:
private function onCreationComplete():void {
NativeApplication.nativeApplication.idleThreshold = 2 * 60; // In seconds -- the default is 5 minutes.
NativeApplication.nativeApplication.addEventListener(Event.USER_IDLE, onUserIdle);
NativeApplication.nativeApplication.addEventListener(Event.USER_PRESENT, onUserPresent); }
private function onUserIdle(e:Event):void {
// No keyboard or mouse input for 2 minutes. }
private function onUserPresent(e:Event):void {
// The user is back! }
我发现在现实方案中,在我的应用程序中直接注册这些事件并不那么有效;相反,通知框架等库执行该操作往往更加有效。例 如,MailBrew采用的通知框架可自动注册这些事件,并在用户处于空闲状态时列队等候显示通知,然后在用户返回后自动开始显示这些通知。此外,在使用这些 API 时,请确保将应用程序工作流程考虑在内。例如,如果您的应用程序显示视频,由于用户可能并非真的处于空闲状态,您可能会想要在媒体播放期间禁用空闲计时器。
如需有关这些 API 运行的简单而又现实的例子,请参见我的屏幕保护示例应用程序,叫做 SPF,或者。
AIR 应用程序针对首选项或者方框开启辅助窗口这一操作不足为奇。在 AIR 程序中打开辅助窗口非常容易,但有些方面必须注意:打开多个相同的实例。由于 AIR 程序没有模式窗口这一概念,如果您想要阻止用户同时打开多个窗口,您必须自行制定方案。
图 7.MailBrew 设置窗口。每次仅可打开一个窗口。
幸运的是,这很容易做到。我具有 WindowManager 类,其中包含处理下列类型的辅助窗口的多项有效功能:
/** * Returns an instance of a NativeWindow if it's already open.
*/ public static function getWindowByTitle(title:String):NativeWindow {
var allWindows:Array = NativeApplication.nativeApplication.openedW
for each (var win:NativeWindow in allWindows)
if (win.title == title)
return null; }
getWindowByTitle&功能使我能够打开下列窗口:
private function onOpenSettings(e:MouseEvent):void {
var win:NativeWindow = WindowManager.getWindowByTitle(WindowManager.PREFERENCES);
if (win != null)
win.activate();
var prefsWin:PreferencesWindow = new PreferencesWindow();
prefsWin.open(true);
这种方法可保证每次仅可开启一个首选项窗口 & 即使用户不小心双击"Preferences"按钮也是一样。如果"Preferences"窗口已经打开,也只会被激活(来到前面的窗口,并予以关注),而不会遭到复制。
作为额外奖励,下面是我的 WindowManager 类的另一项有用功能:
/** * Hand me a window, and I'll center it on the primary monitor. */ public static function centerWindowOnMainScreen(win:NativeWindow):void {
var initialBounds:Rectangle = new Rectangle((Screen.mainScreen.bounds.width / 2 - (win.width/2)), (Screen.mainScreen.bounds.height / 2 - (win.height/2)), win.width, win.height);
win.bounds = initialB
win.visible = true; }
AIR 具有跨平台运行的特性,但这并不意味着应用程序不能或不应该识别平台之间的差异,我们已经在本文中了解到,采用 Windows 系统托盘与 Mac OS X 停靠开展工作时如何采用不同的图标尺寸,但是有时平台差异并没有那么简单。例如,在 MailBrew 设置窗口中,我拥有 Mac OS X 选项,在新邮件到来时停靠图标会不停跳动,而在 Windows 上并不存在这种图标,但在 Windows 上,我具有任务栏图标闪烁选项,而 Mac OS X 上不存在该选项。
有多种方法可供处理这些类型的平台特定问题,因此,与其说是一种方法正确或者高级,不如只是向您介绍我在编写 MailBrew 时尝试使用的几种方法。下面是处理 PreferencesWindow 组件平台差异的相关代码:
&s:Window creationComplete="onCreationComplete();"&
&fx:Script&
private function onCreationComplete():void
if (NativeApplication.supportsDockIcon)
this.currentState = "supportsDockIcon";
this.bounceDockIconCheckbox.selected = prefs.getValue(PreferenceKeys.APPLICATION_ALERT, false);
this.currentState = "supportsSystemTray";
this.flashTaskBarCheckbox.selected = prefs.getValue(PreferenceKeys.APPLICATION_ALERT, false);
&/fx:Script&
&s:states&
&s:State name="supportsDockIcon"/&
&s:State name="supportsSystemTray"/&
&/s:states&
&s:VGroup width="100%" height="100%"&
&s:Group width="100%" includeIn="supportsDockIcon"&
&s:Label text="Bounce Dock Icon" fontWeight="bold" y="5" left="5"/&
&s:Label y="20" width="210" left="5"&Do you want the Dock icon to bounce when you get new messages?&/s:Label&
&s:CheckBox id="bounceDockIconCheckbox" y="5" right="20"/&
&/s:Group&
&s:Group width="100%" includeIn="supportsSystemTray"&
&s:Label text="Flash Task Bar Icon" fontWeight="bold" y="5" left="5"/&
&s:Label y="20" width="210" left="5"&Do you want the task bar icon to flash when you get new messages?&/s:Label&
&s:CheckBox id="flashTaskBarCheckbox" y="5" right="20"/&
&/s:Group&
&/s:VGroup& &/s:Window&
正如您所见,此处的关键在于利用非常便利的 Flex 状态功能完成绝大部分工作。但是当然,还有其他方法也可以完成这项操作。例如,MailBrew 的另一项平台差异在于应用程序主窗口工具栏。在 Mac OS X 上,标题和徽标位于窗口左侧,按钮位于窗口右侧(见图 8)。
图 8.MailBrew 在 Windows 上位于后台,而在 Mac OS X 上位于前台。请注意工具栏的不同布局。
不过,我发现在 Windows 上,将互动工具置于窗口右侧很容易一不小心点击窗口控制器而意外关闭窗口。答案是改变次序,如下列代码所示:
&s:Group creationComplete="onCreationComplete();"&
&fx:Script&
private function onCreationComplete():void
if (NativeApplication.supportsSystemTrayIcon) // Windows
this.logoBitmap.visible = false;
this.logoLabel.right = 3;
this.buttonGroup.left = 5;
this.logoBitmap.visible = true;
this.logoBitmap.left = 4;
this.logoLabel.left = 31;
this.buttonGroup.right = 5;
&/fx:Script&
&s:BitmapImage id="logoBitmap" source="{ModelLocator.getInstance().TopLeftLogo}" top="3"/&
&s:Label id="logoLabel" text="MailBrew" top="11" fontSize="20" color="0xf2f2f2" fontFamily="_sans"/&
&s:HGroup id="buttonGroup" top="5"&
&mx:Button id="checkNowButton" label="Check Now" icon="{ModelLocator.getInstance().CheckNowIconClass}"/&
&mx:Button id="settingsButton" label="Settings" icon="{ModelLocator.getInstance().ConfigureIconClass}"/&
&mx:Button id="aboutButton" label="About" icon="{ModelLocator.getInstance().AboutIconClass}"/&
&/s:HGroup& &/s:Group&
在这个例子中,我不采用状态,而是只是利用其left,&right, 及&visible&属性重新排列或移除组件。
虽然我尽量将应用程序间的平台差异降至最低,但现实情况是差异偶尔还是会出现。在我看来,最好编写一些代码来处理平台间的差异,而不是假装它们不存在。
阅读(...) 评论()

我要回帖

更多关于 adobe air runtime 的文章

 

随机推荐