AIR文件操作(一):AIR文件基础
AIR允许我们开发与文件系统协同工作的应用程序
我们可以使用Adobe? AIR? 文件系统API提供的类访问主机的文件系统。使用这些类,可以访问、管理目录与文件,建立目录与文件,向文件写数据等等。我把与文件系统协同工作的内容总结为AIR文件操作三部分:
AIR文件基础(下文)
使用File对象操作文件和目录
使用FileStream对象读写文件
相关类的语言参考
flash.filesystem.File
flash.filesystem.FileStream
flash.filesystem.FileMode
下面进入AIR文件操作第一部分:
AIR文件基础
AIR提供了让您能用来访问、创建、管理文件与目录的类。这些类被放置在flash.filesystem包中,也就是下面那三个类:
类 描述
File File对象代表一个文件或目录的路径。您可以用file对象建立一个指向文件或目录的指针,以作用于文件或目录。
FileMode FileMode类定义在FileStream类的open()和openAsync()方法中使用的字符串常量参数。
这些方法的FileMode参数确定了文件打开后FileStream对象可用的功能,包括写入、读取、追加和更新。
FileStream FileStream对象打开文件以便读写数据。当创建一个File对象指向一个新的或已存在的文件后,您将该指针传递给FileStream对象,就可以用FileStream来打开并操作文件数据。
File类中的某些方法分别有同步和异步两种版本:
File.copyTo() 和 File.copyToAsync()
File.deleteDirectory() 和File.deleteDirectoryAsync()
File.deleteFile() 和File.deleteFileAsync()
File.getDirectoryListing() 和File.getDirectoryListingAsync()
File.moveTo() 和File.moveToAsync()
File.moveToTrash() 和File.moveToTrashAsync()
同样,FileStream是以同步或异步方式来操作数据,取决于FileStream对象如何打开文件:是调用open()方法还是调用openAsync()方法。
异步版本的处理过程在后台运行,当执行完成或产生错误时触发相应事件。其他代码可以在这些异步操作后台运行的同时执行。使用异步版本操作,你必须设置事件监听,使用File或FileStream对象的addEventListener()方法调用相应函数。
同步版本使您不需要依赖设置事件监听,直接写简单的代码。然而,其他代码无法在同步方法执行时执行,重要的进程(比如显示对象渲染和动画播放)可能被暂停。
AIR文件操作(二):使用文件对象操作文件和目录
文件对象是啥?
文件对象(File对象)是在文件系统中指向文件或目录的指针。由于安全原因,只在AIR中可用。
文件对象能做啥?
获取特定目录,包括用户目录、用户文档目录、该应用程序启动的目录和程序目录
拷贝文件和目录
移动文件和目录
删除文件和目录(或移至回收站)
列出某目录中的文件和目录
创建临时文件和文件夹
创建目录
读取文件信息
获取文件系统信息
在AIR中,我们用FileStream读写文件的前提就是用File对象来指向文件。
那么文件对象具体怎么玩呢?
功能1、指向目录和文件
File 对象有两个属性都能定义文件路径,它们是nativePath和url。nativePath是在特定平台使用的文件路径(主要就是Windows和 MacOs上的路径表示不同),url则是统一的”file:///c:/Sample%20directory/test.txt”这样的表示方法。
我们来看几个指向目录的实例,其中1-7演示了如何获取特殊目录:
var file:File = File.userDirectory; //指向用户文件夹
var file:File = File.documentsDirectory; //指向用户文档文件夹
var file:File = File.desktopDirectory; //指向桌面
var file:File = File.applicationStorageDirectory; //指向应用程序存储目录
(参见AIR的URL方案)
var dir:File = File.applicationDirectory; //应用程序安装目录
var dir:File = File.getRootDirectories(); //文件系统根目录
还有一招,指向请求启动该应用程序的目录,先空着,以后补上。参考资料见《Capturing command
line arguments》
var file:File = new File();
file.nativePath = "C:\\Mousebomb\\";
//(windows平台)指向一个具体的目录,这里使用了nativePath属性,”C:\\Mousebomb\\”只适用windows中。
var file:File = File.userDirectory;
file = file.resolvePath(”Mousebomb”);
//跳转到用户目录下的Mousebomb目录
var urlStr:String = "file:///C:/Mousebomb/";
var file:File = new File()
file.url = urlStr;
//指向c盘下的Mousebomb目录,这里使用了url属性
/*让用户选择目录*/
var file:File = new File();
file.addEventListener(Event.SELECT, dirSelected);
file.browseForDirectory("Select a directory");
function dirSelected(e:Event):void {
trace(file.nativePath);
}
下面看看指向文件的实例:
指向明确的文件地址:
var file:File = File.applicationStorageDirectory;
file = file.resolvePath("Flashj.txt");
使用url属性的例子:
var urlStr:String = "file:///C:/Mousebomb/Flashj.txt";
var file:File = new File()
file.url = urlStr;
当然你也可以直接这样写
var urlStr:String = "file:///C: /Mousebomb/Flashj.txt";
var file:File = new File(urlStr);
//url中的空格会被%20替换
使用nativePath属性:
var file:File = new File();
file.nativePath = "C:/ Mousebomb/Flashj.txt";
或者
var file:File = new File("C:/ Mousebomb/Flashj.txt");
//(Windows下)
通过对话框让用户选择文件
实现这个功能需要认识三个方法:
browseForOpen()
browseForSave()
browseForOpenMultiple()
三 个方法都是异步的,browseForOpen() 和 browseForSave()方法在用户选择文件时会触发select事件,在选择了某文件时,File指向选择的文件。 而browseForOpenMultiple()方法会触发selectMultiple事件,该事件属于FileListEvent型,它的属性中具 有指向所选文件的File对象数组。
例子:
var fileToOpen:File = File.documentsDirectory;
selectTextFile(fileToOpen);
function selectTextFile(root:File):void
{
var txtFilter:FileFilter = new FileFilter("Text", "*.as;*.css;*.html;*.txt;*.xml");
root.browseForOpen("Open", [txtFilter]);
root.addEventListener(Event.SELECT, fileSelected);
}
function fileSelected(event:Event):void
{
trace(fileToOpen.nativePath);
}
功能2、拷贝文件和目录
拷贝文件使用到的方法有copyTo()和copyToAsync(),详见AIR文件基础,前者为同步方法,后者为异步方法。
要拷贝文件,需要创建2个File对象,一个指向原文件,一个指向目标文件。像下面两例:
1.同步拷贝例:
var original:File = File.documentsDirectory.resolvePath("Mousebomb/FlashJ.txt");
var newFile:File = File.resolvePath("Mousebomb/FlashJcn.txt");
original.copyTo(newFile, true);
第二个参数true表示覆盖存在的文件,默认值是false,若设置为false,而拷贝的目标文件已经存在,则AIR会发出IOErrorEvent事件。
2.异步拷贝例:
var original = File.documentsDirectory;
original = original.resolvePath("Mousebomb/FlashJ.txt");
var destination:File = File.documentsDirectory;
destination = destination.resolvePath("FlashJ/FlashJcn.txt");
original.addEventListener(Event.COMPLETE, fileCopyCompleteHandler);
original.addEventListener(IOErrorEvent.IO_ERROR, fileCopyIOErrorEventHandler);
original.CopyToAsync(destination);
function fileCopyCompleteHandler(event:Event):void {
trace(event.target); // [object File]
}
function fileCopyIOErrorEventHandler(event:IOErrorEvent):void {
trace("I/O Error.");
}
功能3、移动文件和目录
移动文件使用的方法有moveTo()和MoveToAsync(),不仅长相类似,连使用方法都与拷贝文件一样,可以直接参考上文。
功能4、删除文件和目录(或移至回收站)
deleteFile()和deleteFileAsync()负责删除功能,而moveToTrash()和moveToTrashAsync()功能是移至回收站。先创建一个File对象指向某个文件或目录,然后执行四个方法之一,处理异步方法要加事件监听。
var file:File = File.documentsDirectory.resolvePath("DeleteMe.txt");
file.moveToTrash();
功能5、列出某目录中的文件和目录
可以使用getDirectoryListing()方法和getDirectoryListingAsync()方法获取某个目录下文件与子目录的File指针数组。
例如:
var directory:File = File.documentsDirectory;
var contents:Array = directory.getDirectoryListing();
for (var i:uint = 0; i < contents.length; i++)
{
trace(contents[i].name, contents[i].size);
}
本例输出了用户文档目录中的文件名和大小。
若使用异步方法,例如:
var directory:File = File.documentsDirectory;
directory.getDirectoryListingAsync();
directory.addEventListener(FileListEvent.DIRECTORY_LISTING, dirListHandler);
function dirListHandler(event:FileListEvent):void
{
var contents:Array = event.files;
for (var i:uint = 0; i < contents.length; i++)
{
trace(contents[i].name, contents[i].size);
}
}
其中directoryListing事件对象中有个files属性,为目录下内容的File指针数组。
功能6、创建临时文件和文件夹
使用createTempFile()和createTempDirectory()方法可以创建临时文件和文件夹。
var temp:File = File.createTempFile(); //在系统临时文件夹下创建临时文件
createTempFile()方法会自动创建一个唯一的临时文件。
createTempDirectory ()方法会自动创建一个唯一的临时文件夹。
你可以用临时文件来临时存储应用程序回话中的信息。
由于临时文件不会自动删除,所以你可能得让应用程序在关闭前删除它。
功能7、创建目录
使用createDirectory()方法可以创建目录,例如:
var dir:File = File.userDirectory.resolvePath("Mousebomb");
dir.createDirectory();
这个例子在用户文件夹下创建了Mousebomb目录,如果Mousebomb目录存在,则不会作出操作。
功能8、读取文件信息
File类中包含以下属性,提供File对象所指向文件或目录的信息。
属性
描述
creationDate
创建日期
exists
是否存在
extension
扩展名,若无则为null
icon
该文件的图标对象
isDirectory
是否目录
modificationDate
修改日期
name
文件名(包括扩展名)
nativePath
特定平台使用的文件路径
parent
父级目录,若该File对象就是顶级则此属性为null
size
字节大小
url
统一资源定位符
详细参见AIR ActionScript. 3.0 Language Reference for Adobe AIR.
功能9、获取文件系统信息
File类包含一下静态属性,提供有用的文件系统信息(主要是跨平台使用):
属性
描述
File.lineEnding
系统的行结束符
File.separator
系统的分隔符(Windows下为\ Mac Os为/)
File.systemCharset
系统的默认文件编码,属于系统所使用的字符集
顺便插进Capabilities类包含的静态属性:
属性
描述
Capabilities.hasIME
当前运行的系统是否安装了输入法编辑器
Capabilities.language
当前运行的系统的语言编码
Capabilities.os
当前运行的操作系统
参考文献:http://livedocs.adobe.com/air/1/devappsflash/help.html?content=dg_part_6_1.html(文件与数据)
AIR文件操作(三):使用FileStream对象读写文件
快速上手例:
例1.读xml
var testXML:XML;
var file:File = File.documentsDirectory.resolvePath("Mousebomb/test.xml");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.READ);
testXML = XML(fileStream.readUTFBytes(fileStream.bytesAvailable));
fileStream.close();
例中使用readUTFBytes()方法读取内容并转换为XML对象。
例2.写xml
var testXML:XML =<mousebomb><site>www.mousebomb.org</site><blog>www.flashj.cn</blog></mousebomb>;
var file:File = File.documentsDirectory.resolvePath("Mousebomb/test.xml");
var fileStream:FileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
var outputString:String = '<?xml version="1.0" encoding="utf-8"?>\n';
outputString += testXML.toXMLString();
fileStream.writeUTFBytes(outputString);
fileStream.close();
写XML也一样简单,创建File对象和FileStream对象,使用writeUTFBytes()写入数据。
工作流程
要完成读写文件操作无非就是这几步:
1. 创建File对象指向文件路径
2. 初始化FileStream对象
3. 使用FileStream的open()或openAsync()方法
4. 若使用的是异步的openAsync()方法则需要为FileStream设置事件监听
5. 加入所需的读写数据代码
6. 完成文件操作后执行FileStream的close()方法
使用FileStream要了解的知识
1. FileMode
FileStream的open()和openAsync()方法都包含一个fileMode参数,该参数用于设置:
读取文件能力
写入文件能力
是否总在文件末尾追加数据(写数据时)
文件不存在时如何操作(或文件的父级不存在时)
具体值包括
FileMode值
描述
FileMode.READ
设置文件打开方式为只读
FileMode.WRITE
设置文件打开方式为写数据。若文件不存在,则创建之;若文件存在,则该文件所有存在数据被删除。
FileMode.APPEND
设置文件打开方式为追加。若文件不存在,则创建之;若存在,则文件所有存在数据不被覆盖,所有写入的数据从文件末尾开始。
FileMode.UPDATE
设置文件打开方式为读写。若文件不存在,则创建之。设置该模式通常用于随机读写访问文件。可以从文件的任意位置读取,写入数据时,只有写入位置的存在字节被覆盖,其他所有字节不受影响。
2. position
该属性决定下一个数据读写操作进行的位置。
在读写操作前,设置position属性为文件中的有效位置,比如:
var myFile:File = File.documentsDirectory.resolvePath("Mousebomb/site.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.UPDATE);
myFileStream.position = 8;
myFileStream.writeUTFBytes("hello");
该例在位置8处写入UTF编码的字符串“hello”
新打开的FileStream对象的position值为0,在读文件操作前,position的值必最小为0并小于文件总字节数。
position的值仅会在以下情况下改变:
直接设置该属性值
执行读取操作
执行写入操作
当执行读/写操作时,position的值会立即自增读/写的字节数,再次执行读/写操作时会从新的position位置开始:
var myFile:File = File.documentsDirectory.resolvePath("Mousebomb/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.UPDATE);
myFileStream.position = 4000;
trace(myFileStream.position); // 4000
myFileStream.writeBytes(myByteArray, 0, 200);
trace(myFileStream.position); // 4200
position有一个例外:若文件打开模式设置为append(追加模式),则position属性不会随着写操作变化。在追加模式下,数据总是往文件末尾写,与position无关。
异步方式打开文件,写数据操作在下一行代码执行时并没有结束。这怎么办呢?没关系,你可以按顺序的调用多个异步操作,AIR运行环境会逐个执行:
var myFile:File = File.documentsDirectory.resolvePath("Mousebomb/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.openAsync(myFile, FileMode.WRITE);
myFileStream.writeUTFBytes("hello");
myFileStream.writeUTFBytes("world");
myFileStream.addEventListener(Event.CLOSE, closeHandler);
myFileStream.close();
trace("started.");
closeHandler(event:Event):void
{
trace("finished.");
}
该例会输出:
started.
finished.
你可以在异步读写操作调用后,立即设置position的值,下次读写操作将换作从那个位置开始。比如:
var myFile:File = File.documentsDirectory.resolvePath("Mousebomb/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.openAsync(myFile, FileMode.UPDATE);
myFileStream.position = 4000;
trace(myFileStream.position); // 4000
myFileStream.writeBytes(myByteArray, 0, 200);
myFileStream.position = 300;
trace(myFileStream.position); // 300
3. 根据数据格式,选择合适的读写操作
硬盘上的每个文件都是字节集合。在AS中,文件中的数据总是可以描述为ByteArray.比如下面的代码把文件数据读取到bytes这个ByteArray中:
var myFile:File = File.documentsDirectory.resolvePath("Mousebomb/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(Event.COMPLETE, completed);
myFileStream.openAsync(myFile, FileMode.READ);
var bytes:ByteArray = new ByteArray();
function completeHandler(event:Event):void
{
myFileStream.readBytes(bytes, 0, myFileStream.bytesAvailable);
}
下面的代码把数据从bytes这个ByteArray中写入文件:
var myFile:File = File.documentsDirectory.resolvePath("Mousebomb/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.open(myFile, FileMode.WRITE);
myFileStream.writeBytes(bytes, 0, bytes.length);
往往我们并不希望把数据作ByteArray处理,有时候要处理的文件是特定格式,比如文件中的数据是字符串。因此FileStream类也包含ByteArray以外的数据格式读写方法,比如readMultiByte()方法,可将文件读取暂存为字符串,如下代码:
var myFile:File = File.documentsDirectory.resolvePath("Mousebomb/test.txt");
var myFileStream:FileStream = new FileStream();
myFileStream.addEventListener(Event.COMPLETE, completed);
myFileStream.openAsync(myFile, FileMode.READ);
var str:String = "";
function completeHandler(event:Event):void
{
str = myFileStream.readMultiByte(myFileStream.bytesAvailable, "iso-8859-1");
}
readMultiByte()的第二个参数(本例中为“iso-8859-1”)指定了ActionScript用来解释的文本格式。ActionScript支持通用字符集编码,具体罗列在http://livedocs.macromedia.com/flex/2/langref/charset-codes.html
FileStream 类还具有readUTFBytes()方法,从读缓存中以UTF-8字符集读取数据。由于UTF8字符集为可变长,读缓存末尾数据并不一定是完整字符,所 以不要在处理progress 事件的方法中使用readUTFBytes()方法(用readMultiByte()读取可变长字符编码也应遵循此项),而应在FileStream的 complete事件发生时读取完整数据集。
同样,有类似的写操作writeMultiByte()和writeUTFBytes(),用来处理字符串对象和文本文件。
readUTF()和writeUTF()方法同样是读写文本数据,不过它们假定文本数据在指定文本数据长度之前,该文本数据是不在标准文本文件里普遍应用的。
有些UTF编码文本文件以一个UTF-BOM(Byte Order Mark)字符开头,像编码格式(如UTF16和UTF32)一样,也声明字节序。
readObject() 和writeObject()方法便于为复杂AS对象存取数据,数据作AMF(ActionScript. Message Format)编码,此格式为ActionScript私有,AIR、Flash Player、Flash Media Server、Flex Data Services以外的程序都没有操作该格式的内建API。
此外还有一些读写操作,像readDouble()和writeDouble()之类的,使用它们需确保所操作文件格式与之对应。
一般的文件结构往往比文本文件要复杂的多。比如mp3文件包含只能被mp3解压解码算法解释的压缩数据格式。其他文件,像图片、数据库、应用程序档案等等都有不同的结构,要想用AS操作它们的数据,得对其结构十分了解。
至此,学习笔记《AIR文件操作》结束。所有知识点来自:官方文档。
(本文若有不当之处,敬请指出。)
参考文献:http://livedocs.adobe.com/air/1/devappsflash/help.html?content=dg_part_6_1.html
http://livedocs.macromedia.com/flex/2/langref/charset-codes.html
http://www.adobe.com/go/learn_air_aslr
文章来自:http://www.flashas.net/html/air/20091005/4593.html
发表评论
-
ActionScript 类中属性的 PropertyChangeEvent
2011-10-28 10:08 910SWF: ××××××××××××× ... -
Flex 同时监听单击和双击事件
2011-10-27 16:30 1810有时我们在一些应用实例中可能会遇到这么一种需求:同一个组件,比 ... -
Blazeds数据推送和消息机制
2011-10-19 10:06 1763Flex 通过开源的BlazeDS消息服务来支持订阅及 ... -
blazeds通道、端点配置
2011-10-19 09:59 1208http://bhsc-happy.iteye.com/bl ... -
Flex4 Error #2032 Stream Error的解决方式 .
2011-10-18 09:30 7043在flex程序初始化默认加载滚动条还没出来时就报了Error ... -
flex文件流方式传输介绍 file filestream
2011-10-17 11:03 2381http://www.flashas.net/html/air ... -
显示对象平滑移动--本站转载
2011-09-30 17:11 787http://www.iteye.com/topic/1624 ...
相关推荐
Cisco-vWLC-AIR-CTVM-K9-7-6-120-0.ova
AIR-PolSAR-Seg数据集
airplay协议,编译工具 VS2017 苹果手机投屏源码。 开源项目来源:...1)删除了一个工程,2)删除了一些文件,3)修改一些目录结构 4)初始化的修改了屏幕比例。5)修改编译工具为vs2017和SDK。
本文将深入探讨思科AP固件的版本"AIR-K9-ME-8-9-111-0.zip"及其对AP1832和AP3800等型号的影响。 首先,我们要明确固件的作用。固件是嵌入在硬件设备中的软件,负责控制和协调设备的功能。对于思科AP而言,固件更新...
AIR-CT2500-K9-8-5-182-0.aes WLC 2504固件,配合AIR-CT2500-AP_BUNDLE-K9-8-5-182-0.aes一起使用 MD5 Checksum : 0ec0927df061c754ebbd9c5baa9047ad SHA512 Checksum : 8de868143326d027b175f99801287b7e65d0d4...
思科AIR-CT5500-K9-8-0-121控制器8.0镜像文件,需要的请下载
Virtual Wireless Controller 小公司版本 带有 60 天评估许可证的 Cisco 无线局域网小型虚拟控制器安装。 Release 8.5.171.0 思科虚拟控制器,vWLC,AIR_CTVM-K9_8_5_171...Modules: AIR-RM3010L-x-K9 and AIR-RM3000M
AIR-CTVM-K9-8-5-131-0.aes 299.13 MB AIR_CTVM_LARGE-K9_8_5_131_0.aes 299.12 MB AIR-CTVM-K9-8-3-143-0.aes 294.47 MB AIR_CTVM_LARGE-K9_8_3_143_0.aes 294.47 MB AIR-CTVM-K9-8-7-106-0.aes 250.76 MB AIR_CTVM...
此升级包包含两个关键文件:"AIR-CT5500-K9-8-5-161-0.aes"和"AIR-CT5500-AP_BUNDLE-K9-8-5-161-0.aes"。前者是WLC固件更新文件,后者是AP固件补充包。这两个文件都采用AES加密,以确保数据的安全性。 升级WLC固件...
of air-to-ground wireless services. These applications include the rapid recovery of damaged terrestrial wireless infrastructure due to a natural disaster, as well as the fulfillment of sudden ...
Virtual Wireless Controller Release 8.10.130 最新版本的虚拟控制器, 小公司版本,非large,好像支持最大200AP
CISCO AIR-CT2504 Cisco 2504 Wireless Controller AIR-CT2500-K9-7-5-102-0.aes 本分卷由2345好压(Haozip)生成,请使用2345好压来解压。 分卷文件共有以下3个: AIR-CT2500-K9-7-5-102-0.haozip01.7z AIR-CT...
标题"AIR-AP1830-K9-ME-8-10-130-0.zip"暗示了这是一个与思科(Cisco)无线接入点(Access Point, AP)相关的软件更新或固件包。"AIR"是思科无线产品的前缀,"AP1830"指的是思科的Aironet 1830系列接入点,这是一个...
压缩包子文件的文件名称列表只有一项:"AIR-AP3800-K9-ME-8-10-130-0",这通常代表固件升级文件的完整名称。这个文件很可能是一个.bin或.iso格式的镜像文件,用户可以通过TFTP(Trivial File Transfer Protocol)...
CISCO AIR-CT2504 Cisco 2504 Wireless Controller AIR-CT2500-K9-7-5-102-0.aes 本分卷由2345好压(Haozip)生成,请使用2345好压来解压。 分卷文件共有以下3个: AIR-CT2500-K9-7-5-102-0.haozip01.7z AIR-CT...
需要配合AIR-CT2500-K9-8-5-182-0.aes一起使用 MD5 Checksum : 304e1e7e0ed953da1fe447f3ef897825 SHA512 Checksum : 3bcb44091d79402eeb695b46cdf76611ea76aa2a78230662ce895a77f5243bfcdab030378c89c2e2b08da8cc...
AIR-AP1830-K9-8-2-166-0.tar,是cisco AP1830系列的IOS软件,可以配置成ME模式,欢迎大家下载
思科2504最新控制器固件AIR-CT2500-K9-8-5-161-0最新也是最终的固件,8.0以上版本可以直接升级,7.0版本需要先升级到AIR-CT2500-K9-8-0-152-0.aes过渡版本。
思科官网Downloads Home / Wireless / Access Points / Aironet 2800 Series Access ...1、AIR-AP2800-K9-ME-8-10-185-0.tar(轻量级接入点进行转换ios文件) 2、AIR-AP2800-K9-ME-8-10-185-0.zip(软件接入点映像捆绑包)
《使用Air-Kinect-Gesture-Lib实现AIR中的Kinect体感交互》 在现代的交互设计中,Kinect作为一款先进的体感设备,已经广泛应用于游戏、教育、医疗等多个领域,提供了非接触式的人机交互体验。对于Adobe AIR开发者来...