存档

文章标签 ‘AIR’

AIR2对HTML5的支持力度

2010年6月20日 ColorHook 没有评论

html5test是一个测试浏览器对HTML5支持情况的一个web应用。在github上可以看到作者公布的一些测试结果。Adobe AIR2对HTML5, CSS3都提供了增强,我记得用html5test对AIR1.5的测试结果在20分左右,今天再用它测试一个AIR2。demo代码如下:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   creationComplete="init()">
	<fx:Script>
		<![CDATA[
			import spark.components.Group;
			import spark.core.SpriteVisualElement;
 
			protected var htmlLoader:HTMLLoader;
			protected var htmlUI:SpriteVisualElement;
 
			private function init():void{
				htmlLoader=new HTMLLoader();
				htmlLoader.width=800;
				htmlLoader.height=this.height;
				htmlLoader.load(new URLRequest('http://html5test.com'));
				htmlUI=new SpriteVisualElement();
				htmlUI.addChild(htmlLoader);
				this.addElement(htmlUI);
			}
		]]>
	</fx:Script>
</s:WindowedApplication>

运行后发现得分依然是很低——46分,跟Android 1.6的得分42分差不多,不过跟iPhone, iPod touch的120多的得分来比真是差的很远。Adobe官方有一篇文章讲到了AIR2对HTML, CSS, JavasScript的支持情况以及不支持的个中缘由。

分类: Develop & Design 标签: , ,

使用AIR2录制音频

2010年6月20日 ColorHook 没有评论

AIR2的正式版总算是出来了,前些天SDK也放出来了,于是就鼓捣一下它的一些新特性,其中一个特性就是录制Microphone,本地录制,本地存储,不需要FMS的协助。

为了完成这个录制Microphone的功能,我们需要先做如下事情:

  1. 下载AIR2 SDK并覆盖到Flash Builder的SDK中。
  2. 下载adobe官方用于保存WAV音频的开源库WAVWriter

接下来,新建一个AIR2工程,为了力求简单,本例中只用一个按钮,用于开始录制和停止录制。UI代码大致如下:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
				xmlns:s="library://ns.adobe.com/flex/spark" 
				xmlns:mx="library://ns.adobe.com/flex/mx"
			        creationComplete="init()">
        <fx:Script>
		<![CDATA[
                ]]>
	</fx:Script>
	<s:layout>
		<s:VerticalLayout paddingTop="10" horizontalAlign="center"/>
	</s:layout>
	<s:Button id='controlBtn' label="{controlBtnLabel}" click="clickHandler()"/>
</s:WindowedApplication>

下面开始编写逻辑代码,程序启动后,初始化Microphone, 设置音频文件保存路径。

import com.adobe.audio.format.WAVWriter;
import mx.controls.Alert;
 
protected var targetFile:File;
protected var microphone:Microphone;
protected var recordedData:ByteArray;
 
private var recordFlag:Boolean=false;
private static const START_RECORD:String='start recording';
private static const STOP_RECORD:String='stop recording';
[Bindable]public var controlBtnLabel:String=START_RECORD;
 
private function init():void{
	if(!Microphone.isSupported){
		Alert.show("Cannot find a Microphone");
		controlBtn.enabled=false;
		return;
	}
	targetFile = new File(File.desktopDirectory.nativePath+"/sound.mp3");
	microphone = Microphone.getMicrophone(0);
	microphone.setSilenceLevel(0);
	microphone.rate = 44;
}

然后处理按钮的动作,执行开始录制或停止录制操作。

private function clickHandler():void{
	if(recordFlag){
		controlBtnLabel=START_RECORD;
		recordFlag=false;
		this.stopRecording();
	}else{
		controlBtnLabel=STOP_RECORD;
		recordFlag=true;
		this.startRecording();
	}
}

开始录制时,先删除原有的音频文件,然后监听Microphone的SampleDataEvent.SAMPLE_DATA事件。

public function startRecording():void{
	if(targetFile.exists){
		targetFile.deleteFile();
	}
	recordedData=new ByteArray();
	microphone.addEventListener(SampleDataEvent.SAMPLE_DATA, onMicData);
}
 
private function onMicData(event:SampleDataEvent):void {
	recordedData.writeBytes(event.data);
}

当点击了停止录制时,移除Microphone的事件监听,并使用WAVWriter来生成一个音频文件。

public function stopRecording():void{
	microphone.removeEventListener(SampleDataEvent.SAMPLE_DATA, onMicData);
	saveWAV();
}
 
public function saveWAV():void{
	var wavWriter:WAVWriter = new WAVWriter();
	var stream:FileStream = new FileStream();
 
	recordedData.position = 0;
	wavWriter.numOfChannels = 1;
	wavWriter.sampleBitRate = 16;
	wavWriter.samplingRate = 44100;               
 
	stream.open( targetFile, FileMode.WRITE );
 
	wavWriter.processSamples( stream, recordedData, 44100, 1 );
	stream.close();
}
分类: Develop & Design 标签: ,

继AIR 2 RC1发布后更新Twitter Air至0.5

2010年5月13日 ColorHook 没有评论

数小时前,Adobe labs上放出AIR 2 RC1版本,从它的release note中可以发现不少的新特性:

  • 增强打印机的支持
  • 支持TLS/SSL socket通信
  • 支持外部存储设备检测
  • 具备高级网络功能,如secure sockets, UDP, 监听sockets
  • 支持本地代码集成
  • 使用默认应用程序打开文件
  • 多点触摸,手势支持
  • 增加获取麦克风数据的API
  • WebKit更新至支持HTML5/CSS3
  • 全局错误处理
  • 跨平台印刷能力提升
  • 安全性提升

虽然正式版还没有发布,不过已经告别Beta版本了,于是立刻利用这个最新的SDK编译了Twitter Air,并无bug修改和新功能加入。

关于Twitter Air无法启动的临时解决方案

2010年5月8日 ColorHook 没有评论

由于Adobe AIR 2 Beta 1目前已经不在被支持,所以基于该虚拟机创建的应用程序无法正确启动了,也包括我基本上每天都会使用的twitter客户端Twitter Air。不过把系统时间设置在5月1号及其以前则可以正常启动,但是每次启动之前都要修改系统时间,启动之后又要改回来,这样未免太繁琐,于是想写个一站式解决方案的脚本。

大致思路是这样的:

  1. 修改系统日期至2010年5月1日前某一天
  2. 启动Twitter Air
  3. 完全启动后(大约要1秒钟),改回系统时间

然后查阅Google baidu之,最后用Ruby完成脚本:

# 获得当前系统时间
now=Time::now
# 修改系统日期至2010年4月1日
system('date 2010-4-1')
# 创建一个进程执行Twitter Air
IO.popen("D:/AIR Program Files/Twitter Air/Twitter Air.exe",'r')
# 等待3秒让Twitter Air启动完全
sleep(3)
# 改回系统日期
system("date #{now.year}-#{now.mon}-#{now.day}")

使用seesmic-as3-xmpp更新renren状态

2010年4月11日 ColorHook 没有评论

seesmic-as3-xmppXMPP在ActionScript脚本上的一个实现。或许更加出名的是xiff这个框架,但是目前它并不支持TLS加密,所以需要要TLS支持的时候,更好用的是seesmic-as3-xmpp

人人网的IM工具校内通是基于XMPP协议进行通信的,根据网络上各路神仙的指示,使用基于XMPP框架的API可以很方便的更新一条状态。那么,在我使用桌面工具Twitter Air更新twitter的时候也可以同步更新到人人网,虽然人人网提供了REST API供应用程序调用,但是它们的验证机制明显需要花费更多的时间。

要想成功地连接到人人网,账号密码是必不可少的,人人网用户注册账号是Email地址,Email地址前的用户名无法保证唯一性,所以人人网用户都有一个额外的数字标识,就像QQ号一样,登陆之后可以从浏览器地址中得到该标识,例如http://www.renren.com/Home.do?id=9527这个用户的ID是9527。在进行XMPP连接前,要设置连接的JID, PASSWORD和SERVER三个值,RFC 3920中规定一个完整的JID应该是id@domain/resource这样一个形式,resource可以作为一个账户多处登陆的会话ID。按照这个规定,人人网用户9527的JID则是9527@talk.xiaonei.com。

下面在AIR中试着更新人人网的状态。打开Flash Builder新建一个AIR工程,将seesmic-as3-xmpp加入到编译路径,工程代码大致如下(MXML省略):

import com.hurlant.crypto.tls.TLSConfig;
import com.hurlant.crypto.tls.TLSEngine;
import com.hurlant.crypto.tls.TLSEvent;
import com.hurlant.crypto.tls.TLSSocket;
import com.seesmic.as3.xmpp.XMPP;
import com.seesmic.as3.xmpp.XMPPEvent;
 
var xmpp:XMPP;
private function init():void{
    xmpp=new XMPP("USER_ID@talk.xiaonei.com","USER_PASSWORD","talk.xiaonei.com");
    xmpp.addEventListener(XMPPEvent.SESSION, handleSession,false,0,true);
    xmpp.setupTLS(TLSEvent,TLSConfig,TLSEngine,TLSSocket);
    xmpp.connect();
}
private function handleSession(e:XMPPEvent):void {
    var status:String="a presence sent by AIR using XMPP protocol";
    xmpp.sendPresence(status);
}

设置好正确的ID和密码,编译运行,然后登陆人人网就会发现状态已经更新了。have fun!

Twitter Air V0.3 Released

2010年4月9日 ColorHook 没有评论

今天我终于升级了twitter客户端软件Twitter Air。相对于上一版本,V0.3加入了search user, follow user, unfollow user, change profile image等功能。虽然还没有支持direct message,但是这些功能已经基本满足日常需求了。

Twitter Air基于Adobe AIR技术构建,客户端需要安装Adobe AIR2 beta1,而目前AIR的正式版本为1.5,所以使用该软件时需要先手动安装Adobe AIR2 beta1,而安装了Adobe AIR2 beta2的用户可能需要先卸载AIR再安装Adobe AIR2 beta1。在这方面,我也十分恼火,希望Adobe尽快放出AIR2的正式版。

首先,苦于没有twitter账号朋友可以从这里进行注册:http://twitese.darkices.com/。

由于某些原因,目前国内无法直接访问twitter.com的REST API,所以Twitter Air使用了API Proxy来获取和更新数据。目前使用的API proxy是本人空间的一个地址:????(已移除) 我并不保证这个地址永久可用,所以在软件不能使用的情况下可以搜索其它可用的API Proxy

当然,如果你拥有一个国外的PHP空间,也可以搭建自己的API Proxy,具体方法请参考:http://code.google.com/p/tweetr/

最后要感谢一些开源框架的作者,没有他们的杰出贡献,Twitter Air也不能这么顺利的完成:

1. Robotlegs

Robotlegs是一个纯ActionScript(指不依赖Flex框架中的代码或特性)写成的MVC微型架构。它简单易用,为应用程序的设计提供一个清晰的层次结构,并且它的DI(Dependency Inject)特性容易让人对这个迷人的框架产生“依赖”。

2. tweetr

tweetr是一个twitter api的library, 它既包括一个AS3的API, 还包括一个PHP的API proxy,更新一条tweet,follow一个user都靠它们来实现了。

3. kingnarestyle

kingnarestyle是一套Flex skin, 这套黑色皮肤是十分受本人喜爱的,这里“严重”声明一下。

使用Merapi来在AIR和Java中通信

2010年2月2日 ColorHook 没有评论

Merapi是一个用于Java和AIR之间通信的桥接库。通过它可以极大的扩展AIR在本地的执行能力,当然前提是客户端不仅装有AIR运行时虚拟机,还需要安装有Java虚拟机。Merapi通过Socket来通信,使用Adobe的AMF作为数据传输格式。下面看看如何在Flash Builder中创建一个基于Adobe AIR的桌面软件。

在Java和ActionScript两端都存在一名为Bridge的类,它是一个Singleton,用来注册消息类型和发送消息。在这个例子中,AIR向Java端发送一个名为”flashEvent”的消息,消息内容是一个Dictionary实例;并且监听名为”javaEvent”的消息。

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="absolute" creationComplete="initApp()">
	<mx:Script>
	<![CDATA[
	import demo.JavaMessageHandler;
	import demo.SerializeMessageHandler;
	import merapi.Bridge;
	import merapi.messages.Message;
	import merapi.error.MerapiErrorMessage;
 
	private function initApp():void{
		//register a error handler
		new SerializeMessageHandler();
		//send a message
		var message:Message=new Message();
		message.type="flashEvent";
		var data:Dictionary=new Dictionary();
		data["name"]="colorhook";
		message.data=data;
		message.send();
		//register a message handler
		Bridge.getInstance().registerMessageHandler("javaEvent",
					new JavaMessageHandler());
	}
	]]>
	</mx:Script>
</mx:WindowedApplication>

CoreErrorHandler继承自EventDispatcher,实现了IMessageHandler接口,它在构造函数中就集成了错误处理。所以不需要显示的在Bridge中注册,而是构造一个实例就行了。SerializeMessageHandler继承自CoreErrorHandler,用来处理全局错误。

package demo{
 
	import merapi.handlers.mxml.CoreErrorHandler;	
	import mx.rpc.events.ResultEvent;
 
	public class SerializeMessageHandler extends CoreErrorHandler{
 
		public function SerializeMessageHandler(type:String=null){
			super(type);
			this.addEventListener(ResultEvent.RESULT,onMessageResult);
		}
 
		private function onMessageResult(event:ResultEvent):void{
			trace("SerializeMessageHandler:",event);
		}
	}
}

JavaMessageHandler实现了接口IMessageHandler,并在handleMessage方法中输出从Java中返回的数据。

package demo{
 
	import merapi.handlers.IMessageHandler;
	import merapi.messages.IMessage;
 
	public class JavaMessageHandler implements IMessageHandler{
 
		public function handleMessage(message:IMessage):void{
			trace(message.type);
			trace(message.data);
		}
	}
}

编译运行会发现控制台输出SerializeMessageHandler中的trace信息,因为目前还没有开启Java端的ServerSocket。所以下面来启动一个Java程序。首先调用Bridge.open()来启动ServerSocket。然后监听名为”flashEvent”的消息。

package demo;
 
import org.apache.log4j.Logger;
import merapi.Bridge;
 
public class Application {
 
	protected Logger logger=Logger.getLogger(Application.class);
 
	public Application(){
		logger.info("Application start");
		//open Bridge
		Bridge.open();
		//register a message handler
		Bridge.getInstance().registerMessageHandler("flashEvent",
			new AIRMessageHandler());
	}
 
	public static void main(String[] args){
		new Application();
	}
}

在消息处理器AIRMessageHandler中,输出来自Flash的数据,AMF将ActionScript中的Dictionary映射为Java中的Map。接受到数据之后,我们再从Java中发出一个Message,该Message携带了一个List类型的数据,在Flash中,它会被映射成Array类型。

package demo;
 
import java.util.*;
import org.apache.log4j.Logger;
import merapi.handlers.IMessageHandler;
import merapi.messages.IMessage;
import merapi.messages.Message;
 
public class AIRMessageHandler implements IMessageHandler {
 
	protected Logger logger=Logger.getLogger(AIRMessageHandler.class);
 
	@Override
	public void handleMessage(IMessage message) {
		//handle message
		logger.info(message.getType());
		Map<String,String> map=(Map<String, String>)message.getData();
		logger.info(map.get("name"));
		//send a new message
		Message newMessage=new Message();
		newMessage.setType("javaEvent");
		List<String> list=new ArrayList<String>();
		list.add("Flash Player");
		list.add("AIR");
		newMessage.setData(list);
		newMessage.send();
	}
}

Merapi在Java端用到了Spring, log4j和Adobe AMF相关包, 所以运行时要保证项目包含了这些jar包。可以从MerapiGoogle Code中得到这些包。

AIR2的发布,让我们在AIR和Java通信方面有了新的选择: flerry
flerry使用了AIR2的新特性NativeProcess,它直接创建了一个进程了执行Java程序。从其作者的blog上可以了解更多信息: http://www.riaspace.net/2010/01/flerry-flex-java-bridge-for-adobe-air-2-0/