Pages

2011年8月20日土曜日

iPhoneアプリ(Titunium)からWebアプリ(Ruby on Rails)へのデータ転送

TutorialのTwitterアプリでWeb API経由でデータを取得する方法の勘所をつかんだので、iPhoneからWebアプリへのデータのアップロードを試してみる。

Webアプリケーション

Webアプリ側は、手っ取り早く Ruby On Railsで作成。
(Railsのヴァージョンは、2.3.8を入れてあるので、databaseのdefaultは、sqlite3)
Webアプリのイメージは、在庫管理用の商品コードの保管と表示。モデルは、在庫Stock。StockをiPhone側から扱うコントローラは、Apiと言う名前にした。
$ rails testapp
$ cd testapp
$ script/generate model Stock
$ script/generate controller Api index

"Stock" modelのmigrationの中身は、以下の感じ
create_table :stocks do |t|
	t.string :name # 商品名 今回は、無用。
	t.string :code # 商品コード
	t.timestamps
end

controllerの中身は、WebAPI的なのりで作成してみた。APIの仕様?は以下の通り。
http://hogehoge/api/               --- 全てをjson形式で提供(表示)
http://hogehoge/api/show/code_no   --- コード = code_no のstockをjsonで提供
http://hogehoge/api/upload/code_no --- 新しいデータを登録 code = code_no

例外処理とか未だ入れてないので、エラー頻発だ。

class ApiController < ApplicationController
    # 全て表示のアクション
	def index
		@stocks = Stock.all
		# レスポンスは、jsonにフォーマットして出力
		respond_to do |format|
			format.json { render :json => @stocks, :callback => params[:callback] }
		end
	end

	# 商品コードを指定して出力
	def show
		@stock = Stock.find_by_code(params[:id])
		respond_to do |format|
			format.json { render :json => @stock, :callback => params[:callback] }
		end
	end

	# 今回の主役。商品コードを受け取り、データベースに保管する
	# レスポンスは、textにした
	def upload
		message = 'Upload Error'
		if params[:id] && stock = Stock.new({:code => params[:id]})
			message = 'Save New Code :' + stock.code if stock.save
		end
		render :text => message
	end
end

これで、script/server でテストサーバを起動。
http://hogehoge:3000/api/ を試してみた。確かにjson形式で出力されている。


Titunium側のプログラム(一部)

さて、Tituniumアプリ側の該当部分。HTTPClientオブジェクトを操作する。

var win = Ti.UI.currentWindow;
var sendButton = Ti.UI.createButton({
	title:'Send Data',
	top:200,
	left:10,
	width:300,
	height:100
});
win.add(sendButton);

// sendボタンのclickイベントを記述
sendButton.addEventListener('click', function(){
	// HTTPClientオブジェクトを用意
	var xhr = Ti.Network.createHTTPClient();
	xhr.timeout = 1000000;
	var sample = '12345'; // サンプルデータ
	var url = 'http://hogehoge:3000/api/upload/' + sample;
	xhr.open('GET',url);
	// ロードされた場合の処理を記述。
	// ここではレスポンスを受け取ってダイアログボタンに結果を返すと定義。
	xhr.onload = function(){
		var res = this.responseText;
		Ti.UI.createAlertDialog({
	  		title: 'Send Data',
	  		message: res
	  	}).show();
	};
	// リクエストを送信する。レスポンスが帰ったときに、onloadアクションとなる。
	xhr.send();
});

iPhoneアプリをエミュレータで起動。[send]ボタンを押すと、サーバアプリにサンプルデータが送信され、その結果がモーダルボタンで表示される。

気になったこと
  • ボタンイベントに変数(この場合はデータ)を渡す方法
  • HTTPClientの接続失敗の処理方法
  • send()のタイミングは、正しいか?

2011年8月14日日曜日

OSX Lionのsandboxとは

Macの最新OS OSX Lionでは、セキュリティ面で大きな変更が行われている。マイクロソフトは、セキュリティとして自前のセキュリティソフトの提供を行っているが、Macはどうだろうか? 気になっていた点を解説している記事をみつけたので、英訳を試みてみた。

http://arstechnica.com/apple/reviews/2011/07/mac-os-x-10-7.ars/9

サンドボックス

Appleが静かにしているからといって、それはセキュリティに関して何も改善の歩を進めていないわけではありません。レパード(OX 10.5)にて、Appleは「サンドボックス」の基本的な形を加えました。スノーレパード(OX 10.6)では、デーモンプロセスの多くは「サンドボックス」内で動くようになりました。これらは、何のファンファーレも鳴らさずに行われているのです。

アプリケーションをサンドボックスの内側で動かすことは、マルウエアなどによって信用出来なくなった場合の被害を最小限に抑えることを意味します。サンドボックス化したアプリケーションは、通常のアプリケーションでは出来る様々な出来る機能を自ら制限します。例えば、通常のアプリは、そのユーザによって作成されたファイルを(同じユーザが)削除することが出来ます。当然ですが躾の良いアプリは、そんなことはしません。しかし、いったん障害が起きると、破壊的な行為が引き起こされてしまうかもしれないのです。

Lion (OSX 10.7)では、「サンドボックス セキュリティ モデル」が大きく拡張されました。Appleは、サードパーティに、サンドボックス化を強く進めています。サンドボックス化アプリは、利用する資源、機能を一覧にした「権限付与リスト」を中に持っています。
訳者注)OSXのアプリは、一見exeバイナリに見えますが、実態はフォルダです。
Lionは、30もの異なる権限リストをサポートしています。中には、ネットワーク接続を作成する権限リストや、ネットワーク接続を通じてListenする権限リストなどもあります。これらは、(ネットワーク接続関連ですが)別の2つの権限リストです。ビデオのキャプチャや組み込みカメラに接続するための権限などもあります。

(途中省略。ファイル関連のサンドボックスの権限付与リストの作成はどうするのか? 的な話。)

Appleは、ファイルの扱いなど特別な分類の行動群に高度な制限を与えることで、権限ファイル権限リスト更新の問題を解決しようとします。Lionでは、Powerbox(pboxd)と呼ばれる信頼されたデーモンプロセスが提供されています。Powerboxデーモンは、サンドボックス化されたアプリケーションにファイル表示やオープン・保存のためのダイアログを提供します。サンドボックス化されたアプリがファイルを選んだあと、Powerboxは、そのアプリのサンドボックスに小さな穴をあけます。

(途中省略。似たような機能は「最近開いたファイル」メニューに利用されている、的な話)

サンドボックス化されたプロセスは、アクティビティモニターで見ることができます。
(このイメージは、訳者のものです)

近い将来、Mac App Storeは、Appleが新しいLionテクノロジを普及させる方法として、使われていくでしょう。サンドボックスの場合、すでにそれは行われているようです。Appleは、11月から全てのアプリはサンドボックス化しないと許可しないと宣言しています。



ふう! 疲れました。私の英語力では、もういっぱいいっぱいです。熱いし!
あとは記事で読んでみてください。以下は、要約っぽいものを。

この後、記事では権限分離の話が続きます。例えば画像処理のような機能は、まとめて一つのプロセスとして、それをアプリが利用する形態を進めているそうです。サンドボックス、その共通プロセスのほうに行います。画像処理アプリは、そのプロセスのAPIを利用することで、セキュリティ上も、開発の上でも簡単に実装できることになると言う考えです。
すでに、この考えかたは、GoogleのChromeで行われているそうで、セキュリティの一つのトレンドとなっていると言って良いでしょう。

2011年8月13日土曜日

jarをつくってみる

scalaで作られたTwitter clientがあると言うので
http://www.moongift.jp/2011/07/20110722-3/
ソースコードの勉強のために、ダウンロードしてみた。興味があったのは、以下の点
1. scalaで作ったweb applicationやコマンドではなく、クライアントアプリだということ。クライアントアプリケーションは、そのGUIとかどうしているのだろうか。
2. Twitter APIを利用しているはずだが、具体的には?

開発者のサイトをみて、実際にアプリケーションをインストールして判ったのは、
https://github.com/kaizawa/kotsubu
Java Web Startで配布されていること。Java Web Startは、未だ試したことがないので、これはいつか調べることにして、まずは jarファイルの作成までをやってみた。

Sakura VPSで作業をおこなったので、java関連のパッケージをインストール。
Jakarata Antをインストール。antは、yumからだと1.6系がインストールされてしまうので、これはApacheサイトからバイナリをダウンロード。
 $ yum -y install java-1.6.0-openjdk java-1.6.0-openjdk-devel java-1.6.0-openjava-javadoc
 $ cd /usr/src/
 $ wget http://archive.apache.org/dist/ant/binaries/apache-ant-1.8.2-bin.tar.bz2
 $ tar jxvf apache-ant-1.8.2-bin.tar.bz2
 $ mv apache-ant-1.8.2 /usr/local/ant

/etc/profile にPath情報を追加。
(どうも、以前 scalaをインストールしたとき、既にJava実行環境がはいっていたようだ。)
 export JAVA_HOME=/usr/java/default
 export ANT_HOME=/usr/local/ant                      # 追加
 export PATH=$PATH:$JAVA_HOME/bin:$ANT_HOME/bin      # $ANT_HOME/bin 追加
 export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar

ダウンロードしたTwitterクライアントのソースには、Twitter用のライブラリがはいっていない。
必要なTwitter4j(Twitter APIのJavaラッパー)を以下からダウンロード。
http://twitter4j.org/ja/index.html
どこにライブラリファイルを置いて良いのか判らないので、とりあえず build.xmlファイルと同じディレクトリにおいてみた。

 $ wget http://twitter4j.org/en/twitter4j-2.2.4.zip
 $ unzip twitter4j-2.2.4.zip
 $ mkdir twitter4j
 $ mv twitter4j-2.2.4.zip twitter4j
 $ cd twitter4j/
 $ unzip twitter4j-2.2.4.zip
 $ cp lib/twitter4j-core-2.2.4.jar ../kaizawa-kotsubu-7b37fd7/
 $ cd ../kaizawa-kotsubu-7b37fd7
 $ ant

javadocパートでコンパイルエラーがでた。jar本体は出来たようす。
 $ ls -l dist/
 合計 272
 -rw-rw-r-- 1 baker baker 268597  8月 10 17:46 kotsubu.jar
 drwxrwxr-x 2 baker baker   4096  8月 10 17:46 scaladoc  # なかは空っぽ

面倒くさいので、build.xml の パートのjavadocの部分を削除して再度、ant

# 変更前のbuild.xmlの一部
< target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>

# 変更後
< target depends="test,jar" description="Build and test whole project." name="default"/>

# ant コマンド発行の結果
-do-jar-with-manifest:
-do-jar-without-manifest:
-do-jar-with-mainclass:
     [echo] To run this application from the command line without Ant, try:
     [echo] java -cp "/home/baker/work/kaizawa-kotsubu-7b37fd7/dist/kotsubu.jar" kotsubu.Main
     [echo]                 
-do-jar-with-libraries:
-post-jar:
jar:
default:
BUILD SUCCESSFUL
Total time: 8 seconds

とりあえず、ここまで。
 $ ls -l dist/
 合計 272
 -rw-rw-r-- 1 baker baker 268597  8月 10 17:46 kotsubu.jar
 drwxrwxr-x 2 baker baker   4096  8月 10 17:46 scaladoc  # なかは空っぽ

2011年8月2日火曜日

Titunium 新規プロジェクト始動

Titanium Studio 悪戦苦闘

いくつかチュートリアルをこなしたが、Titunium Studioは使いにくい。コード補完機能は日頃使っていなかったので、とても新鮮なのだが。
以下、気になったところ
  • コンパイルに時間がかかりすぎると、sessionが切れる。
  • 過去のコンパイル情報と矛盾した場合、エラーになる。
  • 再度、コンパイル & 実行すると上手くいく。
  • subverion pluginは使いにくい。
  • プロジェクトの削除の方法が不明だった。

Subversionの利用

新規プロジェクトを始める。ソース管理は、やっぱりsubversionを使うことにしたが、subversionもコマンドラインで使っていたので、Titunium Studioでの利用に随分と迷う。いろいろ試行錯誤したが、結果以下の手順にした。ある程度ソースが出来、SVN Pluginのインストールの後、
  1. [clean ..] する。 build ディレクトリを空にする。(iphoneディレクトリも無くす)
  2. command line で、import する。
  3. command line で、export する。
  4. buildフォルダの属性をignoreにする。
  5. 元のプロジェクトのIDを変更する(import時にIDで同じかを判断しているらしい)。
  6. 別のプロジェクトでimportする。
  7. 元のプロジェクトは削除する。menuから。
なかなか、スタートアップが上手くいかないねえ。

subversionプラグインのインストールは、以下を参照。
http://wiki.appcelerator.org/display/tis/Subversion

$ cd /project/dir/
 $ svn import . -m "iPhone Titanium mobile app" http://xxx/svn/trunk/app 
 $ cd ..
 $ mv app _app
 $ svn co http://xxx/svn/trunk/app
 $ cd app
 $ svn propset svn:ignore "*" build/
 $ svn commit -m "set propset svn:ignore build/*"

最初のコード app.js

さて、今日のTitaniumの勉強は、棚卸業務プログラムの手始めとして、TabGroupの制御などを学習。

Resorces/app.jsは、アプリケーションの起動ファイル。このソースが最初に処理される。
ここでは、タブグループのセットと、他のviewとのつながりを記述することにした。

Titanium.UI.setBackgroundColor('#000'); //背景をセット
var tabGroup = Ti.UI.createTabGroup();   //タググループセット

// [tab_scan]タブの生成。 [win_scan]ウインドウを所有する。
// 起動の初期画面。バーコードスキャンなど主業務を行う画面となる予定。
var win_scan = Ti.UI.createWindow({
 url: 'win_scan.js',             // win_scanが記載されるソースファイル
 title: 'SCAN',                 // cssに準拠しているらしい
 backgroundColor:'#fff'
});

var tab_scan = Ti.UI.createTab({    // 
 window: win_scan,
 icon:'KS_nav_ui.png',
 title:'scan'
});

// タブ [list_tab]
// スキャンしたコードを保管し、その一覧を表示する予定。
var win_list = Ti.UI.createWindow({
 url: 'win_list.js',
 title: 'LIST',
 backgroundColor:'#fff'
});

var tab_list = Ti.UI.createTab({
 window: win_list,
 icon:'KS_nav_ui.png',
 title:'list'
});
tab_list.setBadge(52); // バッチ表示を試してみた。

// タブ [tab_config]
// 各種設定を行う画面の予定。
var win_config = Ti.UI.createWindow({
 url: 'win_config.js',
 title: 'CONFIG',
 backgroundColor:'#fff'
});

var tab_config = Ti.UI.createTab({
 window: win_config,
 icon:'KS_nav_ui.png',
 title:'config'
})

// タブグループへの各タブの追加とスタート。
// 初期は、tabs[0] になるらしい。addTabは、配列への追加イメージか。
tabGroup.addTab(tab_scan);
tabGroup.addTab(tab_list);
tabGroup.addTab(tab_config);
tabGroup.open();

win_scan.js

ボタンの追加とボタンクリックの時のイベントリスナー処理を試してみた。

// このファイルが呼ばれた時点で "current"
var win = Ti.UI.currentWindow; // currentWindowは(appの)プロパティ。

var label = Ti.UI.createLabel({
 color:'#999',
 text:'this is scan windows.',
 font:{fontSize:20,fontFamily:'Helvetica Neue'}, // フォントは設定がこれ?
 textAlign:'center',
 top:10,
 height:30 // 指定しないと autoになり、windowいっぱいの縦幅になる。
});
win.add(label);

var scanButton = Ti.UI.createButton({
 title:'Scan It',
 top:80,
 left:10,
 width:300,
 height:100
});
win.add(scanButton);

var sendButton = Ti.UI.createButton({
 title:'Send Data',
 top:200,
 left:10,
 width:300,
 height:100
});
win.add(sendButton);

// ボタン[scanButton]がクリックされた場合のイベントを記載。
// イベントの実際は、無名関数 function() で実装。
scanButton.addEventListener('click', function(){
 Ti.UI.createAlertDialog({
  title: 'SCAN ...',
  message: 'scan complete !'
 }).show(); // オブジェクトを生成し、すぐ表示。イベント発生時になる。
});

イベントリスナーのテストをしたところ!