Archive for the ‘AIR 迷你教程’ Category

Posted by Kevin Luo at 21 January 2010

Category: AIR 迷你教程

Tags: ,

AIR 2.0 有很多令人期待和振奋的功能,使得AIR向成熟的桌面应用程序开发环境又进了一大步。上一篇文章里介绍了ServerSocket的用法,这篇教程中将向大家介绍NativeProcess,在AIR2.0中我们可以使用程序默认的打开方式直接打开一个外部的应用程序 (file.openWithDefaultApplication()) 或者 通过今天要讲的启动进程方式运行一个程序。

AIR与本地应用程序的交互是AIR 2.0的一个重要更新,这个功能的实现可以帮助我们做到在AIR 1.5时代很难完成的事情,比如我在项目中就需要操作一些硬件,但AIR不能直接操作端口,所以只能借助其他的小程序来实现,现在我们就可以很容易的操作这些小程序以达到操作硬件的目的,而Flex (AIR)与JAVA的结合很早就已经开始了,但由于早期AIR的局限性,想要把JAVA直接部署在客户端还是比较麻烦的事情,但是从AIR2.0开始我们不用担心了。现在我们用很简单的方式就可以在AIR程序中集成TOMCAT, 一次性的将后台与AIR部署到客户端。

程序的原版(Flash Builder 4版)同样是从http://coenraets.org/获得,有兴趣的朋友可以关注这个博客。我的例子仍然使用FLEX 3.

Demo过程

  1. 下载安装 AIR 2.0 beta runtime.
  2. 下载AIRAppWithEmbeddedTomcat..exe 或者 AIRAppWithEmbeddedTomcat.dmg (NativeProcess 必须在程序发布为相应平台的应用程序后才可以使用,发布的方法这里就不介绍了,可以参看http://help.adobe.com/en_US/FlashPlatform/develop/air/building_apps/WS789ea67d3e73a8b22388411123785d839c-8000.html)
  3. 安装运行AIRAppWithEmbeddedTomcat.exe, 修改JAVA_HOME,如果默认的路径不对
  4. 点击 “启动” 可以开启TOMCAT(端口是8080)。在JSP实例和RemoteObject实例中可以看见加载JSP页面和使用RemoteObject获取数据的测试。

(more…)

Posted by Kevin Luo at 6 January 2010

Category: AIR 迷你教程, 未分类

Tags: ,

AIR 2.0 一个非常重要的更新是支持了对Socket的监听,包括TCP (ServerSocket)以及UDP(DatagramSocket)。另外也支持了以UDP方式对外发送信息。这两个功能的增加无疑大大的增加了AIR的应用范围,比如………..这一下想个具体的还是比较困难,比如协作型的应用程序。

这篇教程将使用ServerSocket功能做一个HTML服务器,这个不是我原创的,是看到一个老外写的,觉得很有意思,是一个ServerSocket的好例子,原文在 http://coenraets.org/blog/2009/12/air-2-0-web-server-using-the-new-server-socket-api/. 原文是Flash Builder 4 版本的,这里我给大家的是Flex 3版本, 使用源代码请先下载AIR 2.0 SDK

Demo过程

  1. 下载安装 AIR 2.0 beta runtime.
  2. 下载MiniAIRWebServer.air
  3. 安装运行 MiniAIRWebServer.air.
  4. 运行 http://localhost:8765/HelloWorld.html (端口以你在运行MiniAIRWebServer.air后输入的为准, 注意安装MiniAIRWebServer.air后安装文件夹下的webroot/HelloWorld.html, 我们运行的就是这个文件)

运行效果如下:

airserver

源代码

?View Code ACTIONSCRIPT3
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" close="closeHandler()" creationComplete="init()">
	<mx:Script>
		<![CDATA[
			import flash.events.Event;
            import flash.events.ProgressEvent;
            import flash.events.ServerSocketConnectEvent;
            import flash.net.ServerSocket;
            import flash.net.Socket;
            import flash.utils.ByteArray;
 
            import mx.controls.Alert;
 
 
            //ServerSocket,用于监听TCP下的链接
            private var serverSocket:ServerSocket;
 
            private var mimeTypes:Object = new Object();
 
            private function init():void
            {
                // 支持的类型
                mimeTypes[".css"]     = "text/css";
                mimeTypes[".gif"]     = "image/gif";
                mimeTypes[".htm"]     = "text/html";
                mimeTypes[".html"]     = "text/html";
                mimeTypes[".ico"]     = "image/x-icon";
                mimeTypes[".jpg"]     = "image/jpeg";
                mimeTypes[".js"]     = "application/x-javascript";
                mimeTypes[".png"]     = "image/png";
 
                // 初始化服务器文件夹
                var webroot:File = File.applicationStorageDirectory.resolvePath("webroot");
                if (!webroot.exists)
                {
                    File.applicationDirectory.resolvePath("webroot").copyTo(webroot);
                }
            }
 
            private function listen():void
            {
                try
                {
 
                    serverSocket = new ServerSocket();
                    //监听链接
                    serverSocket.addEventListener(Event.CONNECT, socketConnectHandler);
                    //绑定端口
                    serverSocket.bind(Number(port.text));
                    //开始
                    serverSocket.listen();
                    log.text += "正在监听 " + port.text + "端口...\n";
                }
                catch (error:Error)
                {
                    Alert.show("端口 " + port.text + 
                        " 也许正在被使用,请尝试另一个端口.\n(" +
                        error.message +")", "错误");
                }
            }
 
            private function socketConnectHandler(event:ServerSocketConnectEvent):void
            {
                var socket:Socket = event.socket;
                //监听数据
                socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
            }
 
            private function socketDataHandler(event:ProgressEvent):void
            {
                try
                {
                    var socket:Socket = event.target as Socket;
                    var bytes:ByteArray = new ByteArray();
                    socket.readBytes(bytes);
                    var request:String = "" + bytes;
                    log.text += request;
                    var filePath:String = request.substring(4, request.indexOf("HTTP/") - 1);
                    var file:File = File.applicationStorageDirectory.resolvePath("webroot" + filePath);
                    if (file.exists && !file.isDirectory)
                    {
                        var stream:FileStream = new FileStream();
                        stream.open( file, FileMode.READ );
                        var content:ByteArray = new ByteArray();
                        stream.readBytes(content);
                        stream.close();
                        socket.writeUTFBytes("HTTP/1.1 200 OK\n");
                        socket.writeUTFBytes("Content-Type: " + getMimeType(filePath) + "\n\n");
                        socket.writeBytes(content);
                    }
                    else
                    {
                        socket.writeUTFBytes("HTTP/1.1 404 Not Found\n");
                        socket.writeUTFBytes("Content-Type: text/html\n\n");
                        socket.writeUTFBytes("<html><body><h2>Page Not Found</h2></body></html>");
                    }
                    socket.flush();
                    socket.close();
                }
                catch (error:Error)
                {
                    Alert.show(error.message, "错误");
                }
            }
 
            private function getMimeType(path:String):String
            {
                var mimeType:String;
                var index:int = path.lastIndexOf(".");
                if (index > -1)
                {
                    mimeType = mimeTypes[path.substring(index)];
                }
                return mimeType == null ? "text/html" : mimeType;
            }
 
 
            private function closeHandler():void{
            	if(serverSocket){
            		serverSocket.close()
            	}
 
            }
		]]>
	</mx:Script>
 
	<mx:HBox verticalAlign="middle">
        <mx:Label text="Port:"/>
        <mx:TextInput id="port" text="8765" width="50"/>
        <mx:Button label="Listen" click="listen()"/>
    </mx:HBox>
 
    <mx:TextArea id="log" width="100%" height="100%" />
</mx:WindowedApplication>

下载:

MIniAIRWebServer.air (305) MIniAIRWebServer.zip (309)

Posted by Kevin Luo at 12 February 2009

Category: AIR 迷你教程

Tags: ,

实现DataGird行颜色的改变不难,网上也有很多类似的教程,不过有的太罗嗦,有的说的又太简单,我稍微折中了一下。

首先继承DataGrid做一点简单的扩展。扩展的目的是:

  1. 添加一个rowColorFunction,根据当前行的值设置行的颜色,用法与labelFunction一样。
  2. 覆写drawRowBackground, 让其能用rowColorFunction返回的颜色设置当前行。

附件的RowColorDataGrid.as 是国外一个家伙写的,我没改(实在没什么可改的了),只添加了注释帮助大家理解。

下面是一个简单的Demo, 将check box钩中的行高亮显示: (more…)

Posted by Kevin Luo at 2 January 2009

Category: AIR 迷你教程

Tags: ,

AIR与Flex web应用的另一区别在于可以动态监测网络状态,可以让开发者在网络连通或断线时用不同的方式处理程序,在Demo中我将用以下情况来表现AIR的离线与在线应用。

1. 用户在文本框中输入内容。文本框下方的保存按钮会动态显示当前网络状态: (在线)保存与(离线)保存.
2. 在用户点击保存按钮时如果网络在线,将对话框内容保存在服务器。
3. 如果保存时处于断线状态,将内容保存在本地文件中。
4. 当网络恢复时检查本地文件,如果有已经保存的内容,将内容传入服务器。

源代码很简单,不到100行,大家可以在最下方下载。现在我开始讲解

Demo操作方法

1. 按装运行demo,如果网络连接正常,你会看到文本框下的按钮为 (在线) 保存。
2. 输入任意信息,点击 (在线)保存 。你会看倒信息 “内容已上传服务器”。
3. 切断网络。大概3-5秒后你会看到文本框下方按钮变为(离线)保存。
4. 点击保存,你会看倒信息“内容已经在本地保存,会在下次连线时自动上传到服务器”。
5. 接痛网络,大概3--5秒后你会看倒信息 “缓存内容已上传服务器”。
6. Demo结束。 (more…)

Posted by Kevin Luo at 2 January 2009

Category: AIR 迷你教程

Tags: ,

接上一篇教程,我们来扩展一些内容。

Demo内容

1. 保存文本框内容到指定路径,创建名为saveFileDemo.xml的文件。
2. 读取txt与xml类型文件到文本框。
3. 重新以文本框的内容更新打开的文件。 (more…)

Posted by Kevin Luo at 2 January 2009

Category: AIR 迷你教程

Tags: ,

买了战争机器2,写完教程准备杀到睡觉,现在先做第一步,写教程。AIR的文件操作不难,看完教程应该可以满足你对文件的所有基本操作。这篇教程主要以实际操作中遇到的情况来讲解

我们想想文件操作都会有什么内容,无非是创建,修改,删除,移动,拷贝。在这个过程中我们会涉及到一些周边的操作,比如文件夹,文件选择器,文件列表,文件信息获取等。 我就围绕创建,修改,删除,移动,拷贝来展开我们的教程。因为内容比较多,基于迷你教程每篇都短小,易读的原则。我分为两篇,今天先讲第一篇,基本的操作,下一篇我再加入上面所说周边的操作相对深一步的讲解。

Air的文件操做主要涉及两个类,FIle和FileStream。一般来说我们不会直接以文本形式保存文件,那样的内容不易于修改,所以这里我以xml 文件为例。

Note: 下面所有的function可以直接复制到你的代码中运行 (more…)

Posted by Kevin Luo at 2 January 2009

Category: AIR 迷你教程

Tags: ,

今天说一下AIR中的window, 作为桌面应用,免不了会有多窗口存在的可能。所以这也是AIR于Flex web的另一区别。flex web应用的“窗口”都是内部窗口,不管你怎么拖拽它也不会超出flash player的范围。而我们今天说的air中的窗口,是没有范围限制的,任一窗口都可以说是一个“独立”的存在,不受主程序窗口的限制。

Demo主要有以下功能

1. 简单继承window类创建MyWindow。加入parentWindow属性以及advOpen()方法, 设置MyWindow默认样式。
2. 从主程序中弹出窗口1,从窗口1中弹出窗口2。每个窗口里有image和button
3. 窗口1可以关闭主程序窗口,窗口2可以关闭窗口1。(关闭父窗口) (more…)

Posted by Kevin Luo at 2 January 2009

Category: AIR 迷你教程

Tags: ,

这个教程主要针对对flex有一定基础,准备开始AIR开发的朋友。由于AIR是针对桌面应用程序,所以相对于flex的web应用,自然就多出了对应用程序窗口的控制。而 AIR的一大特点就是允许开发者使用自定义的窗口代替系统窗口从而使开发者对程序UI的设计更加随心所欲,设计出独具个性风格的跨平台的桌面应用程序。

罗嗦的话到次为止,下面正式开始主题,本教程主要实现了以下功能。

1. 屏蔽系统窗口、 flash窗口、窗口底部状态栏。使用自定义窗口。
2. 对自定义窗口的缩放、移动、关闭。 (more…)

Posted by Kevin Luo at 2 January 2009

Category: AIR 迷你教程

Tags: ,

这篇教程算是AIR的 Hello world,写给那些知道一点AIR,想要开始AIR开发的人。读这篇教程你可以没有任何Flex的基础,我会告诉你如何创建你的第一个项目,并且发布一个HelloWorld程序。

下面我们开始讲解以下的内容。

1. 准备工作。
2. 第一个 AIR程序(编写、运行、调试)
3. 发布AIR程序。
4. 安装已发布的AIR安装包。

1.准备工作。

AIR 的开发环境非常简单,你唯一需要的就是FlexBuilder3,下载地址我就不提供了,只需要在google中搜索”Flex builder3 下载”,你会得到一大把地址。 Flexbuilder的安装也很简单,直接运行安装程序,然后一路按照导航菜单下去既可。 (more…)

Posted by Kevin Luo at 2 January 2009

Category: AIR 迷你教程

Tags:

看了Moon和Grubby两场比赛。看的很爽,写点有意思的,用javascript可以获取本地ip,这个我就先不说了,我说说怎么能通过ip获取城市,能获取城市的话用处就比较大了,比如……

现在说正题。获取城市最大的问题是ip对应城市数据库,我们自己建这个数据库的话太麻烦。杂办呢,网上有很多可以根据ip查城市的网站,我们就用他们。首先找一个速度比较快的ip地址查询网站。我找的是 www.ipxxx.com(大家在源代码看吧,写出来成做广告了)。接下来确定三步

1. 看网站的结果是怎么得到的,经过观察发现上述网站是通过get查询,那就好办了。
2. 看看结果页面,因为网站不会给我们提供数据源的,所以我们要从结果页面找到我们想要的东西。上述网站的结果页面很干净,过滤很方便。
3. 确定它的首页没有版权信息说不准从外部直接访问某某页面。

(more…)