2013年2月23日土曜日

Flashの画像を差し替える

ソースリストなど一切失われてしまって手元にあるのはSWFだけ。その上のビットマップを張り替える必要が生じて、いろいろ試行錯誤しました。

  • swfmill
  • swfmill on Moutain Lion
  • 画像差し替えのために
  • どうやってPNGをエンコードするか
  • Mountain Lion上で動かして見る



■ swfmill ■

というオープンソースのツールがあります。これはSWF<->XMLを相互に変換できるという素晴らしいものです。コマンドラインツールでソースとMac版 /  Windows版が配布されています。Windows版はdylibも含んでいて、インストーラを動かせばすぐ使えるようになるはずです(私の環境ではdylibをインストールする時にアンチウィルスさんに怒られる)。

Macでは以下のような作業が必要になります。
  1. サイトからMac版バイナリをダウンロード&解凍
  2. ターミナル上で必要なdylibを用意して、swfmillを実行
…と書くと簡単なんですが。

■ swfmill on Mountain Lion■

配布されているのはコマンドラインツールのバイナリです。前述の通りlibfreetype6などのdylibが/usr/local/libにインストールされている必要があります。いろいろ試行錯誤しましたが、結果としてこんな感じ
  1. http://xquartz.macosforge.org/landing/からXQuartzをダウンロード&インストール
  2. MacPortsをインストール
  3. ターミナル上で準備
    1. MacPortsを最新版にアップグレード
      • sudo port self update
    2. 必要なdylibを読み込むためにportを実行
      • sudo port libfreetype +universal
      • sudo port libpng +universal
    3. portが読み込みディレクトリとswfmillが想定するディレクトリが異なるのでシンボリックリンクを置く
      • sudo ln -s /usr/X11/lib/libfreetype.6.dylib /usr/local/lib/
      • sudo ln -s /usr/X11/lib/libpng12.0.dylib /usr/local/lib/
    4. swfmill起動してdylibが足りないというエラーが出たら、2のようにdylib名称の尻尾を取ってportし、3のようにしてシンボリックリンクを置く
これで使えるようになるはずです。

swfmillの使い方は、またターミナル上での作業ですが、
  • SWFからXMLへの変換
    • swfmill swf2xml source.swf result.xml
  • XMLからSWFへの変換
    • swfmill xml2swf source.xml result.swf
と実行するだけです。他にも沢山機能があるようですが、今回使ったのはこれだけ。

蛇足ですがswfmillをダウンロード&解凍したディレクトリの中で作業するのであれば、
  • ./swfmill
とする必要があります。

変換処理を確認するためにSWFからXMLに変換したものをそのままSWFに変換しなおして動作確認してみてください。私の場合は多少SWFのサイズが変わったものの、動作が変わらなかったので一応OKとしました。

■画像差し替えのために■

XMLをエディタなどで開きます。PNG/GIF画像はDefineBitsLossless2のタグ内にbase64でエンコードされています。私の場合、対象画像のwidthから一発で目的の画像を探し当てることが出来たのですが、そういうヒントがない場合はバイナリのサイズなどから虱潰しに試してみるしかないかもしれないですね…みなさんのご健闘を祈ります。さて、あとは、差し替える画像をテキストに変換するだけです。

■どうやってPNG画像をエンコードするか■

ここは悩みました…。JPEGは比較的カンタンで、単純にBase64に変換してその文字列を<data></data>タグで挟めば良いらしいです。でも、GIF / PNGに関しては、技術的な解説記事が出ているし、Rubyでのライブラリもあるんですが…「ドラッグ&ドロップとは言わないが、せめてコマンドライン一発で変換するツール」みたいなのは見当たりません。

SFWMILLの解説ページにXMLに新しい画像ファイルを取り込む方法は書いてあるのですが、いろいろタグの書き方を変えてみたもののうまくいきません。楽をするためならどんな苦労をすることも厭わないので、帰りの電車で眉間に縦ジワ寄せつつ考えていたら…ひらめいた。画像を入れたSWFを作って、それをswfmillで変換すれば良いということにw

  1. 元の画像をswfmillでXMLに変換しておく
    • swfmill swf2xml Source.swf Source.xml
  2. FlashBuilderを起動、新しいFlashプロジェクトを作る
  3. 画像ファイルをプロジェクトに追加
  4. デザインビューでImageを貼り、さっきの画像ファイルをEmbed
  5. あとは何もいじらないで、リリースビルド
  6. bin-releaseの中の <project-name>.swfをXMLに変換
    • swfmill swf2xml image.swf image.xml
  7. 変換したXML(image.xml)をエディタで開き<data>タグを探す。
  8. 新しい<data><data>....</data></data>を古いものの上にコピペ
  9. swfmillでXMLをSWFに変換
    • swfmill xml2swf Source.xml Result.swf

■Mountain Lion上で動かして見る■

そういえばコントロールパネルからapacheを起動できなくなったんですね。これまたターミナルから、

で起動させて、ブラウザ上で
    http://localhost/
とタイプし「It works!」が表示されれば起動は成功。あとはさっき出来上がったswfを
    sudo cp test.swf /Library/WebServer/Documents/
などとコピーして、ブラウザでURLを入力します。
    http://localhost/test.swf
これで思った通りに画像が差し替わっていれば出来上がりです。

それにしても…オレもいろんなことやるなぁ…。

2013年2月21日木曜日

iOS 6にすると起動しない

サマリー

  • 現象:起動しない
  • 調査
  • 解決策1:エミュレータを削除
  • 解決策2:デバッガを変更

夏休みの宿題は8月下旬に始める子供だった私は、例によってリリース直前になって「そういえばiOS 6で試してなかった」ということに気づいて慌てるのだった(完)。



■現象:起動しない■

Xcode 4.5上でiOS 5.1用に作っていたアプリをiOS 6で起動しようとしたら、エミュレータが起動した直後、スプラッシュも出ないうちにアプリが即死します。デバッグコンソールすら出てくれません。

■調査■

XcodeのView->Debug Area->Activate Consoleでログを見るとそこには
    error: failed to attach to process ID 0
というエラーメッセージが出ていました。これをそのままGoogle先生で検索すると、日本語のページと、困った時のStackoverflowさんが2件。経験上、Stackoverflowさんを先に見ます。

■解決策1:エミュレータを削除■

まずその1(「error: failed to attach to process ID 0」)。結果的にはこれが大正解でした。

iOSシミュレータを終了してから、
  • ホーム下のLibrary/Application Support/iPhone Simurator/<対象バージョン>/Applications内の中にあるファイルを全て削除
これだけです。

なお、それ以前にiOSシミュレータの「コンテンツと設定をリセット...」も試したのですが、は効きませんでした。というかリセットしたり言語設定を切り替えるとそのままハングすることがあったのですが、削除してからは問題なしです。

■解決策2:デバッガを変更■

次がこれ(「Failed to Attach to Process ID Xcode」)。デバッガをLLDBからGDBに変更します。
  • XcodeのProduct->Edit Scheme
  • スキーマ編集画面で左側のバーから「Run YourApp.app Debug」を選択し、右側の「Info」タブを選ぶ
  • DebuggerをGDBに切り替える
  • Product->Clean

これでもまだアプリが立ち上がらない場合には、さっきのDebugger選択画面でLaunchを「Wait for YourApp.app to launch」に切り替えて、エミュレータ上でアプリのアイコンをタップしてみてください。それでもダメならDebugger=None。

ただ、一度起動するとLLDBに戻してもうまくいくという報告もあるので(「[Objective-C]iOSシミュレータでのデバッグができなくなった」)、iOSシミュレータでバージョンを切り替えたりした時にエミュレータの設定がおかしくなったのが原因ではないかなと思っています。

これでもうまく行かない場合は、対象アーキテクチャからarm7sを外す(「iPhone 5からはarmv7sアーキテクチャ」)というのもあるようです。特に外部のライブラリがarm7s非対応の場合はこれしかありません。私は先にこっちを試したのですが、変化ありませんでした。

2013年2月14日木曜日

AndroidのソフトキーボードでEditViewが隠れる場合

AndroidでEditTextがソフトキーボードに隠れてしまう件。

シングルラインであれば、AndroidManifest.xmlの該当するactivityの中に
    
    android:windowSoftInputMode="adjustPan"

を追加すれば解決することが多いですが、マルチラインの場合には
   
    android:windowSoftInputMode="stateVisible | adjustPan"

と書かないと最初の1行目しか見えません。よくある「ScrollViewを使う」等のwork aroundも試したのですが、結局、これが一番よく効きました。上記はScrollViewなしでも効いてます。

ただ機種依存やその他の設定による影響もいろいろあるようなので(この記事が参考になりました→「Android キーボードの出現と同時に画面がスクロールしないときに」)、あくまでも私のところでは…という話です。

ってかデフォルトをadjustPanにしといてくれよ>Google

DDMS post-create initでフリーズ

何か今日は沢山のBad Know-howが収集できて嬉しいorz

ADT/Eclipseを普通に終了してからMac(Lion)を再起動、再度ADTを起動したらstatusに

  DDMS post-create init

という表示が出てそのままフリーズしてしまった。Eclipseを強制終了して再起動してもダメ。

ググったら、StackOverflowでwork aroundが見つかりました。ありがたやありがたや。Eclipseがしっかり終了しているのを確認し(生き残っている場合には強制終了)、ターミナルでWorkspaceへ移動し、以下のコマンドを実行します。

  rm .metadata/.lock

これでEclipseは起動しました。いやはや。

2013年2月10日日曜日

userIdの取得

■userIdを知る■

自分がポストしたデータは表示しない、という処理を実装する場合にuserIdを知る必要があります。

古いForce.com SDKでは

AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *userId = [[[app coordinator] credentials] userId];

と書くこともできましたが、今はAppDelegateからSFOAuthCredentialsのインスタンスを見ることができません。最新のSDKで同じ事をする場合には

NSString *userId = [[[[SFRestAPI sharedInstance] coordinator] credentials] userId];

と書けばOKです。

■Xcodeバージョンアップ■

Xcode 4.4で作ったプロジェクトを4.5に持って行ったらエラーの山が出来てしまいました(今更ですが)。結局プロジェクトを修正するのは諦めて、最新のForce.com mobile SDKを入れて新しくプロジェクトを作りました。リソースなどをコピー、AppDelegateなどはソースをにらめっこして必要なところだけをコピーしましたが、ViewControllerについてはそのまま上書きです。その作業中に上記のエラーに遭遇した次第。

あとは「認証中」画面のxibからstoryboardの置き換えが残っています。以前のテンプレートではSFNativeRootViewController.mのsetupAuthorizingViewControllerを書き換えればStoryboardに置き換えるのも簡単だったんですが…app delegate上でオーバーライドするのも面倒くさい。

起動時に一度呼び出されるだけで他の実行には影響のない画面なので、ここはそのままxibで済ませましたm(_ _)m

2013年2月9日土曜日

マクドナルドのレジ



マクドナルドのレジは、コーヒーひとつ買うのに会話が多すぎてめんどくさい。最近は日本語があまり得意でない店員や不慣れな店員も多くて「えーと、ホットコーヒーのM、持ち帰り、砂糖ミルク袋要らない、Edy払い」なんてのが一発で通るのも珍しいぐらい。

「注文所要時間を短くするためにメニューを無くしました」なんて的はずれなことばっかりやっていないで、マクドナルドのレジがこんな具合になってたらもっと使いやすいんだがなぁ。

  1. 事前にスマフォ上でメニュー、支払い方法、袋はどうするか?などすべて入力
  2. レジにかざすとオーダ情報がすべて伝達、Edyで決済
  3. あとは品物を受け取るだけ

注文が5秒で終わるw

情報の伝達は既存レジだとEdyが付いているから、アプリからクラウド上に注文あげておいて、EdyのIDから引っ張ってくればおk

時間帯にもよるんだろうけど、繁華街にある店だと1/3-1/2ぐらいの客がスマフォ/ケータイのクーポンを見せているような感じかな? そのうちの半分がアプリで注文するようになれば、せっかちな客の満足度は上がるしレジの流れも早くなる。

さらに、「1週間分のランチ予約でクーポン!」などの販促もリンクしやすいし精度が高くなる。A店が空いているなとなったら「今から17時までA店限定でポテトが半額!」なんてpush notificationを流せば特定の店の稼働率をコントロールすることも可能になる。プリペイと組み合わせれば事前予約がキャンセルされにくくなる。

マクドナルドに限らず、苦手意識のあるヒトが少なからず存在するというスターバックスでも売上増につながると思うけどね。

2013年2月1日金曜日

Android:今日ハマったこと

■layout.xmlが壊れる■ 

Graphical Layoutでの作業。画面の最上部にRelativeLayoutを置きます。

その中に「左端にボタンA、真ん中にTextView、右端にボタンB」を配置しました。ボタンAは左寄せ、ボタンBは右寄せ、TextViewはAの右かつBの左を指定します。

ソースを保存してもエラーなし。


で、実行しようとするとエラー。TextViewのandroid:layout_toLeftOfで「そんなidない」って言われる。

原因は…xml上で、ボタンA,TextView,ボタンBの順番で並んでいるのにTextViewが後にあるボタンBを参照しているから…でした。


そりゃそうなんですけどね…Graphical Layout上で作業しているとエラーが出ない、でも一度エラーになるとXMLのソースを見ても手動でIDを付け替えてみても、どうにもなりません。現象だけ見ると、開発ツールがバグっててID管理テーブルが壊れているような感じなもので「+id/buttonA」と定数を対応付けているのはどこだろう、なんて無駄な探索をしてしまいました…。いやはや…。


■Activityが見つからないエラー■

またやってしまった>マニュフェストへの登録忘れ。

1日1回、忘れたころにやってしまう…。

今日はいくつもREST APIコールを書いたので、おかげさまでthreadとかrunnableとかhandler.postなんてのがソラで書けるようになりました。でもListViewのAdapterについては原理は何とか理解したものの、コードは覚えられない。