初めてのAIRアプリケーションの作成
AIRアプリケーションに挑戦してみました。
javascript + html
actionscript + mxmlでも出来るみたいなんですが、
javascript + htmlで作成してみました。
だからって、こっちも十分な経験あるわけではありません。
仕様+ポイント
簡単なZipファイル解凍アプリケーションを作ることにしました。
- Drag&Drop対応
- オシャレというか、リッチな感じに
- メディアごとに解凍
これは、個人的に気に入っているアイデアですが、
指定した拡張子のファイルのみを解凍する、といったものです。
使いどころは微妙かもしれませんが。
zipファイルが階層構造を持つ場合は解凍に失敗します。
かつ、日本語ファイルは文字化けしたり、上手く解凍できない可能性があります。
この辺は以下に挙げるAdobe AIRのByteArrayのページを参照。
こんなのが出来ました
airファイルを以下にうpしました。
興味のある方は以下のリンクからダウンロードどうぞ。
http://firestorage.jp/download/ac7e3af2f823ea38db9df52556d1863e4d72113f
- ファイルは7-Zip圧縮されています。7-Zip Portableなどで解凍できます。
- Adobe AIRランタイムがインストールされている必要があります。Adobe AIRのAdobe AIRを今すぐインストールからインストールできます。
黒い部分をクリックすると、
例えば、musicなら、mp3,wav,ogg,m4aの拡張子を持つもののみ解凍します。
といっても、正規表現でチェックしているだけですが。
Zip部分にドラッグドロップすると、zipなら同じディレクトリに解凍します。
Zip部分をダブルクリックするとアプリケーションを終了します。
Drag&Dropに関して
八角研究所 : API で覚える Adobe AIR(5) - Adobe AIR ドラッグ&ドロップ API についてが参考になりました。
Zipファイルの解凍に関して
http://livedocs.adobe.com/air/1/devappshtml/help.html?content=ByteArrays_3.htmlが参考になりました。
というか、ほぼそのまま使ってます。
もっと、簡単にZipファイルを扱えればよかったのですが。
でも、Zipファイルのヘッダーのフォーマットについてもわかりやすく書かれているので、勉強になりました。
必要な分だけバイトを読み込み、必要な情報の位置にポジションをセットして読み込んでいるだけだとわかると楽しいものですね!
ただ、このページに載っている箇所で、uncompressに渡しているアルゴリズムオブジェクトはjavascriptから使う場合は、
CompressionAlgorithm.DEFLATE
ではなく、
air.CompressionAlgorithm.DEFLATE
とすることは注意です><
インターフェース
見た目はGIMPで適当に作りました。
application.xmlを設定してやることでガジェットのようなものを作ることができるようです。
このような見た目のアプリケーションのための設定はapplication.xmlで設定できます。
SimpleZipExtract.html
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body> <div id="ctype"> <img src="type-all.png"> </div> <div id="sze"> <img src="SimpleZipExtractUI.png"> </div> <script type="text/javascript" src="AIRAliases.js"></script> <script type="text/javascript" src="ZipExtract.js"></script> <script> function $(name){ return document.getElementById(name); } var type = { all : "app:/type-all.png", music: "app:/type-music.png", image: "app:/type-image.png", movie: "app:/type-movie.png", ptext: "app:/type-plain_text.png" }; var re = /\..+$/i; var ctype = $("ctype"); // add event listener ctype.addEventListener('mousedown', function changeType(){ var cur = ctype.getElementsByTagName('img').item(0); if (cur.src == type.all) { cur.src = type.music; ctype.replaceChild(cur, ctype.lastChild); re = /\.(?:mp3|wav|ogg|m4a)$/i; }else if (cur.src == type.music) { cur.src = type.image; ctype.replaceChild(cur, ctype.lastChild); re = /\.(?:jpe?g|png|tiff?|gif|bmp|dvi|pdf)$/i; }else if (cur.src == type.image) { cur.src = type.movie; ctype.replaceChild(cur, ctype.lastChild); re = /\.(?:wmv|rm|avi|mp4)$/i; }else if (cur.src == type.movie) { cur.src = type.ptext; ctype.replaceChild(cur, ctype.lastChild); re = /\.(?:txt|csv|html?|m?a?xml|js|as|rb|py|hs|scm|pl|pm|java|php|cp{,2}|sh|ml|css|tex)$/i; }else if(cur.src == type.ptext){ cur.src = type.all; ctype.replaceChild(cur, ctype.lastChild); re = /\..+$/i; } }); var sze = $("sze"); // register events sze.addEventListener("dragenter", onDragOver); sze.addEventListener("dragover", onDragOver); sze.addEventListener("drop", onDrop); // event handler function onDragOver(e){ e.preventDefault(); } function onDrop(e){ var cb = e.dataTransfer; // check if file is dropped var typeFileList = "application/x-vnd.adobe.air.file-list"; var file_ary = cb.getData(typeFileList); for (var i=0; i < file_ary.length; i++){ var resource = decodeURI(file_ary[i].url); resource.match(/(.+\/)(.+?\.(.+?))$/); if (RegExp.$3 == 'zip') { var dir = RegExp.$1; var basename = RegExp.$2; zipExtract(dir, basename, re); } } alert("Complete!"); } // allow drag sze.onmousedown = function(){ window.nativeWindow.startMove(); }; // allow exit sze.ondblclick = function(){ window.close(); }; </script> </body> </html>
ZipExtract.js
var bytes = new air.ByteArray(); // variables for reading fixed portion of file header var fileName = new String(); var flNameLength; var xfldLength; var offset; var compSize; var uncompSize; var compMethod; var signature; var output; // File variables for accessing .zip file var zStream = new air.FileStream(); function zipExtract(dir, basename, re) { var zfile = new air.File(dir + basename); zStream.open(zfile, air.FileMode.READ); bytes.endian = air.Endian.LITTLE_ENDIAN; while (zStream.position < zfile.size) { // read fixed metadata portion of local file header zStream.readBytes(bytes, 0, 30); bytes.position = 0; signature = bytes.readInt(); // if no longer reading data files, quit if (signature != 0x04034b50) { break; } bytes.position = 8; compMethod = bytes.readByte(); // store compression method (8 == Deflate) offset = 0; // stores length of variable portion of metadata bytes.position = 26; //offset to file name length flNameLength = bytes.readShort(); // store file name offset += flNameLength; //add length of file name bytes.position = 28; //offset to extra field length xfldLength = bytes.readShort(); offset += xfldLength; // add length of extra field // read variable length bytes between fixed-length header and compressed file data zStream.readBytes(bytes, 30, offset); bytes.position = 30; fileName = bytes.readUTFBytes(flNameLength); // read file name //output += fileName + "<br />"; // write file name to text area bytes.position = 18; compSize = bytes.readUnsignedInt(); // store size of compressed portion //output += "\tCompressed size is: " + compSize + '<br />'; bytes.position = 22; // offset to uncompressed size uncompSize = bytes.readUnsignedInt(); // store uncompressed size //output += "\tUncompressed size is:" + uncompSize + '<br />'; // read compressed file to offset 0 of bytes; for uncompressed files // the compressed and uncompresed size is the same zStream.readBytes(bytes, 0, compSize); if (fileName.search(re) == -1) // break if file type doesn't match { continue; } if (compMethod == 8) // if file is compressed, uncompress { bytes.uncompress(air.CompressionAlgorithm.DEFLATE); } var fullpath = dir + fileName; outFile(fullpath, bytes); // call outFile() to write out the file } // end of while loop } // end of init() method function outFile(fullpath, data) { var outFile = new air.File(fullpath); var outStream = new air.FileStream(); // open output file stream in WRITE mode outStream.open(outFile, air.FileMode.WRITE); // write out the file outStream.writeBytes(data, 0, data.length); // close it outStream.close(); }
突っ込みは歓迎です><!