2013年1月31日木曜日

ACS Android SDKでハマる

ACSでググっても化学とか冠状動脈とかばっかりで、なかなか情報にたどり着けないのが困ったもんです。Appcelerator Cluod ServicesだとTitaniumばっかりだし(当たり前だけど)。ということで、ACS Android SDKでのハマりねた。

■Whereをどう書けば?■

Titanium mobileのSDKと違って、Android SDKはほとんど素のREST API SDKです。iOS SDKだと、あまり便利とはいえないけどCCWhereなんてクラスもあって、それなりにラップしてくれます。でもAndroidだと、こんな感じで書く必要があります。

    Map<String, Object> q = new HashMap<String, Object>();
    q.put("order", "-updated_at");
    q.put("where", "{\"email\":\"" + strEmail + "\"}");
    CCResponse r = sdk.sendRequest("users/query.json", 
                                   CCRequestMethod.GET, q);


…なんかperlでも書いている気分だ…書いたことないけど…。

まぁでも「ほぼREST」だと思ってしまえば、ある意味気は楽です。

ところで、Android 4以降はネットワークアクセスを別スレッドにしないと動いてくれません。

    public void acsThread() {
        listFriendsRequest = null;
            
        new Thread(new Runnable() {
            @Override
            public void run() {
                acsProcess();
            }
        }).start();
    }

そして終了後に画面切り替えたりするにはHandlerを使う必要があります。

以上をひとまとめにしてACSへのログインをActivity上に書くとこんな感じ。会社で使っているコードを貼るわけにはいかないので、記憶などを頼りにADT上で書いたもの。実働ソースではないので、もし不具合が出たらすみません。

    public void acsLogin(String inEmail, String inPassword) {
        final String email    = inEmail;
        final String password = inPassword;
        final Handler handler = new Handler();
        
        final JSONObject result = null;
        
        new Thread(new Runnable() {

            @Override
            public void run() {
                CCResponse r = null;
                
                Map<String, Object> q = new HashMap<String, Object>();
                q.put("login",    email);
                q.put("password", password);
        
                try {
                    r = sdk.sendRequest("users/login.json", 
                                        CCRequestMethod.POST, q);
                    CCMeta m = r.getMeta();
                    if ("ok".equals(m.getStatus()) 
                            && m.getCode() == 200 
                            && "loginUser".equals(m.getMethod())) 
                    {
                        result = r.getResponseData()
                                  .getJSONArray("users")
                                  .getJSONObject(0);
                    }
                }
                catch (CocoafishError e) {
                    e.getMessage();
                }
                catch (IOException e) {
                    e.getMessage();
                }
                catch (Exception ex) {}

                if (result != null) {
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            jsonUser = result;
                            Intent intent = new Intent(MainActivity.this, 
                                                       NextActivity.class);
                            startActivity(intent);
                        }
                    });
                }
            }
        }).start();
    }

何かもう1歩あるくたびにつまずいてググらないと進めない。

まぁiOSアプリ書いている時もそうですけどねorz

2013年1月30日水曜日

Android開発、いいとこ探し

Xcodeでの開発とくらべて、サクサク感に足りないところが多すぎるADTですが、とりあえずいいところを見つけました。

それはUI上のラベルなどを文字リソースとして追加しやすいということ。文字拡大するほどのことじゃないかw


たとえば、ボタンのラベルを文字リソースにする場合、PropertiesのText右端にある「…」をクリックするとResource Chooserが出てくる。



ここでNew Stringボタンをクリックすると「Create New Android String」、リソース名と文字列を入力すればおk


で、ここで追加したリソースは、javaソース上でも「R.id.」と入力すれば、入力補完してくれる。私は入力補完が便利になるようにリソース名を付けているので、とても楽。

Xcodeだと文字定数の入力補完が効かないので、それだけは羨ましい。

2013年1月26日土曜日

IBM Cast Iron


■IBM Cast Ironハンズオンセミナー■

IBM Cast Ironのハンズオンセミナーに行きました。

ドラッグ&ドロップ+設定ベースで、例えば「あるディレクトリをポーリングする。CSVファイルが投げ込まれたらこれに演算処理を加えて、条件によって異なるXMLファイルとして出力する」「ローカルのDBを読んで、必要な項目だけをSalesforceにUpsertする」なんてことが出来てしまう。一つ一つの処理要素をアクティビティと呼ぶのだけど、このアクティビティにはとにかく種類が沢山あって、「こんなことはできないか?」ということがすべて網羅されている。

■Apple, MS, IBM■

昔OS|2とかOpenDoc、最近はWork lightとCast IronしかいじったことないIBM童貞の感想なんですが…Appleの対局にあるのはMSやAndroidじゃなくてIBMじゃないかと思う今日このごろ。

昔から「正しいことをダメな方法でやるのがヒッピー(ジョブズ)、間違ったことを真面目にやっちゃうのがオタク(ゲイツ)」って言われたりしてたけど、IBMは「正しいことを徹底的に真面目に美しくやる」って感じですかね。「これはダメ」ってなったときの方向転換は小売店並に速いし。

ともかく、Appleが少ないルールでシンプルに、MSはとにかくスペックや機能を網羅しまくる方向であまり綺麗でない仕事をする、そしてIBMは徹底的に網羅するという点ではMSと似ているけどMSのように「あ、XXは出来ないんだねw」と15分でバレるような仕事をしないし網羅しまくっていても要素が整理されているので「コントロールパネルのどこで設定すりゃ良いんだよおおおお(怒」となることもない。

まぁくどいですが、あくまでもWork lightとCast Ironをハンズオンセミナーで少しいじっただけの感想です。実際の現場は涙目になるのがこの業界のお約束ってもんだけどね。

■アクティビティ■

よくある「モバイル☓クラウド」な案件でAndroid屋さんとCast Iron屋さんが同席して技術的な話をしたらお互いに一瞬ニヤッとする…はず>アクティビティ / Activity

もっとも、Cast Ironのアクティビティというネーミングはとても納得がいくんだけど、AndroidのActivityは未だに違和感ある。

2013年1月25日金曜日

Xcode 4.5でiOS 5.1対応プロジェクトを作る

サマリー:

  • Xcode 4.5で作ったアプリがiOS 5.1上でクラッシュ
  • Deployment TargetをSDK 5.1にしたけどそれでもクラッシュ
  • Autolayoutが原因じゃった
  • 余談:Android開発は辛いよ

■いきなりクラッシュ■

Xcode 4.5移行後に作ったプロジェクトをまだiOS 6でしか動かしていないことに気づき、iOS 5.1 SDKを入れて試したところ、即死しました。iOS 6なら動きます。iOS 6固有の機能なんて何も追加した覚えがないのになーと真っ青になりました。

■原因■

Autolayout機能を使ったことが原因でした。エラーメッセージの中に出てきたNSLayoutConstraintでググって判明しました。いやはや…。



■SDK 5.1の組み込み方■

一応書いておきます。iOS SDK 5.1はXcode 4.4に含まれていますので、
  • developer.apple.comのdownloadsからXcode 4.4をダウンロード
  • xcode_4.4.1_xxxxxxx.dmgをマウントし、Xcode.appを右クリック「パッケージの内容を表示」を選び、 Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKsにあるiPhoneOS5.1.sdkを /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs にコピーします。ディレクトリ深いわ。
  • Xcodeを再起動
これでiOS Deployment Targetとして「5.1」を選べるようになります。ProjectのPROJECTとTARGETSにある「iOS Deployment Target」を5.1にセットしてください。エミュレータで5.1を選べるようになります。


■対策 - Autolayoutを切る■

Storyboardをクリックし、Identity and Typeの「Interface Builder Document」にある「Use Autolayout」のチェックボックスをoffにします。


これで、Xcode 4.5で作ったプロジェクトをiOS 5.1で起動しても落ちなくなります。

なお、MainStoryboard_iPhone.storyboardだけでなくMainStoryboard_iPad.storyboardも直しておくことをお忘れなく(と経験者は語る…)

■Autolayout■

Autolayoutがonだと余計な補助線が出てきてウザいです。これ、Androidの開発ツールにも似たような機能があるんですが…ご安心ください、Androidのはもっとウザいです。縦横比の異なるiPhone5をサポートするにはリキッドレイアウトが一番無難ではあるわけですが…

■余談■

最近気づいて驚いたのですが。Androidってソフトキーボードが出た/引っ込んだを検出するイベントがないのね…。ソフトキーボードが出てくると、真ん中辺に置いたEditTextは自動的に縮むんだけど、移動はしてくれない。移動はプログラマがやらないといけないんだけど、「キーボード出たよ」ってイベントがない。「viewが縮んだ」ってイベントを使って間接的に検知するしかない。間接的だから副作用を避けるためにはいろいろ小細工しなければならない。iOSならこんなにイベントあるのに。


  • UIKeyboardWillChangeFrameNotification
  • UIKeyboardWillHideNotification
  • UIKeyboardDidChangeFrameNotification
  • UIKeyboardDidHideNotification
  • UIKeyboardWillChangeFrameNotification
  • UIKeyboardWillShowNotification
  • UIKeyboardDidChangeFrameNotification
  • UIKeyboardDidShowNotification


Android開発、しんどいです…。優しい上司は「難しければ、iPhone版を先に出して、Android版外注にしようかねぇ」と言ってくださるのですが…社内にiPhoneユーザが少ないので、iPhoneだと十分なテストが出来ないです。困った…。

2013年1月21日月曜日

Titanium mobileその後、とMonaca


今回の要約:
  • Titanium Updates Available
  • Titanium mobile:異常の原因
  • Monacaを試した

■Titanium Updates Available■

Titanium Studio起動時に、自分ちのMacではログイン認証求められないのに会社のMacだとid/passwordを入れないとダメってのは何が原因なのか未だに不明。

それとTitanium Studioを起動したら、Titanium Updadates Availableが出ました。「もしかして、今抱えている問題がこれで片付くかも!」とwktkしながらクリックしたら…Alloy 0.3.6だったorz

いやいや「orz」したら失礼ってかAlloyには少しは期待しているんだけど、でも、そろそろTitanium 3.0.1とか出ても良いんでないの?出てくれないかな??出てくれるよね???と思っていたものですから。すいません。

今のところMVC3層モデル対応のmobileアプリ用JavaScriptフレームワークというとSenchaが先行している感じだけど、UIレイアウトツールのないTitaniumがAlloyによってリキッドレイアウトとMVCモデルを同時に取り込むことができたら、少なくともビジネス系モバイルアプリ開発にもっと踏み込むことができる、はず。期待してます。

■Titanium mobile:異常の原因■

さて、本題。結局不具合はイベントの異常によるものでした。

selfがwindowで、すでにfocusがあるにも関わらずwindows上のTextFieldがタップされた時にself.addEventListener('focus', function() {});が呼び出されてしまうことが原因。selfのfocusイベントで初期値を設定していますが、password/emailをタップするたびに初期化されるのだからそりゃ入力できないのも当たり前。

iOSとAndroidで挙動が違いますね。iOSではTextFieldをタップしてもfocusが発火することはありません。

こういうのを潰すのは大変です…。

■Monacaを試した■

jQuery mobileというよりHTML5ならAndroidのフラグメントをいくらか吸収できるので、とりあえずお試し。以前XCodeの上でPhoneGap+jQuery mobileを動かしたことはあるものの今回のプロジェクトではAndroidが対象なので開発環境を用意しなければなりません。

一応、クロスプラットフォームであまり面倒なことなしに使える、ということでまずはMonacaを試してみました。

Monaca.mobiにアクセスしてアカウントを登録、するとすぐにブラウザ(私はSafari 6.0.2+Mountain Lion)上でIDEを使えます。このIDEがとてもブラウザ上で動いているとは思えないほど、というかEclipse上のADTよりもサクサク動くから泣けます。

IDEに付属しているスマフォビューワは必要最小限の機能で再現性も低いので、とりあえずAndroid用アプリとして提供されているMonacaデバッガを使います。今回はエミュレータ上にデバッガをインストール。
  1. Androidエミュレータ上でブラウザを起動
  2. ブラウザにMonaca.mobiのデバッガ配布URLを入力→自動的にダウンロード
  3. Downloadsからファイルをタップすればインストール完了
  4. 起動して、さっきMonaca.mobiに登録したアカウントを設定
  5. アプリ一覧が表示→デバッグしたいアプリをタップすればすぐ起動
  6. IDE上で更新したら、デバッガ上の更新ボタンをタップすればすぐに更新
もう恐ろしいほどスムーズです。

で、さくさくと試験用のGUIを作って、さてACSを読み込もうとしたら…jQueryの対象バージョンがMonacaとACSとで異なるのでアウトでしたorz

というわけで、ACSについてはダメでしたが、jQuery mobile開発環境としてはとてもよくできていますので、今後時間を見つけて試そうと思ってます。

2013年1月20日日曜日

ムービーアプリがリジェクト

お友達からの依頼で作ったiPhoneアプリ、リジェクトされました。

理由:「ムービーだけならiTunes Storeから売れや」

昔は良かった…。

というわけで、お友達から「参考にして」と言われて買った「AKB48」アプリや「We are the world」アプリを眺めつつ、機能を大幅アップ中。AKB48はともかくWe are the worldなら技術的にはそう難しくないんだけど、ちょこっとしたアニメーションとか配色なんぞのさりげないセンスが難しい…。

2013年1月19日土曜日

iPhoneアプリ開発のお勉強

iPhoneアプリ開発について、ググれば大抵のことは出てきます。でも、古い人間なもんで、本を読まないと全体像が頭に入りません。

新しいプラットフォームを学ぶ場合、私(痛い目に合わないと学習しないタイプ)は:
  • (概念がわからない時は)まず雑誌や本を片っ端から斜め読みする
  • 入門書のチュートリアルに沿って実習
    • これは開発環境などの確認です。超初心者だと環境が悪いのか自分が悪いのかがわからないので、そのロスを防止します
  • とりあえず自分の好きなものを作ってみる
  • 当然ハマるのでググりつつ進む
  • 上級編の書籍を熟読するか、セミナーに出る
で。

なんだかんだでこれまで買った本は10冊ぐらいだと思います。とりあえず、その中で役に立ったものを何冊かピックアップします。

■まず入門編■

よくわかるiPhoneアプリ開発の教科書【iOS 5&Xcode 4.2対応版】
「何だかよくわからないんだけど、とりあえず作ってみよう」「『来週までに簡単なiPhoneアプリ1本作って』って言われたけど、どーすればw」そんな時にお役に立ちます。ある程度自信と経験のあるヒトは後述の「10日でおぼえるiPhoneアプリ開発入門教室」から始めても良いと思います。

■実践編■

10日でおぼえるiPhoneアプリ開発入門教室 (10日でおぼえるシリーズ)
有料セミナーで教科書として使われていた本。上の「教科書」は小さなサンプルが沢山乗っていてとにかく動くようにする、こっちは開発フローを意識してある程度ボリュームのあるサンプルを丁寧に教えていく感じです。入門書の割にコードもしっかり正しく書かれているので悪い癖がつきにくいと思います。まぁ10日で覚えるのはまず無理ですがw

■学習編■

詳解 Objective-C 2.0 第3版
ARCが導入されたからあんまり意識しなくていいんじゃねーの?という見解もあったりしますが、やっぱりこの変な言語についてはしっかり学んでおかないといけません。もう一冊入門 Objective-C 2.0 (Programmer’s SELECTION) の方もコード例が沢山乗っていてわかりやすいですが、言語の教科書としては「詳解」の方がしっかり学べるかなと思います。

■これが電子書籍だったら編■

iOSプログラミング逆引きリファレンス110 [iOS 5.1対応]
この本に書かれている内容を全文検索できるなら、もうアップルその他に問い合わせしなくても良いんじゃね?と思うくらい、びっしり情報のツマった本。もうお世話になりっぱなし。気力と記憶力のあるヒトは、精読しておくことをお勧めします。そうすれば具体的なAPIは覚えていなくても、誰かに相談された時に「できるか、できないか」の判断ができますから。

Titanium mobile、どうも困った…

記事に要約つけることにしました。
  • TitaniumアプリのAndroid版でフラグメントに遭遇
  • Titaniumあかんか…という気配
  • 次はNative+jQuery。いや、いっそNative+Airでw

iPhoneでは問題ない…■

会社でTitaniumを使ってちょっとしたアプリを書いてます。iPhoneでテストしてひと通り動くようになったところでAndroidエミュレータでテスト、画面の差異などを吸収したりソース分けたりして社内テスターにリリース。

そこで問題発生、Android OSバージョン:
  • 2.3.3では問題なし
  • 2.3.4では動くヒトと動かないヒト
  • 2.3.5では起動すらしない
  • 4以降は今のところ問題なし
いろいろ追いかけてみたところ、スマートフォンなのにisTabletがtrueで返ってきてしまってあちこち矛盾するのが原因らしいと判明。2.3.5のエミュレータなんて無いからテストできないですよorz

今回Titaniumを使うことになったのは、クロスプラットフォーム性を最重視、であればPhoneGap+jQueryより少しはサクサク動くTitaniumの方が良いか…という判断でした。Androidのフラグメントについては皆さん了解済だったんですが、0.0.1の違いでバラついてしまい、同じバージョンでも差異が出てしまうというのはさすがにアウトだなぁという空気になりまして。まぁそりゃそうですわな。

それなりにwork aroundもあるとは思うんですが、Titanium SDK 3.0.0も出たばかりでそのバグフィックスリストを見ると、ちょっとこれはシンドいかなという気分に。「JavaScriptからブラウザを経由しないでネイティブのAPIを叩くからjQueryより少し軽い」というのはメリットなんですが…ランタイム上のネイティブなオブジェクトを参照する辺りの処理がイマイチ書き切れてない感じです。以前もviewのframeサイズを拾ってこようとしたら何やっても0しか返って来ないってこともあったっけ。ごく基本的なAPIがreferenceに書いてある通りに動かないのはイカンよなぁ…。

今回Titaniumの評価も兼ねたプロジェクトだったわけですが…とりあえずACS(Appcelerator Cloud Service)はそのまま使うけど、Titaniumについてはしばらくペンディング…ということになりそうです。

個人的にはUIエディタのないツールでプロトタイプを作るのはイヤなので、ちょっと助かったとです。リキッドレイアウトが協力ならまだ良いんだけどねぇ。

ホントならここでSenchaへ行きたいところなんですが、ツールを買い揃える予算がないのでMonaca方面で試行錯誤中。

しかし…jQuery mobileについて勉強してた当時はある程度ソラで書けるようになっていたのに、また「えーと、画面と画面を区切るのはなんだっけ…(ググり中)そうそう <div data-role="page" id="foo"></div> だった」なんてところまで退化していて困ったもんだ。

個人的には「そんなにクロスプラットフォームが良いなら、iPhone版はNativeで書くとしてもAndroid版を含めて残り全部Adobe Airで良いんじゃね?」と鬼のようなことを考えていたりもするのですがw