Pages

2011年7月17日日曜日

Titanium Mobileで Twitterアプリを作る

Titaniumで、Twitterクライアントを作成してみる。まあ、表示のみだが。
参考にしたのは、
http://gihyo.jp/dev/serial/01/titanium/0002
http://developer.appcelerator.com/blog/2011/06/titanium-studio%E3%81%A8titanium-mobile-1-7%E3%82%92%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F.html?lang=ja
http://code.google.com/p/titanium-mobile-doc-ja/wiki/get_started


記事の通りに進めてみたが、うまく表示しない。空のTableViewだけが表示される。
この解析だけで、随分と時間を食ってしまった。
結論から言うと、単なるスペルミスだったのだが....

JavaScriptでは宣言されていない変数もエラーにならない

え!そうだったけ!!
おかげで、いろいろと試行錯誤し、勉強になった。ポイントは以下の通り。
  • デバックするためには、Ti.API.info() が便利
  • サンプルコードを疑わないためにも、お手本となる動くソースが必要。Appcelerator社が提供しているサンプル集[KitchenSink]をTitanium Studioでダウンロード出来る

KitchenSinkのTwitterソースを参考に、Gihyo.jpのソースを修正したものが以下の通り。


右のように、iPhoneシミュレータで私のツイートを表示することが出来ました。ああ疲れた。

  1. //背景色をセット  
  2. Titanium.UI.setBackgroundColor('#000');  
  3. //[タブグループ]オブジェクトtabGroupを作成  
  4. var tabGroup = Titanium.UI.createTabGroup();  
  5. //[ウインドウ]オブジェクトwin1を作成  
  6. var win1 = Titanium.UI.createWindow({    
  7.     title:'Tab 1',  
  8.     backgroundColor:'#fff'  
  9. });  
  10. //[タブ]オブジェクトtab1を作成し、win1をプロパティにセットする  
  11. var tab1 = Titanium.UI.createTab({  
  12.     window:win1  
  13. });  
  14.   
  15. // Twitter ここからはTwitter機能の実装  
  16. // ======================================================================  
  17. // TableViewオブジェクトを初期化  
  18. var tableView = Ti.UI.createTableView({  
  19.  data: [];  
  20. });  
  21.   
  22. // HTTPClientオブジェクトを作成  
  23. var xhr = Ti.Network.createHTTPClient();  
  24. xhr.timeout = 1000000;  
  25. var user = 'silentbaker';  
  26.   
  27. // HTTPClientオブジェクトで Twitter APIを操作。接続用メソッド?をセット  
  28. xhr.open("GET","http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+user);  
  29.   
  30. // 読み込み時(onloadイベント)の処理を関数で定義  
  31. xhr.onload = function()  
  32. {  
  33.  // タイムラインを配列に格納。JSON.parseが出来る。従来通り? evalも可能。  
  34.  var timeline = JSON.parse(this.responseText);  
  35.  //var timeline = eval('('+this.responseText+')');  
  36.  var currentData = [];  
  37.  // デバックの時には、Ti.API.info()を使いましょう  
  38.  Ti.API.info(timeline.length);  
  39.  // テーブル行を作成し、そのラベル プロパティにツイート文をセット  
  40.  for(var i=0 ; i < timeline.length ; i++){  
  41.   var tweet = timeline[i];  
  42.   var row = Ti.UI.createTableViewRow();  
  43.   var commentLabel = Ti.UI.createLabel();  
  44.   commentLabel.text = tweet.text;  
  45.   Ti.API.info(commentLabel.text); // Debugのため  
  46.   row.add(commentLabel);  
  47.   currentData.push(row);  
  48.  }  
  49.  // 各行(オブジェクト)の配列をtableViewオブジェクトにセット  
  50.  tableView.setData(currentData);  
  51. };  
  52. // HTTPメッセージを送信する (この時、onloadイベント発生?)  
  53. xhr.send();  
  54. // end of twitter  
  55. // =====================================================================  
  56.   
  57. win1.add(tableView);   // テーブルオブジェクトをウインドウwin1に追加  
  58. win1.hideTabBar();     // タブバーは隠す  
  59. tabGroup.addTab(tab1); // タブグループにタブtab1を追加  
  60. tabGroup.open();       // アプリケーションを起動 tabGroup -> tab1 -> win1 -> tableView  
//背景色をセット
Titanium.UI.setBackgroundColor('#000');
//[タブグループ]オブジェクトtabGroupを作成
var tabGroup = Titanium.UI.createTabGroup();
//[ウインドウ]オブジェクトwin1を作成
var win1 = Titanium.UI.createWindow({  
    title:'Tab 1',
    backgroundColor:'#fff'
});
//[タブ]オブジェクトtab1を作成し、win1をプロパティにセットする
var tab1 = Titanium.UI.createTab({
    window:win1
});

// Twitter ここからはTwitter機能の実装
// ======================================================================
// TableViewオブジェクトを初期化
var tableView = Ti.UI.createTableView({
 data: [];
});

// HTTPClientオブジェクトを作成
var xhr = Ti.Network.createHTTPClient();
xhr.timeout = 1000000;
var user = 'silentbaker';

// HTTPClientオブジェクトで Twitter APIを操作。接続用メソッド?をセット
xhr.open("GET","http://api.twitter.com/1/statuses/user_timeline.json?screen_name="+user);

// 読み込み時(onloadイベント)の処理を関数で定義
xhr.onload = function()
{
 // タイムラインを配列に格納。JSON.parseが出来る。従来通り? evalも可能。
 var timeline = JSON.parse(this.responseText);
 //var timeline = eval('('+this.responseText+')');
 var currentData = [];
 // デバックの時には、Ti.API.info()を使いましょう
 Ti.API.info(timeline.length);
 // テーブル行を作成し、そのラベル プロパティにツイート文をセット
 for(var i=0 ; i < timeline.length ; i++){
  var tweet = timeline[i];
  var row = Ti.UI.createTableViewRow();
  var commentLabel = Ti.UI.createLabel();
  commentLabel.text = tweet.text;
  Ti.API.info(commentLabel.text); // Debugのため
  row.add(commentLabel);
  currentData.push(row);
 }
 // 各行(オブジェクト)の配列をtableViewオブジェクトにセット
 tableView.setData(currentData);
};
// HTTPメッセージを送信する (この時、onloadイベント発生?)
xhr.send();
// end of twitter
// =====================================================================

win1.add(tableView);   // テーブルオブジェクトをウインドウwin1に追加
win1.hideTabBar();     // タブバーは隠す
tabGroup.addTab(tab1); // タブグループにタブtab1を追加
tabGroup.open();       // アプリケーションを起動 tabGroup -> tab1 -> win1 -> tableView

Titanium MobileでiPhoneアプリ開発環境を作る

Titanium は、"チタニウム"ではなく"タイタニウム"と発音するらしい。Titan(巨人族)と関係あるのだろうか。JavascriptでiPhone, Androidアプリケーションの開発が出来る開発環境(SDK)だ。
この開発環境がすばらしいのは、iPhoneのAPIを操作できるアプリケーションを作成できること。カメラやGPS機能などを操作できるらしい。
早速、インストールしてみる。
ここを参考にしました。
http://developer.appcelerator.com/
http://developer.appcelerator.com/blog/2011/06/titanium-studio%E3%81%A8titanium-mobile-1-7%E3%82%92%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F.html?lang=ja

手順は
  1. OSXに開発環境XCodeとiOS SDKをインストール
  2. Titanium mobileをインストール
  3. Hello Worldしてみる
  4. Apple IDを取得(実機にインストールするため)

X Codeのインストール

1年前に入れたのだがバージョンが古いので、最新の4.0.2をMac AppStoreから、600円で購入。600円は高いのか、安いのか、よう判らん。昔は只なので。

インストールサイズは、なんと4G。一晩掛かりました。

Titaniumをインストール

Titaniumのアカウントを取得する。
参考にした記事では、Titanium SDKがダウンロードされるはずでしたが、Studioがダウンロードされました。有償の罠にはまったかとドキドキ。どうやら、6月14日から全てがStudio (Appcelerator Titanium Studio version 1.7)に統合され配布されることになった様子。オリジナルは、eclipusのらしい。日頃の開発はVimでやっているので、ちょっと不安。どうもIDEは、覚えなければならないことが余計にでてくるみたいで面倒なんだが。

Hello World

Appcelerator社の開発者サイトの記事通りにやって、特に問題なく終了。iPhoneシミュレータが起動した時には、ちょっとした感動ものです。(右図)



プロジェクトを作成した時に自動的に生成される初期ソースを以下解説。
  1. // Master UIView (Titanium.UI) に背景色をセットする  
  2. Titanium.UI.setBackgroundColor('#000');  
  3. // タブグループを用意。  
  4. var tabGroup = Titanium.UI.createTabGroup();  
  5. // ウインドウwin1を用意。  
  6. var win1 = Titanium.UI.createWindow({    
  7.     title:'Tab 1',  
  8.     backgroundColor:'#fff'  
  9. });  
  10. // タブtab1を追加し、前に追加したウインドウwin1を結びつける  
  11. var tab1 = Titanium.UI.createTab({    
  12.     icon:'KS_nav_views.png',  
  13.     title:'Tab 1',  
  14.     window:win1  
  15. });  
  16. // ラベル label1を用意し、ウインドウwin1に追加。  
  17. var label1 = Titanium.UI.createLabel({  
  18.  color:'#999',  
  19.  text:'I am Window 1',  
  20.  font:{fontSize:20,fontFamily:'Helvetica Neue'},  
  21.  textAlign:'center',  
  22.  width:'auto'  
  23. });  
  24. win1.add(label1);  
  25. // ウインドウ win2、タブ tab2 (win2をセット)、label2を用意。  
  26. var win2 = Titanium.UI.createWindow({    
  27.     title:'Tab 2',  
  28.     backgroundColor:'#fff'  
  29. });  
  30. var tab2 = Titanium.UI.createTab({    
  31.     icon:'KS_nav_ui.png',  
  32.     title:'Tab 2',  
  33.     window:win2  
  34. });  
  35. var label2 = Titanium.UI.createLabel({  
  36.  color:'#999',  
  37.  text:'I am Window 2',  
  38.  font:{fontSize:20,fontFamily:'Helvetica Neue'},  
  39.  textAlign:'center',  
  40.  width:'auto'  
  41. });  
  42. win2.add(label2);  
  43. // タブグループにtab1, tab2を追加  
  44. tabGroup.addTab(tab1);    
  45. tabGroup.addTab(tab2);    
  46. // タブグループを(初期で)起動する  
  47. tabGroup.open();  
// Master UIView (Titanium.UI) に背景色をセットする
Titanium.UI.setBackgroundColor('#000');
// タブグループを用意。
var tabGroup = Titanium.UI.createTabGroup();
// ウインドウwin1を用意。
var win1 = Titanium.UI.createWindow({  
    title:'Tab 1',
    backgroundColor:'#fff'
});
// タブtab1を追加し、前に追加したウインドウwin1を結びつける
var tab1 = Titanium.UI.createTab({  
    icon:'KS_nav_views.png',
    title:'Tab 1',
    window:win1
});
// ラベル label1を用意し、ウインドウwin1に追加。
var label1 = Titanium.UI.createLabel({
 color:'#999',
 text:'I am Window 1',
 font:{fontSize:20,fontFamily:'Helvetica Neue'},
 textAlign:'center',
 width:'auto'
});
win1.add(label1);
// ウインドウ win2、タブ tab2 (win2をセット)、label2を用意。
var win2 = Titanium.UI.createWindow({  
    title:'Tab 2',
    backgroundColor:'#fff'
});
var tab2 = Titanium.UI.createTab({  
    icon:'KS_nav_ui.png',
    title:'Tab 2',
    window:win2
});
var label2 = Titanium.UI.createLabel({
 color:'#999',
 text:'I am Window 2',
 font:{fontSize:20,fontFamily:'Helvetica Neue'},
 textAlign:'center',
 width:'auto'
});
win2.add(label2);
// タブグループにtab1, tab2を追加
tabGroup.addTab(tab1);  
tabGroup.addTab(tab2);  
// タブグループを(初期で)起動する
tabGroup.open();

Apple Developer Programへの参加

1万円ぐらいかかるので、もう少し技術が熟練してからですね :-p

2011年7月10日日曜日

rails + google map を試す

Google APIを試してみた。以下のサイトを参照しました。
http://kenjiro2u.blogspot.com/2009/09/google-maps-on-rails.html
http://d.hatena.ne.jp/zariganitosh/20081012/1223816212
http://ym4r.rubyforge.org/

構成は
* rails 2.3.8
* ym4r-gm --- google map APIを扱うプラグイン
* Google API

まずは、テストプロジェクトを作成し、Google APIを取り扱うプラグインYM4R/GMをインストール。
  $ rails map_test
  $ cd map_test
  $ sudo gem install ym4r
  $ ruby script/plugin install git://github.com/queso/ym4r-gm.git
  $ script/generate controller Map index 

Google Map APIを使うため、Google Maps API Keyを取得します。
4年程前かな。なぜか、このKeyの取得が上手くいかずに凝っただが、今回は簡単にGet。日本語のドキュメントが整備されているのが大きいな。
http://code.google.com/intl/ja/apis/maps/signup.html

日本語ドキュメントは大変貴重で、いろいろと気になることが判った。
* ドメイン名で取得することが吉。www.miyabiit.com ではなく、miyabiit.comでとる。
* localhost は無条件で使える。開発のため。もちろん、自分自身しかみえないけど。
* ビジネス利用のためpremierサービスがある。パスワード利用のサイト構築、有償サイトは要検討。

取得したKeyは、/config/gmaps_api_key.yml に記載します。このファイルはプラグインインストール時に自動作成されているはずです。

html header部に、以下の2つのヘルパーメソッドを埋め込み、必要なjavascript, htmlコードを生成します。
layoutファイルを利用したので、以下のように作成。

  1. <%= GMap.header %>  
  2.   <%= @map.to_html %>  
<%= GMap.header %>
  <%= @map.to_html %>

コントローラ /app/contoller/map_controller.rb にて @mapを生成し、viewに渡します。
  1. def index  
  2.     palo_alto = [37.4419, -122.1419] # 位置情報を配列で用意  
  3.     # google map api オブジェクトを作成。表示タグ map_div  
  4.     @map = GMap.new("map_div")         
  5.     # 位置の表示  
  6.     @map.center_zoom_init(palo_alto, 10)  
  7.     # 拡大縮小ボタン、地図タイプ切り替えボタン  
  8.     @map.control_init(:large_map => true:map_type => true)  
  9.     # マーカの指定  
  10.     @map.overlay_init(GMarker.new(palo_alto,  
  11.       :title => "パロアルト",  
  12.       :info_window => "これは情報窓"  
  13.       )  
  14.     )  
  15.   end  
def index
    palo_alto = [37.4419, -122.1419] # 位置情報を配列で用意
    # google map api オブジェクトを作成。表示タグ map_div
    @map = GMap.new("map_div")       
    # 位置の表示
    @map.center_zoom_init(palo_alto, 10)
    # 拡大縮小ボタン、地図タイプ切り替えボタン
    @map.control_init(:large_map => true, :map_type => true)
    # マーカの指定
    @map.overlay_init(GMarker.new(palo_alto,
      :title => "パロアルト",
      :info_window => "これは情報窓"
      )
    )
  end

viewには以下のコードを埋め込みます。
  1. <%= @map.div(:width => 500, :height => 400) %>  
<%= @map.div(:width => 500, :height => 400) %>

これで、railsを実行すれば以下のような画面をみることが出来ます。