— boreal-kiss.com

Archive
Tag "AIR"

[AIR] Nespresso Stock Checker

» [AIR] Nespresso Stock Checker

NESPRESSO(ネスプレッソ)のコーヒーカプセルの在庫確認専用アプリケーション。Nespressoが日本でどのぐらい知名度があるかしらないけどヨーロッパ、特にフランスでは利用者が多かったので作ってみた。Nespressoって直販してないから手持ちのコーヒーカプセルがなくなる前にオンラインなどで注文しないといけない。しかし注文時に最低注文数みたいなものがあるからどのカプセルを何個買うか組み合わせにめちゃくちゃ迷う。スターターキットでついてくる専用容器は各種類3コずつしかはいらないし(各種10個入りなのに)。このアプリケーションを使えばどれが減ってるか減る傾向にあるかが見た目でわかる。

アプリケーション自体はAjaxでよくある☆マークでスムーズに評点を付けれるやつをイメージした。内容はローカルのデータベースに保存。本当はChumbyなんかにセットしてエスプレッソマシンの横にでも設置できればよいのだろうけど先立つものがない。そもそもChumbyもっててNespressoでコーヒー飲んでる人が何人いるのか知らないけど。

Read More

どちらも同じ出版社の本だけど対照的。

  • Adobe Air in Action
    Adobe Air in Action

    AIRの良書。Flash, Flexに慣れ親しんだ人がAIRについてのみ知りたい場合などに最適。逆にFlashの知識が全くない状態でAIRをやってみようという場合には解読不能かも。Window, File system, Drag-and drop, SQLiteなど、AIR特有の機能に内容を絞っていて、しかもかなり原理的なところから説明しているので好感度が高い(FileStreamの進行状況を視覚化してあったり)。難点を挙げるとすると、これは出版社MANNINGの問題なんだけど、ここの本のレイアウト、文字スタイルが無駄に凝ってたり見出しごとにフォントかえてたりして見づらいんだよね。目がチカチカするっていうか。O’Reillyはそのへんさすがだと思う。

    » レーダーチャート評点

  • Flexible Rails: Flex 3 on Rails 2
    Flexible Rails: Flex 3 on Rails 2

    Flex + Rails。2008年に購入した本の中でぶっちぎり独走状態のクソ本。扱っている内容はFlex, Railsとも実践的で高度なのだが(Flex 3, Rails 2.0, RubyAMF, Cairngormなどを一緒に扱っている本はたぶん世の中にこれしかない)、著者の文章力がお粗末。自分の挙げた質問に脱線しまくったあげく見当違いな答えが書いてあったりして愕然とさせられる。要所要所でかいま見られる「この本への著者の愛」も読んでて非常に気持ち悪い。「TVゲームが超絶うまい小学生に書かかせたゲーム攻略本の文章」っていうとイメージ湧くかな。この本のせいで出版社のMANNINGのイメージがよろしくなくなった。

    » レーダーチャート評点

Read More

カスタムクラスオブジェクトをAIRのファイル読み書きで使用する方法(Flex環境)と注意点について。AMFのserialize/deserializeの話なのでNetConnectionなどにも応用可能だと思う。

使い方

  1. 保存したいクラスに[RemoteClass]メタタグを付ける(aliasの設定は必須ではない)。例えばcom.borealkiss.UserNameクラスを使いたい場合は以下のとおり。
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
        }
    }
  2. ローカルで保持されるのはクラスのパブリックプロパティ(or getters/setters)のみ。例えば以下の場合だとUserName.firstNameの情報を保持したままクラスオブジェクトがローカルに保存できるようになる。publicプロパティを使う場合は以下のとおり。
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
        }
    }

    getters/settersを使用する場合は以下のとおり。この場合setとget両方が定義されていないとローカル保存できない。

    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            private var _firstName:String;
    
            public function set firstName(value:String):void{
                _firstName = value;
            }
            public function get firstName():String{
                return _firstName;
            }
        }
    }
  3. publicまたはsetters/getters定義されているクラスプロパティは全て保存される。保存したくないプロパティには[Transient]メタタグを付ける。例えばUserName.firstNameはローカル保存したいが、UserName.lastNameプロパティは保存したくない場合は以下ように記述する。
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
            
            [Transient]
            public var lastName:String;
        }
    }

    getters/settersを使う場合は、get/setの定義直前に記述する。(privateプロパティ直前の記述は無効)

    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            private var _firstName:String;
            private var _lastName:String;
            
            public function set firstName(value:String):void{
                _firstName = value;
            }
            public function get firstName():String{
                return _firstName;
            }
            
            [Transient]
            public function set lastName(value:String):void{
                _lastName = value;
            }
            public function get lastName():String{
                return _lastName;
            }
        }
    }
  4. FileStream.writeObject()でローカルファイルに保存する。以下の例ではApplicationStorageDirectory (MacだとUsers/USERNAME/Library/Preferences/APPLICATION_ID/Local_Store/)の”username.data”ファイルに書き出される(UserName.lastNameは[Transient]タグがあるので保存されない)。
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    import com.borealkiss.UserName;
    
    var user:UserName = new UserName();
    user.firstName = "Colin";
    user.lastname = "Moock";
    
    var f:File = File.applicationStorageDirectory.resolvePath("username.dat");
    var fs:FileStream = new FileStream();
    fs.open(f,FileMode.WRITE);
    fs.writeObject(user);
    fs.close();
  5. ローカルファイルからデータを取得する場合はFileStream.readObject()を使う。戻り値は型が指定されていないのでUserNameクラスにキャストする必要がある。
    var f:File = File.applicationStorageDirectory.resolvePath("username.dat");
    var result:UserName;
                
    if (f.exists){
        var fs:FileStream = new FileStream();
        fs.open(f,FileMode.READ);
        while (fs.bytesAvailable){
            result = fs.readObject() as UserName;
        }
        fs.close();
    }
    
    trace(result.firstName);//Colin
    trace(result.lastName);//null

注意点

  1. FileStream.readObject()でクラスオブジェクトを取得するとき、クラスオブジェクトのコンストラクタが(引数の設定ができないにも関わらず)必ず呼ばれる。そのためコンストラクタがデフォルト値を持たない引数を持つ場合はFileStream.readObject()を使うとエラーになる。例えば以下の場合、クラスオブジェクトはローカル保存はできるがローカルから呼び出すことができない。
    //FileStream.readObject()できない場合
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
            public var lastName:String;
            
            /**
             * Constructor
             */ 
            public function UserName(firstName:String,lastName:String){
                this.firstName = firstName;
                this.lastName = lastName;
            }
        }
    }

    コンストラクタが引数を持たないか、または引数にデフォルト値が設定されている場合は大丈夫。

    //FileStream.readObject()できる場合
    package com.borealkiss{
        
        [RemoteClass]
        public class UserName{
            public var firstName:String;
            public var lastName:String;
            
            /**
             * Constructor
             */ 
            public function UserName(firstName:String="",lastName:String=""){
                this.firstName = firstName;
                this.lastName = lastName;
            }
        }
    }
  2. FileStream.readObject()ではコンストラクタが呼ばれた後、ローカル保存されている値がプロパティに設定される。
Read More

NativeDragEvent.NATIVE_DRAG_DROPイベントで、ドロップされた画像ファイルのビットマップデータを取得したい。MacとWindowsともに動作する方法を模索した。

1. Clipboardデータから直接取得する

Macの場合以下の一行でJPG, GIF, PNG, BMP, ICOファイルのビットマップデータが直接取得できるが、Windowsだと取得できない。

//NativeDragEvent.NATIVE_DRAG_DROPのイベントリスナー
function onDragDrop(e:NativeDragEvent):void{
    var bmd:BitmapData = e.clipboard.getData(ClipboardFormats.BITMAP_FORMAT) 
                        as BitmapData;
}

2. Loader.load()を使用する

次にClipboard内のファイルパスをLoaderクラスに渡してLoaderクラスのプロパティ経由でビットマップデータを取得してみる。Macだと以下の方法で取得できるが、Windowsだと取得できない。

//NativeDragEvent.NATIVE_DRAG_DROPのイベントリスナー
function onDragDrop(e:NativeDragEvent):void{
    var path:String = e.clipboard.getData(ClipboardFormats.URL_FORMAT).toString();
    var loader:Loader = new Loader();
    loader.load(new URLRequest(path));
    loader.contentLoaderInfo.addEventListener(Event.INIT,onInit);
}

function onInit(e:Event):void{
    var bmd:BitmapData = e.target.content.bitmapData as BitmapData;
}

3. Loader.loadBytes()を使用する

結局Windows(とMac)でビットマップデータにアクセスするためにはどうすればよいかというと、一つの方法は(僕はこれしか成功していない)、ドロップされる画像ファイルに割り当てられたFileクラスオブジェクトのデータをByteArrayにしてからBitmapDataに変換してやることだ。この方法だとWindows、Macともにドロップされた画像ファイルのビットマップデータを取得できる。

//NativeDragEvent.NATIVE_DRAG_DROPのイベントリスナー
function onDragDrop(e:NativeDragEvent):void{
    var files:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT)
                        as Array;
    var f:File = files[0];
    var fs:FileStream = new FileStream();
    var ba:ByteArray = new ByteArray();
    fs.open(f,FileMode.READ);
    fs.readBytes(ba,0,fs.bytesAvailable);
    fs.close();

    var loader:Loader = new Loader();
    loader.loadBytes(ba);
    loader.contentLoaderInfo.addEventListener(Event.INIT,onInit);
}

function onInit(e:Event):void{
    var bmd:BitmapData = e.target.content.bitmapData as BitmapData;
}

ただしLoaderクラスを使うのでJPG, GIF, PNGファイルしか扱えない。BMPやICOファイルを扱いたい場合は、別途BMPDecoder – Spark projectICODecoder – Spark projectを使うとよい。

Read More

外部画像ファイルをアプリケーションにドロップしてやるとキャンバスに描画するように改良。キャンバスの解像度が16×16しかないのでファミコンの大昔のキャラクターやらfaviconあたりをつっこむときれいに描画するはず。お試しあれ。» [AIR] Dot3D

追記 2008/09/30

Windowsで機能していない模様。原因究明中。

追記 2008/10/01

Windowsでも機能するようにした。ただしファイルがJPG, PNG, GIF形式の場合のみ。

追記 2008/10/01

以下ライブラリのおかげでICO, BMP形式も描画可能になった。
BMPDecoder – Spark project
ICODecoder – Spark project

Read More

ドット絵エディターの3Dバージョン!!好きな角度に回転して画像保存(デスクトップにPNG形式で保存)できるのでドット絵マニアは使うといいね!今のところ16×16区画のみ。

» [AIR] Dot3D

追記 2008/09/25

背景(カラー)の表示・非表示機能を追加。ちょっとだけキャンバスを小さくした(500 -> 480 px)

Read More

AirUpdaterUI.mxml

なかなかシステマティックに完成したのでパッケージで公開。セールスポイントはAdobe AIR Update Frameworkの1/10以下のファイルサイズに収まっていること。あと今っぽくAjaxアニメーションで待ち時間を表示すること。AjaxローディングアイコンはAjaxload – Ajax loading gif generatorで作成した。暇なときにでも表示アイコンを増やそうと思う。

AIRアプリケーションのオートアップデートライブラリ(AirUpdater.as)にAjaxローディングアイコンを表示するUI(AirUpdaterUI.mxml)を組み込んだパッケージで以下の機能と利便性があります。

  1. AIRアプリケーションからそのアプリケーションの最新バージョンの有無をチェック
  2. 最新バージョンがあるようならその場でファイルをダウンロード、アップデートを行う(アプリケーションの上書き)。
  3. アップデート情報確認中、および実際のアップデート中にAjaxローディングアイコン(計8種類、選択可能)の表示
  4. アップデート情報のキャッシュを有効にすることでサーバーに負担をかけない設定が可能。
  5. 設定ActionScriptコマンドはわずか2行。
  6. わずか32kbと軽量 (Adobe AIR Update Frameworkは350kb)。

[AIR] AirUpdaterUI.mxml

Read More

Adobe Labsが提供しているAIRアプリケーションの自動更新機能と専用のUIを含んだ便利パッケージについて。実際の使用方法はAdobe AIR Update Frameworkを使ってみる – kwLogがわかりやすい。

長所

  • 更新情報のキャッシュが効く。ApplicationUpdaterUI.delayというプロパティ(defaultは1日)で最新アプリケーション情報を記述したファイルへのアクセス頻度をコントロールできる(ボタン連打されても無問題)。更新状況はSharedObjectに保存されている。Macだと以下。
    /Users/USERNAME/Library/Preferences/app_name/Local Store/ApplicationUpdater
    
  • 他言語に対応したリリースノートを定義できる。以下のように更新情報を定義しておくと、言語環境に応じてアップデート詳細の表示が変わる。
    <update xmlns="http://ns.adobe.com/air/framework/update/description/1.0">
        <version>2.0</version>
        <url>http://example.com/app_name.air</url>
        <description>
            <!--Release notes-->
            <text xml:lang="en">
                <![CDATA[
                    English description is here.
                ]]>
            </text>
            <text xml:lang="ja">
                <![CDATA[
                    日本語の更新情報はこちら。
                ]]>
            </text>
        </description>
    </update>
  • Adobeが提供しているだけあって見た目がAIR(のインストーラー)っぽい。

短所

  • UIのファイルサイズが結構でかい(~350kb)。元々ファイルサイズ2Mのアプリケーションなら気にならないかもしれないけど、550kbのアプリケーションが自動更新機能付けて900kbになるのは結構萎える。UI無しの選択肢もあることはある。
  • ダウンロードした最新版アプリケーションが上記SharedObject保存先に居座りっぱなし。

結論

導入する/しないのcriteriaは元のアプリケーションファイルサイズかなあ。UIにこだわらず作る気があれば完全に自作でもよいと思う。他言語対応は便利かも。

Read More

SimpleLogger update

[AIR] SimpleLogger ver. 1.07

  • mxパッケージ専用のクライアントSimpleLoggerMx.asを追加。
  • オートアップデート機能を追加。

Alertのデザイン変更ではまった。どうもAlert内部のボタンのデザインはAlertのプロパティbuttonStyleNameを変更してやらないといけないらしい(デフォルトはbuttonStyleName=”alertButtonStyle”)。上記の場合だと

/* alert_desin.css */

Alert{
    buttonStyleName: "alertButton";
    fontWeight: normal;   
    color: #FFFFFF;
    backgroundColor: #101010;
    borderStyle: solid;
    cornerRadius: 4;
}

.alertButton{
    textRollOverColor: #00FF00;
    color: #FFFFFF;
    themeColor: #00FF00;
    fillColors: #101010, #101010;
    borderColor : #101010;
    highlightAlphas: 0.0, 0.0;
    cornerRadius: 4;
    fontWeight: normal;
}

という設定にしてやってmxmlに埋め込んである。

<mx:Style source="alert_design.css" />

コンポーネントのCSSデザインはadobe – Flex 2 Style Explorerを使った。コンポーネントのデザインを動的に変更でき、変更したスタイル情報がその場にCSSとして表示されるので便利。

Read More

追記 2008/09/13

もう少し読みやすい文章(図付き)はこちら

追記 2008/09/16

すでにAdobe AIR Update Framework なんてものがあるじゃないか。。。仕組み的には同じっぽいのでまあ安心した。使い方は自動Update part2 (shin1)が詳しいのかな。

追記 2008/09/17

[AIR] Adobe AIR Update Frameworkを使ってみた – blog Boreal Kiss

___________________________

AIRアプリケーションのアップデート機能は汎用性が高いと思われたので専用のActionScriptライブラリを作った。このライブラリは、(このライブラリをインポート済みの)古いAIRアプリケーションから最新バージョン情報の有無をチェックして、もし最新バージョンがあるようならその場でアップデートを行う。ライブラリ以外に必要なのは以下の2ファイルで、それぞれweb上にアップロードしてあることが前提。

  • アプリケーションの最新バージョン
  • アプリケーション最新バージョンの設置先URLとそのバージョン情報を記述したXMLファイル

以下では上記の準備(1, 2)を行ってからライブラリの使い方(3)について説明している。

1. アプリケーション最新バージョンを作る

例えば最新バージョンのアプリケーション(latest_app.air, バージョン2.0と仮定)を以下のURLにアップロードしたと仮定。

http://example.com/latest_app.air

2. 最新バージョンチェック用のXMLファイルを作る

最新アプリケーションバージョンとそのファイル設置場所に関する情報を記述した以下のようなXMLファイル(update.xml)

<?xml version="1.0" encoding="UTF-8"?>
<application>
    <version>2.0</version>
    <download_url>http://example.com/latest_app.air</download_url>
</application>

を以下のURLにアップロードしたと仮定。

http://example.com/update.xml

3. ライブラリを使う

  1. ライブラリのダウンロード
  2. 古いAIRアプリケーション(例としてバージョン1.0)内にインポートしてAirUpdaterのインスタンスを作成。
    import com.borealkiss.fl.utils.AirUpdater;
    
    var updater:AirUpdater;
    updater = AirUpdater.getInstance("1.0",
                                     "http://example.com/update.xml",
                                     "version",
                                     "download_url");
  3. 上記引数は全てStringで一番前から順番に、(1)現在のアプリケーションバージョン、(2)バージョンチェック用XMLファイルのURL、(3)XMLファイル中の最新バージョンを記述しているノード名(<version>)、(4)XMLファイル中の最新バージョンのURLを記述しているノード名(<download_url>)、となっている。バージョンチェック用XMLファイル内のノード名は好き勝手つけれるが、必ずgetInstance()の引数名と一致させる必要がある。
  4. AirUpdater.check()でバージョンチェック開始。update.xmlの内容を解析して、現在のバージョンとXMLファイルに記述されたバージョンの数値の大小を比較して、(1)最新バージョンがある、(2)最新バージョンはない、(3)送信エラー(アクセス先URLにXMLファイルがない等)、の3通りの場合に対してイベントを返す。それぞれにイベントリスナーを設置。
    updater.check();
    
    //最新バージョンが存在する
    updater.addEventListener(AirUpdater.LATEST_VERSION_FOUND,onFound);
    
    //最新バージョンは存在しない(現在のものが最新)
    updater.addEventListener(AirUpdater.LATEST_VERSION_NOT_FOUND,onFound);
    
    //通信エラー
    updater.addEventListener(IOErrorEvent.IO_ERROR,onFound);
  5. あとは最新バージョンがある場合はAirUpdater.downloadUpdate()を行う。これで最新バージョンのアプリケーションをデスクトップにダウンロードし、現在立ち上げているアプリケーションを最新バージョンに書き換える。
    private function onFound(e:Event):void{
        switch(e.type){
            case AirUpdater.LATEST_VERSION_FOUND:
            updater.downloadUpdate();
            break;
                        
            case AirUpdater.LATEST_VERSION_NOT_FOUND:
            trace("No newer version found");
            break;
                        
            default:
            trace("Error");
    
    
        }
    }

その他注意点

  • 単純に数値の大きいものを最新バージョンと見なす。例えば上記の例の場合、1.0より2.0の方が最新ということになる。AirUpdaterに渡すバージョン情報とXMLファイル中のバージョン情報に数値以外が入っていると解析不能(例えばv2.5)。
  • アプリケーションの実際のバージョン情報を参照するわけではない。AirUpdaterに渡すバージョン数値とXMLファイル中のバージョン数値の大小を比較してアップデートを行う。
  • 最新バージョンをリリースするたびにバージョンチェック用のXMLファイルも修正する必要がある。
  • 同じアプリケーションID同士でないとアップデートできない。
Read More