AIR/Flexの最近のブログ記事

Adobe Flash Builder 4.6(x86) で、TF101 がプログラム実行可能なデバイスとして認識されない。

20130516_fb_device_none.jpg
「更新」ボタンを押すと、時々変なデバイスが表示される(シリアル番号に「asus-tf101」が表示されず、全然別のシリアル番号が表示される)のだが、そのデバイスを使おうとすると、

アプリケーションのインストール中にエラーが発生しました:
adb server is out of data. killing...

ADB server didn't ACK

* faild to start daemon *

error:

という内容のダイヤログが開き失敗。

むーん・・・

でも、ADT bundle 版の Eclipse からだと、TF101 が実行デバイスとして選べるんだよなあ・・・

20130516_android_device_select.jpg
・・・と思いつつ、ASUS Sync をアップデートして、ASUS Android USB Driver も更新したら、とうとう ADT bundle 版の Eclipse でも、TF101 見えなくなっちゃったけど(^^;

adb.exe が問題なのかと調べてみたところ、

C:\Program Files (x86)\ASUS\ASUS Sync\adb.exe

が実行されていた。
他にも、adb.exe はこんなにあった。

C:\usr\local\adt-bundle\sdk\platform-tools\adb.exe
C:\Program Files\Adobe\Adobe Flash Builder 4.7 (64 Bit)\eclipse\plugins\com.adobe.flash.compiler_4.7.0.349722\AIRSDK\lib\android\bin
C:\Program Files\Adobe\Adobe Flash Builder 4.7 (64 Bit)\sdks\4.6.0\lib\android\bin\adb.exe
C:\Program Files (x86)\Adobe\Adobe Flash Builder 4.6\sdks\4.6.0\lib\android\bin\adb.exe

ああ、なるほど、C:\usr\local\adt-bundle\sdk\platform-tools\adb.exe が実行されるようにしないといけないんだな・・・と思って path を通してみたけど、ASUS Sync が必ず C:\Program Files (x86)\ASUS\ASUS Sync\adb.exe を実行しちゃうな・・・

さて、ASUS Sync をアンインストールしてみるか・・・と今まさに思っているところ。

ホント、Android の開発も面倒くせえなあ(^^;
いやあ、びっくりしたわ。

現在、PC で動いている AIR アプリがあって、俺が Flash Builder 4.6(FB4.6)で作ったんだけど、それを iOS/Android 端末に移行する提案をしようと思ってる。
FB4.6 では Flex モバイルプロジェクトでスマホ用の AIR アプリが作れるので、PC 用に作ったソースやコンテンツの一部がそのまま利用出来るから、比較的簡単に移行できますよ・・・という話で。

まあ、AIR 開発には Aptana Studio 3 なんかも使えるけど、FB4.6 にはビジュアルデザイン機能っていう WYSIWYG 環境でデザインしながら開発が出来る機能があるので重宝してる。

20130515_AdobeFB46.jpg
で、今回、移行の調査のための「ちょいプロ」を作ってみるのに、Flash Builder 4.7(FB4.7)のお試し版を使ってみることにした。
最新バージョンの方が、より多くの機種に対応した SDK がついてくるんじゃないかなあ・・・と思って。

そしたら、なんか、ビジュアルデザイン機能への切り替えボタンが無いんですけど???

20130515_AdobeFB47.jpg
FB4.6 では、エディタ上部に「ソース」「デザイン」の切替ボタンがあるのに、FB4.7 だと無い。
あれれ??ビジュアルデザイン機能使うためのファイルがまだインストール出来てないとか、そういうことなんかなあ???と Adobe のサイトなどを調べていたら・・・


Q.Flash Builder 4.7には、Flash Builder 4.6に含まれていたFlexアプリケーション用のビジュアルデザインコンポーネントが含まれていますか?

A.Flash Builder 4.7は、Flash Builder 4.6以前のバ-ジョンで利用できたビジュアルデザイン機能をサポートしていません。Flexのビジュアルデザイン機能が必要な場合は、Flash Builder 4.6をアドビビライセンスストアでお買い求めください。

ええと・・・

頭おかしいんですか?Adobe さん(^^;

ビジュアルデザイン機能がなかったら、有料の Flash Builder 使う意味ってほとんどないやろ?
Aptana Studio 3 とどう差別化するつもりやねん!?

・・・なんか、ホント、Adobe の凋落ぶりをまざまざと見せつけられた気がしますわ・・・

ということで、FB4.6 のままで行きます。はい。
例えば、社内システムを Web アプリ化してんだけど、一部のプログラムだけはローカルマシンのリソースを使うので、それぞれのマシンに EXE ファイルとして置いてるんですわ・・・というケースはあるよね。
その時に、そのローカルマシン上のプログラムの起動も、Web アプリのメニュー上から行いたいんですわ・・・という要望もあると思う。

でも、例えば

<a href="C:\Program Files (x86)\apps\apps.exe">A業務システム起動!!</a>

なんてリンクを書いてブラウザからクリックしても(多分)EXE は起動しないよね。
したらセキュリティ的に大変なことだ。

つーことで、普通のプログラムをブラウザから起動するのはなかなか厳しいと思うんだけど、Adobe Flex の AIR アプリなら可能だ。

  1. ローカルマシン上の業務アプリ(Adobe Flex の AIR アプリ)を、allowBrowserInvocation を true にして作成。
  2. AIR アプリを起動するための Flash を作成。
  3. その Flash をセットした HTML を作成。(Flash Builder でリリースビルドのエクスポートをしたら、自動で作成されるけどね。それを自分のサイトにあったデザインに修正すれば良し)

というこれだけだ。

上記 2 で作成した Flash をブラウザに表示して、ボタン(これは Flash の作り方次第だから、文字列でも画像でもボタンでもなんでもいいんだけど)を押せばローカルマシン上で AIR アプリが起動する。

翻訳の微妙な Adobe 本家のサイトより、
http://hakuhin.jp/air/install.html Adobe AIR プログラミング講座
このサイトが非常に参考になった。

Flash 自体は、↓こんな感じで。(ホント、これは起動させるだけのものだけど(^^;)

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark"
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="1024" minHeight="720" initialize="initProc()">
    <fx:Script>

        <![CDATA[

            public var air_app_id:String = "hogehoge.app"; // アプリケーションID
            public var air_app_publish:String = "";
            public var air_swf:Object = null;

            private function initProc():void {

                var airSWFLoader:Loader = new Loader(); //Used to load the SWF
                var loaderContext:LoaderContext = new LoaderContext();  
                loaderContext.applicationDomain = ApplicationDomain.currentDomain;

                airSWFLoader.contentLoaderInfo.addEventListener(Event.INIT, onInit);
                airSWFLoader.load(new URLRequest("http://airdownload.adobe.com/air/browserapi/air.swf"),  
                    loaderContext);

            }

            private function onInit(e:Event):void {
                air_swf = e.target.content;

                air_swf.getApplicationVersion(air_app_id, air_app_publish, function(version:String):void {
                    
                    if(version == null) {
                        // アプリケーションがインストールされてない時の処理<省略>
                    }

                });

            }

            private function airAppStart():void{

                // AIR アプリケーションを起動する
                air_swf.launchApplication(air_app_id, air_app_publish);

            }

        ]]>
       
    </fx:Script>

    <s:Button x="60" y="58" label="起動" click="airAppStart()"/>
</s:Application>

詳しくは、上記のサイトや、
http://help.adobe.com/ja_JP/air/build/WSfffb011ac560372f-1c6efe05128cca667e7-8000.html AIR.SWF ブラウザー API
この辺りのサイトをどうぞ。
Adobe Flex は、画像ファイルとして扱えるのは、PNG, JPEG, GIF, SVG の4種類だけ。

例えば、インターネット上の TIFF ファイルを URLLoader で取得して、それを Loader で、

bmp:Bitmap = Bitmap(event.target.content);

みたいにビットマップデータとしてロードすることは出来ない。

つーことで、今回は Perl で wrapper として動く API プログラムを作成して、AIR アプリから TIFF ファイルへのアクセスがあった場合、JPEG 画像に変換してデータを渡すことにした。

例えば、TIFF 画像を $data に読み込んだ後で、Image::Magick モジュールを使って、

use Image::Magick;

my $image = Image::Magick->new();
$image->Set(magick => 'tif');
$image->BlobToImage($data);

# 今回は、画像サイズを縮小するので、その処理も
my($width, $height)    = $image->Get('width', 'height');
$height    = int($height * ($Width(変更後の横幅) / $width));
$image->Resize(width => $Width, height => $height);

my $new_data    = $image->ImageToBlob(quality => $Quality(画質), magick => 'jpg');

こんな感じ。
これで、$new_data に TIFF から変換された JPEG 画像データがセットされるので、

my $size    = length($new_data);

print "Content-type: image/jpeg\n";
print "Content-Length: $size\n";
print "\n";
print $new_data;

で、AIR アプリ側でも問題なく画像が表示される。

Image::Magick もたまにしか使わないので、いつもメソッドやプロパティを忘れてしまうので、一応、メモ代わりに書いておこう。
幅が 1750ピクセル、高さが 2420ピクセルある JPEG 画像をインターネット上から取得して印刷する AIR アプリを組んだのだが、

・Web サーバ上に、画像選択のための条件を渡せば、その画像を表示する HTML を返してくる API を設置。
・HTML コントロールからのそ API にアクセスし、HTML を取得。
・画像が表示されているその HTML コントロールを PrintJob クラスで印刷。

という流れにしたのだが、これが大間違い。

幅 480ピクセルほどの HTML コントロール(id="html_gamen")を

var myPrintJob:PrintJob    = new PrintJob();

if (myPrintJob.start()) {

try {
myPrintJob.addPage(html_gamen);
myPrintJob.send();
}
catch(e:Error) {
//エラー処理
}

}

みたいに印刷したのだが(もちろん、本当の処理はもっと複雑だけどね(^^;)、これだと、その 480ピクセル幅の HTML コントロールに表示されている部分だけしか印刷されない。
つーか、HTML コントロールのスクロールバーとかも一緒に印刷・・・って(^^;そういう仕様なの???(^^;
イメージ的に(通常のブラウザで印刷する時みたいに)中に表示しているコンテンツだけが印刷されるのかと思ってたよ。それも、表示されていない(スクロールしないと出て来ない)部分も一緒に。

この方法で全体を印刷しようとすると HTML コントロールの中に収まるように <img>タグの width 指定して画像を縮小表示するしかないんだけど、それだともう文字とかが潰れまくりで汚い、汚い・・・

色々ググってみても、「Flash の印刷は汚い」の一言で終わってる話なんかが多くて、こりゃ駄目だって感じだったのだが、FxUG(Flex User Group)のフォーラムで質問してみると、「JPEG 画像を一旦 BMPデータに変換して UIComponent にして、それを印刷したら良い」というヒントをいただいたので、今朝から色々試してみた。

結果、

・URLLoader でインターネット上の JPEG 画像を取得。
・取得した JPEG 画像データを Loader でロードして BMP データに変換。
 (ロードが成功したら、bmp:Bitmap オブジェクトにデータをセット)

この状態から、

var uicomponent:UIComponent = new UIComponent();
var myPrintJob:PrintJob    = new PrintJob();

if (myPrintJob.start()) {

try {

// プリンタから渡される印刷可能サイズで bmp オブジェクトをリサイズ
bmp.height = myPrintJob.pageHeight;
bmp.width = myPrintJob.pageWidth;

uicomponent.addChild(bmp);
// addElement(uicomponent); // 今回は表示はしない(印刷用)

myPrintJob.addPage(uicomponent);
myPrintJob.send();

}
catch(e:Error) {
//エラー処理
}

}

これでOK。

このやり方なら、印刷対象のコントロールにセットする前に、中にセットする画像データのサイズ縮小が行えるから良いね。(HTML コントロールに受信する形だとそれが出来ないし、<img> タグの width 指定なんかで縮小してると汚い)

下に画像を貼っておくので見比べてみ。(印刷したものを再度スキャンしたものなのであんまりきれいじゃないが、左が Bitmap 画像で読み込んで処理をしたもの。右が HTML コントロールに貼った JPEG 画像を印刷したもの。同じ画像ファイルなのに、この印刷品質の違い!(笑))

ああ、夕べからあれこれ実験してて(それは別件だけど)風呂に入ってないので頭が痒い(^^;

20120824_flex_img.jpg
20120411_flash.jpg
Flash Builder を使ってActionScript 3 でアプリを開発する予定がある。
その中で、表示した内容を印刷する処理があるのだ。

実は今まで AS3 のアプリで印刷処理をしたことは無かった。
んが、PrintJob クラスを使えば「印刷するだけ」なら簡単に実装できそうである。

例えば、表示している画像を印刷する・・・という処理なら、下記のようなコードになる。

<!--?xml version="1.0" encoding="utf-8"?-->
<s:application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="618" height="417" minwidth="955" minheight="600" backgroundcolor="#DBCAA7">

    <fx:script>
        <!--[CDATA[

            import flash.printing.PrintJob;

            private function BasicPrintExample():void {

                var myPrintJob:PrintJob    = new PrintJob();

                if (myPrintJob.start()) {

                    try {
                        myPrintJob.addPage(img1); 
                    }
                    catch(e:Error) {
                    }

                    myPrintJob.send();

                }

            } 

        ]]-->
    </fx:script>

    <s:image id="img1" x="121" y="52" width="384" height="293" source="img/20120408_touring.JPG">
    <s:button id="btn1" x="274" y="23" label="印刷" click="BasicPrintExample()">

</s:application>

簡単やねえ(^^;

ただ、ここで困った問題が発生。
実は、お客さんから「印刷部数を記録したい」という要望があったのである。つまり、「何枚印刷したか知りたい」ということである。

これも、デスクトップアプリケーション(AIR)で作れば簡単だ。

PrintJob クラスには、copies プロパティが存在するので、例えば上の例であれば、myPrintJob.send(); の前で、myPrintJob.copies の値を調べれば、印刷ダイヤログの「部数」のところで指定した値を知ることが出来る。

・・・が、今回は AIR ではなく Web アプリケーション(Flash)で・・・ということになっている。これが厳しい。

Flash の場合、AIR と違い(同じ AS3 で書かれていても)ローカル PC の情報は一切取れない。セキュリティ面からの実装だと思うが、そのため、copies プロパティ等も Flash として作成する Flex プロジェクトでは参照できない。定義されていないプロパティだと怒られてしまうのである。

つーことで、どうしても「印刷部数」をアプリケーション内で取りたければ AIR アプリで・・・ということになるな。
20120306_flash.jpg
Flash Builder で作った Flash プログラムを実行テストしようと思ったら、「Flash Builder で、Adobe Flash Player の必要なデバッガーバージョンが見つかりません。Flash Player のデバッガーバージョンをインストールするか、Flash Builder を再インストールする必要がある可能性があります。」の警告が。

Flash の開発をするときは、開発環境(Flash Builder 等)と通信をして、デバッグ用の情報をやり取り出来るデバッガーバージョンの Flash Player をインストールしているのだが、そういえばこのPCには入れてなかったなあ・・・と思って、

Windows Flash Player 11.1 ActiveX control content debugger (for IE)

ってヤツをインストールして入れたんだけど、状況は変わらず。

自宅の PC じゃ上記 Player をインストールしたら問題なくテスト実行出来るようになったんだがなあ・・・

同じ Windows 7 Professional でも、自宅のは 32bit、事務所のは 64bit だからなあ・・・と思ってみてみたら、やっぱそれが原因だった(^^;
もう一回警告ウィンドウ見てみると、

C:\Windows\System32\Macromed\Flash\Flash64_11_1_102.ocx

って(^^;
コンパネの「プログラムと機能」を開いてみると、「Adobe Flash Player 11 ActiveX」というのと、「Adobe Flash Player 11 ActiveX 64-bit」というのが共存してる(^^;

結局、デバッガ版はまだ 32bit版しか出てないので、両方あっても優先的に 64bit版が使われちゃうってことかな?

取り敢えず、両方の Player をアンインストールして、32bit版のデバッガーバージョンを入れなおしたらバッチグーだった。

なんだかなあ(^^;
いくら Apple との戦いに敗れて消えていく技術だとしても、今もまだ色々なところで使われているし、Flash Builder という開発環境だった販売してるんだから、早いところ 64bit版をだそうよ、デバッガーバージョンも。

なんか、このへんのトロい対応に、Apple との戦いに勝てなかった原因がある気がするよ、Adobe さん。
Flash Builder 4.6 で作成した Flash(SWF)を納品したのだが、このプログラムが最新の Flash Player バージョン 11.1.0 を要求するということで、

  • Internet Explorer 9 なら問題ないが、8 や 7 だと Flash Player の自動インストールに失敗することがある。(もちろん、手動でダウンロードしてインストールすれば全然問題無い)
  • Mac OS X 10.6 以下だと、Flash Player 11.1.0 がインストール出来ない。OS が古いと怒られるらしい。(10.6.8 とかはOK)

という問題があって、まあ、(IE の古いバージョン使ってるなんて自殺行為だし(笑))普通なら「バージョン上げなさいよ」という話しなのだが、通販サイトのトップページに置いている Flash なので、やはりなるべく多くの人に見てもらえるように・・・と、ローバージョン対応を行なうことにした。

とは言っても、Flash Builder に「(危険な・・・と少なくともメーカーは思っている)古いバージョンでも実行可能にする」みたいなセキュリティ上の問題のある(現実的には問題が無いにしても)オプションは用意されているわけがないわけで、仕方ないので、Flash Builder の以前のバージョン、Flex Builder 3 で Flash を作成し直すことにした。

会社に Flex Builder 3 が入っている Mac mini があったので、これで作業。
以下、Flash Builder(以下 FB4)で作成したソースを Flex Builder(以下 FB3)でコンパイルする時の留意点。

  1. FB4 の <s><fx> タグは、FB3 では <mx> タグに変更。(例:<s:Application>→<mx:Application>、<fx:Script>→<mx:Script> 等
  2. FB3 では、オブジェクトをスライドさせた時など、標準でスクロールバーが表示されてしまうので、<mx:Application>タグに、horizontalScrollPolicy="off" verticalScrollPolicy="off" を追加。
  3. FB4 にあって FB3 にない、verticalAlign や chromeColor 等のプロパティを削除。
  4. FB4 では、SWF ファイルへのリンクが貼られた HTML ファイルからの相対パスとなるが、FB3 の場合は自分(SWFファイル)が置かれた場所からの相対パスになるので、プログラム中のパスの記述や、SWF ファイルの設置場所に注意が必要。

ってところか。
今回は、特に Flash Builder でないとできないことは何もしていないので、こんな感じの対応で何とかなった。

しかし、まあ、ほんま、古いバージョンにどこまで考慮しないといけないのやら・・・悩ましいところですなぁ。
久しぶりに Flash 案件を受注したので、開発環境として Adobe Flash Builder 4.5 を購入した。

今までは Adobe Flex Builder 3 を使っていたのだが、これももう随分古いんで(もう、4~5年前のソフトだ)、AIR アプリの開発では問題無いんだけど、Flash をローカルでテストする時に色々と不都合があったのである。
なので、そこそこの売上の Flash 案件があったら買い換えようとずっと思ってたのだ。

で、Flash Builder 4.5 は Android 用のアプリも作れるというので、昨日の朝インストールして、早速試してみた。
Android 上で動く SWF ファイルを生成するようだ。

20111210_android.JPG
まあ、最初に作るアプリは当然「Hello World」を表示するものだよな(笑)
つーことで、「ボタンを押したら Hello World が表示されたり、消えたりする」プログラムを 3分で作って(笑)、実機でテストしてみた。

つーても、最初は「デバッグの構成」で起動方法として「デバイス上:USB 経由でデバッグ」を選んでも、デバイス選択の画面で「Flash Builder は接続されているデバイスを検出できませんでした。」と出て駄目。
iPhone では、iPhone 側で何もしなくても開発中のプログラムを突っ込めたと思うけど(最近触ってないので記憶違いならゴメン)、Android の場合、「設定」画面で「アプリケーション」を選び、「提供元不明のアプリ サードパーティーアプリケーションのインストールを許可する」にチェックを入れ、次に「開発」を選び、「USB デバッグ USB 接続時はデバッグモードにする」にチェックを入れてやる必要がある。

これで、Eclipse 上で(Flex Builder 同様、Flash Builder の開発環境は Eclipse である)デバッグボタンを押したら、プログラムが Eee Pad Transformer TF101 に送られて、実際にタッチパッドを使ったテストが可能になる。

いいねえ。
Apple に申請して ID 取らないと実機テストが出来ない iPhone と違って、こういう開発のし易さが、業務端末として使うことを考えると Android 有利なんだよな。

Flash で、<mx:Image>タグで貼り付けた画像ファイルがちゃんと読み込まれたかの判定がしたい。

つまり、

<mx:Image x="10" y="10" id="image1" width="100" source="img/1.jpg" />

みたいに指定してた時、img フォルダの下に 1.jpg が無かったら(読み込めなかったら)任意の処理をしたいというわけだ。

例えば URLLoader を使ってデータを読み込んでくれば、失敗したかどうかはすぐに取れるんだけど、今回は <mx:Image> タグを使うのが必須条件。

で、最初は、データが読み込まれなければ(当然「空の画像」なわけだから)画像の横幅が取れないんじゃないかと思って、 image1.content.width の値を取ってみたんだけど、画像ファイルが読み込めなかった時も、14って値返してくるな・・・
どうも、ファイルが読めなかった時に表示される「壊れ画像アイコン」の幅を取ってきているようだ(^^;

さて、どうしようかなっと思ってググってたら、

obj = image1.getChildAt(0) as FlexLoader;

のようにして、Imageコントロールの子オブジェクトを取得しようとすれば、画像が読み込めてない時は NULL 値が返ってくるような記述を見つけた。

そこで、

var obj:FlexLoader  = image1.getChildAt(0) as FlexLoader;
if (obj == null) { // 読み込まれてない!
    ...いろいろな処理
}

という処理を書いてみたのだが、どうも上手く行く場合と行かない場合がある。
5つくらいの画像でこういう処理をやるのだが、5つの内、2つの画像ファイルが存在していない時、最初の(本来は存在していない)画像のみ NULL が返ってこないのだ。(2つ目の非存在画像ではちゃんと NULL が返ってくる)

何か、タイミングの問題なのかなと思い、メインウィンドウが表示される時の、creationComplete イベントで処理を起動していたのを、updateComplete イベントで起動するようにしたら上手くいったようだ・・・もう少しテストしてみんとタイミングの問題なんで何とも言えんが、今のところは上手くいってるみたい。

この調査及びプログラムの修正だけで半日を潰してしまった。よもや、こんなにハマるとは思わず、この処理はまったく工数見積してなかったのに・・・がっくり(;_;

しかし、creationComplete イベントの説明見ると、「コンポーネントの構築、プロパティ処理、測定、レイアウト、および描画が完了したときに送出されます。」って書いてあるんで、全ての画像ファイルを読み込んだ後で起動される・・・と判断していたのだが、何か違うのね・・・(^^;
updateComplete イベントもプログラム起動時に起動されるとは知らなかった。

なんか、イベント駆動型のプログラミングって、この辺の処理タイミングとかでハマること多いよなあ・・・(^^;

このアーカイブについて

このページには、過去に書かれたブログ記事のうちAIR/Flexカテゴリに属しているものが含まれています。

次のカテゴリはPerlです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら