2013年10月31日木曜日

モバイルアプリ向けにRESTfulなJSON APIを設計するために

rest-api_mobile-appTitanium Mobileを使ってWordPressと連携できるiOSアプリ、Androidアプリを作った。

アプリからのリクエストはWordPress(PHP)で処理しているので、Web版のメソッドを流用出来て開発は比較的楽だった。

しかし、こんな独自仕様のAPIではなく、そもそもアプリのバックエンド(WebAPI)はどうあるべきか調べてみた。

参考サイト

REST APIが主流らしい。

上記サイトからダウンロードできる無料のPDFにWeb APIを設計するための指針がまとめられていて分かりやすい。

 

WordPress.comではREST APIを開発者向けに公開しているので、URIを決めるときの参考になる。

 

さらにサーバー側はNode.jsで構築すればPHPの50倍速くなるらしい。

JavaScriptだけでクライアント側(Titanium Mobile)とサーバー側が開発出来るのは嬉しい。

ただし、WordPressが提供している便利関数が使えなくなるのでテスト工数は増えそう。

 

少ない「人」と「お金」と「時間」で開発するためにはこういった技術を活用することがますます重要になりそう。

 

< Related Posts >

2013年10月24日木曜日

[Subversion]日本語ファイル名をコミットするとエラー

subversion_commit_error日本語を含む名前のファイルをTortoiseSVNでコミットしようとするとエラーになったときの覚書。

環境: Amazon Linux AMI release 2013.09, Subversion Server 1.7.13, TortoiseSVN 1.8.2

SubversionはYUM経由でインストール。

それまでは日本語でもコミット出来ていた。たぶんサーバー側でyum updateしてSubversionのバージョンが上がったからだと思う。

TortoiseSVNのエラー

Command: Commit
Modified: C:\Users\daiki\Documents\Projects\hoge\Documents\99.Etc\アンケート.xls
Sending content: C:\Users\daiki\Documents\Projects\hoge\Documents\99.Etc\アンケート.xls
Error: Commit failed (details follow):
Error: File
Error:  'C:\Users\daiki\Documents\Projects\hoge\Documents\99.Etc\アンケート.xls'
Error:  is out of date
Error: File not found: transaction '668-jc', path
Error:  '/trunk/documents/99.Etc/%A2%E3%83%B3%E3%82%B1%E3%83%BC%E3%83%88.xls'
Error: You have to update your working copy first.
Completed!:

 

サーバー側のエラーログ
# tail -f /var/log/httpd/error_log

[Wed Oct 23 08:24:04 2013] [error] [client 61.205.209.20] Could not fetch resource information.  [404, #0]
[Wed Oct 23 08:24:04 2013] [error] [client 61.205.209.20] Could not get created rev of resource  [404, #160013]
[Wed Oct 23 08:24:04 2013] [error] [client 61.205.209.20] File not found: transaction '673-jt', path '/trunk/documents/99.Etc/%A2%E3%83%B3%E3%82%B1%E3%83%BC%E3%83%88.xls'  [404, #160013]

 

もちろんアップデートやクリーンアップしても変わらず。

 

サーバーの設定を見なおして、なぜかSVNAdvertiseV2ProtocolをOnにしたら直った。

# less /etc/httpd/conf.d/subversion.conf

<Location /repos>
   DAV svn
   SVNParentPath /home/svn/Repositories

   SVNAdvertiseV2Protocol On

   RewriteEngine off

   AuthType Basic
   AuthName "Authorization Realm"
   AuthUserFile /home/svn/.htpasswd

   # Limit write permission to list of valid users.
   <LimitExcept GET PROPFIND OPTIONS REPORT>
      Require valid-user
   </LimitExcept>
</Location>

 

< 2014/02/21 Modified >
Subversionを1.7.14にアップデートしたら今度は(日本語とか関係なく)コミット出来なくなった。

Error: Commit failed (details follow):
Error: POST of '/repos/hoge/!svn/me': 404  (http://hoge.net)

なぜか「SVNAdvertiseV2Protocol Off」にしたら直った。

何なんだ。

 

< Related Posts >

2013年10月23日水曜日

Google Play, App Storeのアプリ画面を起動するQRコードを生成

qr-code_for_appチラシを作成する際にQRコードを貼り付けて、読み込むとAndroidアプリ、iPhoneアプリをダウンロードできるアプリストアを表示するようにしたくて調査したときの覚書。

ちなみにQRコードを読み取るアプリをダウンロードしてスキャンするぐらいならアプリストアでキーワード検索した方が早い。。。

 

URIスキーム(URLスキーム)の仕組みを使うと起動するアプリをある程度制御することができる。

 

Google Playの「teniteo」アプリを起動する場合

market://details?id=jp.teniteo.app

 

App Storeの「teniteo」アプリを起動する場合

itms-apps://itunes.apple.com/jp/app/teniteo/id619969170

 

これのQRコードを生成する。下記サイトで無料で作れる。サイズも指定出来て便利。

 

ちなみにこの記事に付けている画像が実際に生成したQRコード。

 

チラシに必要な「Google Play」と「App Store」のロゴのベクトル画像は下記から手に入る。

 

 

< Related Posts >

2013年10月21日月曜日

Windows8からMacの共有フォルダへのアクセスが切断されたりする

windows_share_folder_mac会社の開発環境では、Mac miniがメインサーバーになっていて、WindowsからMacの共有フォルダにアクセスしてTitanium Mobileの開発したり、VMware Fusion上でLinuxを動かしていたりする。

WindowsからMacの共有フォルダ(SMB/CIFS)にアクセスして、TortoiseSVNでコミット作業しているとたまに途中で失敗することがあったので、イラっときて調べたときの覚書。

環境: Windows 8 64bit, OS X 10.8.5

IPv6が悪さすることがあるらしい。

書いてある通り
System Preferences → Network → Advanced ... → Configure IPv5
を「Link-local only」にするとコミットに失敗することがなくなった。

 

さらに下記記事を読んでSMB/CIFSを理解すると問題の切り分けが出来そうな気がする。

 

< Related Posts >

2013年10月18日金曜日

nginx + php-fpmの環境で処理が途中で止まる

php-fpm_errorサーバーから外部API経由でデータを取得している処理でたまに途中で失敗していたので調べてみた。

環境: CentOS 5.9 x86_64, nginx 1.4.3, php-fpm 5.4.20

エラーログを見てみると

# tail -f /var/log/nginx/error.log

2013/10/17 20:03:36 [error] 5377#0: *3392 readv() failed (104: Connection reset by peer) while reading upstream

# tail -f /var/log/php-fpm/error.log

[17-Oct-2013 20:04:31] WARNING: [pool www] child 10965 exited on signal 11 (SIGSEGV) after 30946.471106 seconds from start
[17-Oct-2013 20:04:31] NOTICE: [pool www] child 13670 started

php-fpmのrequest_terminate_timeoutを設定すると直るという情報があったので設定してみる。

# vi /etc/php-fpm.d/www.conf

request_terminate_timeout = 30s

# /etc/rc.d/init.d/php-fpm restart

 

 

< Related Posts >

2013年10月17日木曜日

Google Apps Scriptで自動的にGmailのメールを定期的に削除

gmail_timerメールマガジンなどはGmailのフィルター機能を使ってラベル付け+アーカイブしているけど、キーワード検索するとヒットしてウザいので定期的に削除することにした。

参考にしたサイトはこちら。

 

手順

  1. Google Apps Scriptにアクセスして「空のプロジェクト」を作成
  2. メールを検索して削除するスクリプトをJavaScriptで記述
  3. 「現在のプロジェクトのトリガー」で実行間隔を設定

上記サイトのスクリプトを参考に、複数のラベルを対象とするように変更したのがこれ。

「filters」に設定する値はGmail上でラベルをクリックしたときに検索バー表示される値そのまま。

試すときは「ゴミ箱」を空にして、「max」の値を5ぐらいで動作確認した方がいい。

もっと簡単設定できるようにUIを付けたウェブアプリケーションも作れるような気がする。

 

< Related Posts >

2013年10月15日火曜日

[Titanium Mobile]TabGroupのTop LevelでAndroidのMenuを表示

android_menuTitanium SDK 3.1.3.GAに上げたらAndroidのメニューが表示されなくなったので調査したときの覚書。

環境: Titanium SDK 3.1.3.GA

TabGroupの各タブのトップだけ表示されず、下の階層へ画面遷移すれば普通にメニューが表示される。

今までは共通関数で、

win = Titanium.UI.createWindow();
win.activity.onCreateOptionsMenu = function(e) {
    e.menu.add({title: L('menu1')});
});

とやっていた。

どうやらTabGroup直下のwndowにはactivity(≒画面)がないらしい。

Titaniumではactivityを持っているwindowを「heavyweight」windowと呼んでいて、「heavyweight」なwindowを作成するかどうかを条件に応じて判断している。詳しくは下記。

 

TabGroup直下の場合はTabGroupのActivityでonCreateOptionsMenuする必要があるみたい。

tabGroup = Titanium.UI.createTabGroup();
tabGroup.activity.onCreateOptionsMenu = function(e) {
    e.menu.add({title: L('menu1')});
});

 

< Related Posts >

2013年10月11日金曜日

[Titanium Mobile]HTTPClientのSession(Cookie)をAndroidのWebViewに引き継ぐ

httpclient_sync_webviewWordPressとやり取りするアプリをTitanium Mobileで開発しているときに、HTTPClientでログインしておいたのにWebViewを使うとセッションが引き継がれないので調査したときの覚書。

表示するだけならHTTPClientでGETして、WebViewのhtmlに流し込んだ方が簡単。

問い合わせフォームなど入力してPOSTするページはWebViewのurl指定で表示させたい。

Androidのみ。iOSは何もしなくても引き継がれる。

参考になったサイト。

環境: Titanium SDK 3.1.3.GA, WordPress 3.6.1

 

まずは、HTTPClientしたときのCookieを覚えておく

xhr = Titanium.Network.createHTTPClient();

xhr.onload = function() {
    // Save cookie for Android WebView
    if (this.getResponseHeader('set-cookie')) {
        self.cookie = this.getResponseHeader('set-cookie');
    }
}

 

その後、WebViewを使用するときにevalJSを使ってCookieをセットする

view = Titanium.UI.createWebView();
view.addEventListener('beforeload', function() {
    cookie = self.cookie.split(/,\s(?=\w+=)/g);
    cookie.forEach(function(item) {
        item.split('; ').forEach(function(data) {
            view.evalJS('document.cookie="' + data + '";');
        });
    });
});

これでcookieは設定できるけど、実際は下記のことをしなければ引き継げなかった。今後のバージョンアップで直っているかも。

  • cookieをセットする前にdocument.cookieがなかったら強制的にreloadする。
  • Aタグなどクリックした先でまた引き継げなかったので(Android 4.0.3)、セットしたときのURLと現在のURL(location.href, location.pathname)を比較して、違っていたらsetUrlする。

確認したのは、Android 2.3.3, Android 4.0.3

WebView内のCookieをリセットするにはアプリケーション管理の「データ消去」をする。

Titanium SDKのバージョンが上がるたびに動作確認しないとダメそう。

 

 

< Related Posts >

2013年10月10日木曜日

Subversion 1.8系をCentOSにInstall (YUM経由)

subversion_installSubversionのクライアント環境だけCentOSに追加したときの覚書。

環境: CentOS 5.9, Subversion 1.8.3

Subversionのサービスを提供しているWANdiscoがインストール用のシェルスクリプトを配布しているのでそれを利用する。

ダウンロードするために登録が必要。

YUMで配布してくれるなら、これくらいはお安い御用。

登録したメールアドレスにリンクが送られてくるので、それをクリックしてダウンロード。

あとはサーバーに置いて実行する。

# chmod 655 ./svn1.8_rhel5_wandisco.sh
# ./svn1.8_rhel5_wandisco.sh

Subversionのクライアントとして使うのでapacheのSVNモジュールはインストールしない。

チェックアウトしてみる。
# svn checkout http://dev.hoge.net/project/branches/demo demo/ --username hoge

ちなみにサーバーはSubversion 1.7.9

コマンドは忘れるものなのでヘルプで確認
# svn help

 

< Related Posts >

2013年10月4日金曜日

LESSファイルを監視してCSSファイルに自動コンパイルする環境を構築

less_to_cssCSSフレームワークの「Bootstrap」をベースにして、CSSを動的に生成する言語「less」の環境を構築したときの覚書。

環境: CentOS 5.9 x86_64, Node.js v0.10.20, Grunt 0.4.1

サーバー側でlessファイルからcssファイルにコンパイルするためにはnode.jsの環境が必要。node.jsはnvm (Node Version Manager) 経由でインストールする。

gitが必須らしい
# yum install git

nvmをインストール
# wget -qO- https://raw.github.com/creationix/nvm/master/install.sh | sh

ここで一旦ログアウト&ログイン

nodejsをインストール
# nvm install v0.10.20

デフォルトでv0.10.20を使うようにする
# nvm alias default 0.10.20

lessファイルをcssファイルにコンパイルするソフトをインストール
# npm install -g less

 

試してみる
# cd /home/projects/hoge/
# lessc less/hoge.less css/hoge.css

 

次はlessファイルを監視して、保存と同時にcssファイルにコンパイルする環境を作る。

参考にしたサイト

手順

  1. タスク管理ツール「Grunt」をインストール
  2. LESSをCSSにコンパイルするGruntプラグイン「grunt-contrib-less」をインストール
  3. ファイルを監視して更新を検知するGruntプラグイン「grunt-contrib-watch」をインストール

 

Gruntのコマンドラインツールをインストール
# npm install -g grunt-cli

Grunt本体とプラグインをインストール
# cd /home/projects/hoge/
# npm install grunt --save-dev
# npm install grunt-contrib-less --save-dev
# npm install grunt-contrib-watch --save-dev

save-devオプションは開発に必要な依存関係をpackage.jsonに書き出してくれる。Gruntのプラグインをインストールするときは付けておいた方がいいらしい。

まずはgrunt-contrib-lessだけで試してみる
# vi Gruntfile.js

module.exports = function(grunt){
    // Load plugins
    grunt.loadNpmTasks("grunt-contrib-less");

    grunt.initConfig({
        less : {
            dist : {
                options : {
                    compress : true
                },
                files : {
                     "path/to/result.css": "path/to/source.less"
                }
            }
        }
    });
};

実行
# grunt less:dist

ファイル監視用の設定を追記する
# vi Gruntfile.js

module.exports = function(grunt){
    // Load plugins
    grunt.loadNpmTasks("grunt-contrib-less");
    grunt.loadNpmTasks("grunt-contrib-watch");

    grunt.initConfig({
        less : {
            dist : {
                options : {
                    compress : true
                },
                files : {
                     "path/to/result.css": "path/to/source.less"
                }
            }
        },
        watch : {
            less : {
                files : ["path/to/*.less"],
                tasks : ["less:dist"]
            }
        }
    });
};

実行
# grunt watch:less

フォルダ内のlessファイルを全てcssファイルに変換したいので、最終的にはこれ

module.exports = function(grunt){
    // Load plugins
    grunt.loadNpmTasks("grunt-contrib-less");
    grunt.loadNpmTasks("grunt-contrib-watch");

    grunt.initConfig({
        less : {
            dist : {
                options : {
                    compress : true
                },
                files : [{
                    expand: true,
                    cwd: '/pass/to/less',
                    src: ['*.less'],
                    dest: '/pass/to/css',
                    ext: '.css'
                }]
            }
        },
        watch : {
            less : {
                files : ['/pass/to/less/*'],
                tasks : ['less:dist']
            }
        }
    });
};

 

 

< Related Posts >

Related Posts Plugin for WordPress, Blogger...

Blog Archives