[AS][iPhone]AIR for iOSにおいてANEファイルを含めたビルドをするには、”mac版”のFlashBuilder4.6一択という残念な現実(GUIを頼りにする場合)

タイトル通りなんですが、そこにたどり着いた経緯をダラダラ書いておきます。

AIR for iOSで作ったアプリはマナーモード(正式にはサイレントスイッチ)ON状態でも音がなってしまいます。
(Flashからはそこを制御するAPIが用意されていないようです)
が、NativeExtension for Air(ANE)という機能が用意されており、自分で足りないAPIを補うANEを用意することでAIR for iOSでもできることを拡張することができます。

ANEはネイティブコード(Objective-Cとか)で作れますが、めんどくさい。
サイレントスイッチを何とかするANEもきっと誰かが作ってくれてるはず。

と、ググってみるとあっさり見つかりました。
StickSports / ANE-Silent-Switch

ソースからANEファイル、テスト用のコード(testフォルダ)まで入っていました。
とりあえずこのテストコードを実機で試してみよう!
と思ったら落とし穴いっぱいだったというお話です。


・はまりポイント1

testコードビルド方法がよくわからず。
READMEには

Antビルドスクリプトのテスト/ build.xmlをビルドし実行します。これは、テストの/ binフォルダ内のテストのIPAを作成します。

Antでビルド?なにそれおいしいの?
FlashDevelopとかFlashCS6でできないの?
できるだけ慣れてるやつでやりたいです。
まずはFlashDevelop。


・はまりポイント2

FlashDevelopでaneファイルを紐付けたビルドがよくわからず。

aneを使ってのFlashDevelopでのビルド例としてこの記事を教えてもらったけども、じっくり読む前にとりあえずFlashCS6にはaneの設定が増えているからきっと簡単にできるだろう、とFlashCS6に逃げる。

2012/06/18 追記
FlashDevelopでaneビルドできましたので記事書きました。


・はまりポイント3

FlashCS6でaneファイルを正しく設定していざパブリッシュ。
すると、こんなエラーが大量に出現。

ld warning: unexpected srelocation type 9

ググってみるといろいろ記事がでてきてiOSのsdkがなんちゃらとか、コマンドラインからもろもろ設定したADTを叩くとかさくっと解決できそうな方法は見つからず。
一番簡単そうなのは、MUSHIKAGO APPS MEMO さんの記事で、FlashBuilderなら「Apple iOS SDK」という項目に最新のiOSのSDKを指定しておけば大丈夫っぽいとのこと。

だがしかし、FlashCS6にはそのような項目がどこにも見あたらず・・・
せっかくaneファイルを簡単に設定できるようになってるのに世の中に落ちてるものを簡単に使えないんじゃ意味無いじゃん・・・
というわけで、解決策のあるFlashBuilderに逃げることに。


・はまりポイント4

Xcode4.3から最新のiOS5.1.sdkフォルダをまるっとwindowsにコピーしてさぁ設定しようかと思ったら。

Win版のFlashBuilderではこの機能が使えないとな・・・
値段一緒なのに。。Windowsユーザーをバカにしてんの。。

というわけで、macのFlashBuilderで試してみたらようやくと実機でテストが正常に動きましたよ、と。

・結論
GUIを使ってANEを含んだビルドしたい人は、とりあえずmac版のFlashBuilde4.6を使うしかないみたい。
とりあえずバージョンアップなりでもうちょっとなんとかしてくださいよ、アドビさん。

[JSFL]座標の小数点を丸めるJSFL使用時の注意(Windows FlashCS4,CS5で確認)

ステージ上のオブジェクトの座標を整数に丸めてくれる便利JSFLに罠があることに気づきました。
CS5で気づいて、CS4でも同じことになったから既知の現象でしょう。

丸めるJSFLはいろんな方が公開してくれてるのでボクもどこかで拾ったものを使ってます。
↓こんなの

var doc = fl.getDocumentDOM();
if (doc.selection.length) {
for (var i = 0 ; i < doc.selection.length ; i++){ var mat = doc.selection[i].matrix; mat.tx = Math.round(mat.tx); mat.ty = Math.round(mat.ty); doc.selection[i].matrix = mat; } } [/sourcecode] 選択したオブジェクトを一括でバーンと変換してくれて便利なんですが、保存時に結果を変換後の座標を保持してくれないことがあるようだということに気づき、なんとなく原因と対策っぽいこともわかったのでメモしときます。


まず、座標を保持しない再現手順を書きます。
(うちでの再現率:100%)

■手順(準備編)

  • 1.新規flaファイルを作成
  • 2.何でもいいから四角いシェイプを書いてMC化(シンボル1とする)
  • 3.シンボル1をさらにMC化(シンボル2とする)
  • 4.シンボル2の中に入り、シンボル1のx座標を0.5にする(プロパティパネルから数値変更)
  • 5.保存して、ファイルを閉じる。
  • 6.再度ファイルを開き、シンボル2の中のシンボル1の座標を確認するとx座標は0.5となっている。

→ここまでは何の問題もない

■手順(不具合発生編)

  • 7.シンボル1を選択した状態で上記JSFLを実行する。
  • 8.プロパティパネル上では0.5が1となっているはず。
  • 9.ファイルを上書き保存して閉じる。
  • 10.ファイルを開いて、シンボル2の中のシンボル1の座標を確認するとx座標は0.5となっている。

→なにこれ、ばかなの、しぬの


ちなみにJSFLを使わずに手動でプロパティパネルの数値を0.5→1に変更した場合は保存は反映されます。
(当たり前か)

では何が問題か。
ここからは推測ですが、上記JSFLでの結果ではflaファイル的には「変更扱いにされていない」っぽいようです。
ためしに上記手順8まで実行した状態でファイルを保存するまえにシンボル2の中のタイムラインのレイヤーをひとつふやしてから保存して開き直してみると、こんどはちゃんとシンボル1座標変更が反映されているのが確認できます。

ここで注意が必要なのは、シンボル2の中のタイムラインをいじったということ。

シンボル2のタイムラインではなく、メインタイムラインのレイヤーをひとつふやしてもシンボル1の座標変更は反映されません。
つまりはFlashはMC単位で変更があったかなかったかを判断して、状態を保存するかしないかを決めてるっぽいので関係ないタイムラインに変更を加えても意味がない、ということになりそうです。


というわけで、対策
確実に「MCに変更を加えたぞ」と判らせてあげるために、上記JSFLを改造。

var doc = fl.getDocumentDOM();
if (doc.selection.length) {
for (var i = 0 ; i < doc.selection.length ; i++){ var mat = doc.selection[i].matrix; mat.tx = Math.round(mat.tx); mat.ty = Math.round(mat.ty); doc.selection[i].matrix = mat; } } //追加:レイヤーを追加して、追加したレイヤーを消す doc.getTimeline().addNewLayer(); doc.getTimeline().deleteLayer(); [/sourcecode] 最後に2行追加しただけです。 レイヤーを追加してすぐにその追加したレイヤーを削除する。 結果的には何の変化もない意味のない処理ですが、これで「MCに変更を加えたぞ」とflaに判らせてあげることができるようになります。 このJSFLを用いて上記手順を実行すると小数点丸めは確実に保存時に反映されるようなりました。 かなり力技な感じですが、もっとマシな方法がありました教えてくださいませ。 (果たしてCS5.5では直ってるのか?・・・まぁ直ってないだろうな。。)

[AS]FlashPlayer11で、FMS接続でのNetStatusEvent.NET_STATUSをリスナーしてるときのNetStreamからのdispatchの挙動が変わったっぽい。

FlashPlayer11(以下FP11)とFlashPlayer10(FP10)で、FMSの動画を再生する際に、NetStreamでNetStatusEvent.NET_STATUSイベントをaddEventLinster登録したさいのイベント配信のタイミングがFP11とFP10で異なる現象に遭遇した。

具体的には以下をドキュメントクラスとしてパブリッシュしたswfを再生した場合に、traceされる結果がFP11とFP10で異なった。

package 
{
	import flash.display.Sprite;
	
	public class FMSTest extends Sprite 
	{
		public function FMSTest() 
		{
			//FMSサーバーへのパス
			var dirPath:String = "rtmp://hoge.hoge.hoge.hoge";
			var filePath:String = "mp4:hoge.mp4";
			addChild(new LoadMovie(dirPath, filePath));
		}
	}
}
import flash.display.MovieClip;
import flash.events.NetStatusEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;

class LoadMovie extends MovieClip
{

	private var nsUrl:String
	private var nc:NetConnection;
	private var video:Video;

	public function LoadMovie(ncUrl:String, nsUrl:String, w:uint = 320, h:uint = 320 ) {
		this.nsUrl = nsUrl;
		//ネットコネクションを作る
		nc = new NetConnection();
		//ネットコネクションの接続状態を調べるリスナー
		nc.addEventListener(NetStatusEvent.NET_STATUS , onNcStatus);
		//ネットコネクションを接続する。
		nc.connect(ncUrl);
		nc.client = new Object();
	}
	
	//ネットコネクションの状態でいろいろ出力される
	private function onNcStatus(e:NetStatusEvent):void 
	{
		switch (e.info.code) 
		{
			//もし無事に接続されたら、
			case "NetConnection.Connect.Success":
			initStream();
			break;
		}
	}

	//ネットストリームの初期化処理
	private function initStream():void {
		//ネットコネクションを作る
		var ns:NetStream = new NetStream(nc);
		//ネットコネクションの接続状態を調べるリスナー
		ns.addEventListener(NetStatusEvent.NET_STATUS, onNsStatus);
		//読み込みの時間を設定
		ns.bufferTime = .1
		//メタデータ取得用のオブジェクトを設定
		ns.client = new Object();
		//videoインスタンスを作成
		video = new Video();
		video.attachNetStream(ns);
		addChild(video);
		//再生開始
		ns.play(nsUrl);
	}

	private function onNsStatus(e:NetStatusEvent):void {
		trace("onNsStatus : "+e.info.code);
	}
}

再生した際のtraceの出力結果を以下に示す。
FP10

onNsStatus : NetStream.Play.Reset
onNsStatus : NetStream.Play.Start
onNsStatus : NetStream.Buffer.Full

FP11

onNsStatus : NetStream.Play.Reset
onNsStatus : NetStream.Play.Start
onNsStatus : NetStream.Buffer.Empty
onNsStatus : NetStream.Buffer.Full

FP11では、NetStream.Buffer.Emptyが追加されている。
再現性は100%ではないが、6割~9割位の割合でNetStream.Buffer.Emptyイベントを取得するっぽい。


で、再生開始のタイミングでNetStream.Buffer.Emptyイベントがでることで何が困るかというと、FMSでは動画の終了のタイミングを取るのにNetStream.Buffer.Emptyを使うことがあるからだ。
参考:RTMP接続のランダム再生で最後の数秒が途切れてしまう!


再生開始のタイミングでNetStream.Buffer.Emptyを出したくない、どうしたもんかと思ってたら解決策っぽいのが見つかった。
Netstream.bufferTimeを多めに取ってあげるとよいようだ。
具体的には上記コードの59行目

ns.bufferTime = .1; //0.1秒
//↓0.1秒を2秒にする
ns.bufferTime = 2; //2秒

これでNetStream.Buffer.Emptyはtraceされなくなった。
とりあえず、同じ現象に遭遇してしまった人の参考になれば幸いです。

[iPhone]3GSから4sに機種変更するとき「実質無償機種変更キャンペーン」を利用するメリットとデメリット

以前書いた記事
「[iPhone]契約2年を迎えたときに、2年契約(キャンペーン)を更新する or しない のメリットとデメリット」
のオマケ的なお話。

本日iPhone4sに機種変更してきました。
現在softbankは以下のようなキャンペーンを実施しています。(11/30まで)

「実質無償機種変更キャンペーン」

これは、ざっくり以下の内容。

  • 使用中の3GSの端末価格の支払いが済んでない場合はその分はチャラにするよ
  • 支払いが完了してる人(ボクはここに該当)でも6000円キャッシュバックするよ

普通に考えると利用しない手はないのですが、ボクは今回このキャンペーンをあえて使わなかった。


その理由は、(前回の記事の内容とも関係するけど)
このキャンペーンを利用するといわゆる2年縛り状態になってしまう、ということ。
つまり特定の期間外でsoftbankを解約した場合に約1万円の違約金が発生してしまう。

前回の記事にも書いたようにボクは現在softbankの2年縛りの呪縛から開放されている状態だった。
目先の6000円を追うよりも、いつでも解約できるという精神的な安定を望んだわけだ。
もちろん解約しないでずっと使うよ、って人はキャンペーンを利用したほうが得だろう。
ただ個人的に、電話会社のプランは日々変化しつづけていて、それが消費者にとっては改悪の場合もあるわけで、新規で契約する場合にはそちらしか選べないけど、既存の契約者が旧プランを維持できるんであればそれを利用しつづけるのも手かな、と。
一度プラン変えちゃったら、もう元には戻れないと思うし。


p.s
今回アップルストアで機種変更したのだけど、対応してくれた店員さんはとても親切でボクの過去3ヶ月の通話記録からもっと安くなるようなプランを提案してくれた。
具体的には全然通話してなかったから、Wホワイトよりホワイトの方がお得ですよ、と。
ありがたくその提案に従ったけれども、さすがに上記キャンペーンについての細かい話はなかった。
(ボクが2年縛りのかかってない状態かなんて知らないだろうしね)
こちらから質問することで丁寧に教えてくれた。
なんでも直接聞いてみるのが一番だね。

[AS]AS3での、TextField.htmlTextでつかえる、HTML,CSSのまとめ

以前作ったもの。
ネットで検索できるようにメモ。

[AS]Progressinで「at jp.progression.casts::CastPreloader/set contextMenu()」なエラーがでたときの(とりあえずな)対処法

Progressionを使ってこんなエラーに遭遇。

TypeError: Error #1009: null のオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません
at jp.progression.casts::CastPreloader/set contextMenu()
at com.courservector.flashbug::Profiler/allCompleteHandler()


詳しく検証してないからわかってることだけとりあえず箇条書き

  • FlashPlayerがデバッグプレイヤーのときだけ発生
    (普通のプレイヤーでは発生しない)
  • FireFoxで、かつFireBugとFlashBugが入ってるときに発生
  • FireBugとFlashBugを無効化するとエラーはでなくなる
    (このときPCを再起動する必要があった)
  • 無効化してからもいちど有効化したらエラーがでなくなった
    (わけわかめ)

再現の規則性がよくわからんのでブラウザ(FF)とアドオンのバグなんじゃないかと推測。


とりあえずProgression側での対処法も書いておく
CastPreloader.asの431行目にあるsuper.contextMenu = menu;をコメントアウトすればOKっぽい。
(右クリックでProgressionのライセンス表記もでるし、とりあえず大丈夫っぽい)

抜粋したコードはだいたいこんな感じ
[

]
//CastPreloader.asの428~431行目あたり

// ContextMenu を作成する
var menu:ContextMenu = new ContextMenu();
menu.hideBuiltInItems();
//■↓ここをコメントアウトする
//super.contextMenu = menu;

[AS]画像をゆっくり動かす方法 その2

以前にも書いた内容についての補足です。
画像をゆっくり動かす方法

上のリンクを読んでもらうとわかるのですが、
画像をゆっくり動かすにはbeginBitmapFill()の第2引数のMatrixを使って位置を変更しながら毎フレーム描画する、
ということだったのですが、これだとあまり直感的でなくてちょっとめんどくさい。

↓のサイトを観たらもっと簡単にできました。
にゃあプロジェクト|[AS3.0] カルーセルに挑戦! (2)

要はShapeなりSpriteなりにbeginBitmapFill()を使って(smoothing=trueで)描画してしまえば、画像が描画されたShapeなりSpriteは0.1px刻みで動かしてもカクカクすることはないようです。

前回のスクリプトを例に修正すると、

package  {
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	/**
	 * ...
	 * @author 393
	 */

	//ライブラリに画像を用意し、クラス名Bmpでリンケージ。
	//画像サイズは400×300

	public class Main extends Sprite{

		//private var matrix:Matrix = new Matrix();
		private var bmp:BitmapData;
		private var sp:Sprite;
		//private var mx:Number = 0;
		//private var my:Number = 0;
		//private var w:Number;
		//private var h:Number;

		public function Main() {
			bmp = new Bmp(0, 0);
			sp = new Sprite();
			addChild(sp);			
			buttonMode = true;
			this.addEventListener(Event.ENTER_FRAME , xEnterFrame);
			
			//■追加:あらかじめspにBitmapDataを描画する。
			sp.graphics.beginBitmapFill(bmp, null, false, true);
			sp.graphics.drawRect(0,0,bmp.width,bmp.height);
		}
		function xEnterFrame (e:Event):void {
			//mx += 0.05
			//my += 0.05
			//matrix.tx = mx;
			//matrix.ty = my;
			//sp.graphics.clear();
			//smoothプロパティをtrueにするのがポイント
			//sp.graphics.beginBitmapFill(bmp, matrix,false,true);
			//sp.graphics.drawRect(mx, my, 400, 300);
			//sp.graphics.endFill();
			
			//直接動かしてもカクカクしない
			sp.x += 0.05;
			sp.y += 0.05;
		}
	}
}

こちらの方が直感的に使えていいですね。

[iPhone]契約2年を迎えたときに、2年契約(キャンペーン)を更新する or しない のメリットとデメリット

iPhone(3GS)を契約して丸2年になったこともあり、softbaknkの窓口でタイトルどおりの質問をしてきたのでメモしとく。


まず、「2年契約(キャンペーン)」とは
たぶん最初にsoftbankに契約したときに入ることになるいわゆる2年縛りの契約。
この2年がたたないうちに契約を解除すると違約金を1万円くらい払わなきゃいけない。
これは、どこの携帯電話会社でもあるよね。


で、このまま何もしないと3年目からも「2年契約(キャンペーン)」に加入することになり、また2年縛りが始まり途中解約では違約金が発生する、ということ。

これが「2年契約(キャンペーン)」を更新したときのデメリットとなります。
「2年契約(キャンペーン)」に加入してるときは、2年契約(キャンペーン)の更新可能月以外はsoftbank解約時に違約金を払う必要があるので好きなときに解約しずらいということ。
ちなみに「2年契約(キャンペーン)」の更新可能月は、契約月+12,13,14の3ヶ月間。
たとえばボクの場合は2009年8月にiPhone持ったので、更新可能月は2011年の8,9,10月ということ。


では「2年契約(キャンペーン)」のメリット
パケットの上限が4410円になります。
ちなみに2年契約(キャンペーン)に加入してない場合の上限は5980円

下限はいずれも1029円なので、具体的には

  • 2年契約(キャンペーン)アリ:1029~4410円
  • 2年契約(キャンペーン)ナシ:1029~5980円

という料金形態になります。


こうなると毎月パケット上限まで使い切ってる人(つまりボク)は「2年契約(キャンペーン)」をナシにすると毎月の支払い額が増えてしまって微妙だなぁと思ったら、「パケットし放題フラット」というサービスもあると。
こちらに加入するとパケット使っても使わなくても毎月定額4410円のパケット代になると。


まとめると、
毎月パケットを上限まで使い切ってる人は、契約2年を迎えたときに迷わず「2年契約(キャンペーン)」の更新をとめる。
これで、3年目以降はsoftbank解約時に違約金を払わなくてすむので安心。
そして「パケットし放題フラット」に加入すれば月々の支払いは今までどおり。

毎月パケットを上限まで使い切ったり使い切らなかったりとムラが激しい人で、softbankから解約することはないって人は「2年契約(キャンペーン)」を更新してもいいんじゃないかな。

softbankの前はau使ってたのだけど、auは何年使っても契約月以外での解約は違約金払わされるシステムだった気がする。
そう考えると、softbankは良心的なんじゃないかと思った。


>2011.10.6追記


どうやらsoftbankの2年縛りには2種類あるらしい。

■1つは上にかいた「2年契約(キャンペーン)」
■もうひとつは、2010年4月27日から改定された「ホワイトプラン」(基本料金のプラン)

ボクの場合は2010年4月27日以前(「2年契約(キャンペーン)」に加入してる人はこうなるはず)にホワイトプランを契約してるので、上記に書いたとおり、「2年契約(キャンペーン)」を解除すれば2年縛りの呪縛から解除されて、いつ解約してもよくなるのだけど、2010年4月27日以降に契約した人は「ホワイトプラン」(iPhoneの基本料金プランなので必ず入ってるはず)に2年縛りの条項が追加されたので、2年縛りからの呪縛からは逃れる方法はないみたい。

詳細>>ソフトバンクの新ホワイトプランが“改悪”にしか見えない理由

全然良心的じゃないな。
あとよくよく考えたらauのときは端末代無料で2年縛り的なことがまかりとおってた時代だった。
端末代一括で払ったとしても2年縛りがつきまとう、依然よりも環境悪化した気がする。

[iPhone]UISliderにてvalue値固定でmaximumValueを変更した際にはUISliderの見た目が変化しないみたい。そんなときの無理やりな対処の仕方。

UISliderの挙動に悩みました。

やりたかったこと。
たとえば、UISliderが二つあって(sliderA,sliderBとする)、
初期値はこんな感じで、

sliderA.maximumValue = 200;
sliderA.minimumValue = 100;
sliderA.value = 150;
sliderB.maximumValue = 100;
sliderA.minimumValue = 0;
sliderA.value = 50;

sliderAのvalue値をsliderBのmaximumValueに対応させたい

//sliderAに対するValue changedなメソッド
-(IBAction) changeSliderAValue:(UISlider* )slider
{
    sliderB.maximumValue= sliderA.value;
}

sliderBはmaximumValueは変化するがvalueは変化しない。
この状態でsliderBの見た目(つまみの位置)が相対的に変化して欲しい。
が、変化しない。。

sliderBのvalueを変数で保持しておいて、明示的にsilderB.valueに代入してみてもだめ。

float sliderBValue;
//sliderAに対するValue changedなメソッド
-(IBAction) changeSliderAValue:(UISlider* )slider
{
    sliderB.maximumValue= sliderA.value;
    sliderB.value = _sliderBValue;
}
//sliderBに対するValue changedなメソッド
-(IBAction) changeSliderBValue:(UISlider* )slider
{
    _sliderBValue = sliderB.value;
}

どうも挙動を確認してみるとslider.valueには現在地と同じ値を明示的に代入しても見た目の変化は起きないようだった。
現在地と違う値を入れてあげれば、maximumValueに対応した見た目の変化も発生する。

で、考えた苦肉の策はこちら

float sliderBValue;
//sliderAに対するValue changedなメソッド
-(IBAction) changeSliderAValue:(UISlider* )slider
{
    sliderB.maximumValue= sliderA.value;
    //わざとランダムな数値を一度代入することで現在値を更新する
   sliderB.value =  arc4random() % 100;
    //改めて_sliderBValueを代入することで正しい見た目にする
    sliderB.value = _sliderBValue;
}
//sliderBに対するValue changedなメソッド
-(IBAction) changeSliderBValue:(UISlider* )slider
{
    _sliderBValue = sliderB.value;
}

もっといい方法がありましたら、教えてくださいませ。。

[AS][iPhone]FlashBuilder4.5のActionScriptモバイルプロジェクトで横向き固定の設定をした場合のステージサイズを正しく取得する方法

前の記事の続き、
FlashBuilder4.5のActionScriptモバイルプロジェクトでの設定のお話。

まず横向き固定にする方向は、hoge-app.xmlに

<!-- hoge-app.xml内のinitialWindow要素に指定 -->
<aspectRatio>landscape</aspectRatio> 

を設定するだけでOK。
これでデバッグプレビューすると確かに横向きでプレビューされる。
が、stage.stageWidthは320、stage.stageHeightは480と変更されていない。
(ちなみにFlexモバイルプロジェクトの場合はstage.stageWidthは480、stage.stageHeightは320となり問題ないようす)

ではどうしたらいいか、
結論としては、ドキュメントクラスのコンストラクタに以下の一行を追加
stage.setAspectRatio(StageAspectRatio.PORTRAIT);

//前提で、hoge-app.xmlに<aspectRatio>landscape</aspectRatio>と設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.PORTRAIT);
trace(stage.stageWidth, stage.stageHeight); //出力:480,320

解せないのが、なぜPORTRAITなのか。
通常はPORTRAITは縦、LANDSCAPEは横をあらわすので、stage.setAspectRatio(StageAspectRatio.LANDSCAPE);と設定すればいいと思ったのだけど、これだとstage.stageWidthは320、stage.stageHeightは480のままとなった。

//前提で、hoge-app.xmlに<aspectRatio>landscape</aspectRatio>と設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
trace(stage.stageWidth, stage.stageHeight); //出力:320,480

解せぬ。


※2011.8.15追記
上記設定だと実機転送した際に横方向にはならない様子。。。
やはりsetAspectRatio()にはStageAspectRatio.LANDSCAPEを設定しないと横向き固定にはなりませんでした。
上に書いたLANDSCAPE設定での懸念されるステージサイズは、
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
となっているようで実機起動上では特に問題なさげ。
ステージサイズがちゃんと取れないのはデバッグプレビューだけでのバグってことなのか!?

※2011.8.18追記
コメント欄にて教えていただきました。
stage.setOrientation(StageOrientation.DEFAULT)を設定することで想定したstageサイズを取得することができました。

//前提で、hoge-app.xmlに<aspectRatio>landscape</aspectRatio>と設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
stage.setOrientation(StageOrientation.DEFAULT);
trace(stage.stageWidth, stage.stageHeight); //出力:480,320