2013年12月26日木曜日

MacをMavericksにしたらTortoiseSVNのコミットが失敗する

windows8_mac_tortoisesvnTitaniumもMavericksをサポートするようになったので、開発サーバーになっているMac miniをMavericksにアップグレードしてみたときの覚書。

環境: OS X Mavericks 10.9.1, Windows 8.1, TortoiseSVN 10.8.4

WindowsからMacの共有フォルダにあるソースをTortoiseSVNでコミットしようとすると下記エラー

Error: Commit failed (details follow): 
Error: Can't move 
Error:  '\\hoge\hogehoge\.svn\tmp\svn-CF8BDE60' 
Error:  to 
Error:  '\\hoge\hogehoge\.svn\pristine\3a\3abd0eabfa1e58f83cfcce2403a3dc22dcb7ad79.svn-base': 
Error:  パラメーターが間違っています。 

 

Macのログには下記エラー

$ less /var/log/system.log

Dec 25 11:21:11 local smbd[184]: File system does not support 0X0, size attrs
Dec 25 11:21:11 local smbd[184]: File system does not support 0X40000, file attrs
Dec 25 11:21:11 local smbd[184]: File system does not support 0X0 time attrs

 

フォーラムにも上がっていてまだ直ってないらしい。

SMB1のみに切り替えると出来るという情報があるが私の環境では成功しなかった。

しょうがないので、しばらくはSSH経由でsvn commitすることにした(一度別フォルダに退避して、svn checkoutしてから上書きする)。

MacのSubversionを1.8に挙げないとTortoiseSVNでログを確認できないのが不便。

Appleさん、早く直してください。

 

< Related Posts >

2013年12月18日水曜日

Node.js + Expressの環境でファイルをアップロードする処理

nodejs_upload-fileTitaniumで開発しているアプリからファイルをアップロードして保存する処理を開発していたときの覚書。

環境:node.js v0.10.22, express v3.4.6, busboy v0.0.12

よく見かけるのは

app.use(express.bodyParser());

としてreq.filesを参照する方法。しかし、これを記述すると下記エラーをnodejsが出力する。

connect.multipart() will be removed in connect 3.0
visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
connect.limit() will be removed in connect 3.0

リンク先を見ると、ディスクにファイルを保存するのはセキュリティ上の問題から非推奨となり、他のパーサーを使えとある。

multipartybusboyを試した結果、難易度は上がるけどbusboyを使ってストリーム形式で処理することにした。

理由は

busboyはアップロードするファイルサイズを制限できる

から。

ちなみにmultipartyはTitaniumからアップロードしたcontent-typeに対応してない(multiparty3.1.0で確認)。こちらのissue#29にあるように正規表現を直せば対応可能。

サンプルコードはGitHubのReadmetestを見れば何となく分かると思う。

 

実際に使ってみた注意点をいくつか(※v0.0.12)

  • アップロードしたファイル名が日本語だとfilenameが化ける。issue#20に上がってる
    → filenameを使わない実装を推奨
    → ちなみにmultipartyは大丈夫
    → v0.0.13で修正されたらしい。試してない。 
  • busboy.on('file')の中でfileに対して操作をしないとbusboy.on('end')が発生しない。このissue#16で説明してる。
  • ファイルサイズの制限に引っかかったら「limit」イベントが発生するので、書き込み中のファイルは自前で削除する必要がある。

 

< Related Posts >

2013年12月17日火曜日

node.jsでImageMagick + gmをインストールして画像処理

nodejs_imagemagickNode.jsで画像処理(Resize, Crop)をする方法を調べたときの覚書。

環境: CentOS 5.10, node.js v0.10.21

GraphicsMagickもしくはImageMagickをnode.jsから利用できるモジュール「gm」が良さそうなのでインストールしてみた。

 

< 2014/08/21 Modified >
CentOS6.5の環境ではYUM経由でImageMagick 6.5.4-7がインストールされて問題なかったので、こっちを推奨。

 

まずはImageMagickでJPEGとPNGをサポートするようにライブラリをインストール
# yum install libjpeg libjpeg-devel libpng libpng-devel

何となくJPEG 2000にも対応しておく
# yum install jasper-devel

ImageMagickをソースからコンパイル(yum経由は古いから)
# cd /opt/software/
# wget http://www.imagemagick.org/download/ImageMagick.tar.gz
# tar xzvf ImageMagick.tar.gz
# cd ImageMagick-6.8.6-4/
# ./configure
# make
# make install

バージョンの確認
# convert --version

対応しているフォーマット一覧
# convert -list format

 

今度はgmのインストール
# cd /home/project/hoge/
# npm install gm

 

ImageMagickを使う場合は次のようになる。

var gm = require('gm').subClass({ imageMagick: true });
gm("img.png").resize(150, 150).write('/path', callback);

 

 

< Related Posts >

2013年12月13日金曜日

REST APIのテストする開発ツール Google Chrome「Postman」

restapi_chrome_firefoxiPhone, Androidアプリ向けにRest APIなWebサービスを開発している時にアプリを起動せず簡単にテストするツールを探したときの覚書。

参考

 


Google Chrome拡張機能「Postman - REST Client

多機能でサクサク動くので使いやすい。

履歴機能など必要なものは揃っていて、ソースコードも公開されているので素敵すぎる。

image

 


Firefoxアドオン「Poster

Postman - REST Client」があればいらない。

インストール後は右下の「P」かツールから起動する。

image

「Headers」は任意の値を設定するときに使う。

「Parameters」を登録しておけば「Body from Parameters」で値を生成してくれるので便利。

 

 

< Related Posts >

2013年12月12日木曜日

Titaniumを使ったアプリと苦労した事とかのまとめ2013年

teniteo_titaniumTitanium™ Advent Calendar 2013の12日目です。

今年の仕事はTitanium Mobileを使ったアプリ開発の1年でした。今回は開発したアプリの紹介と経験をまとめてみました。

開発したアプリがこれ。

 

このアプリの特徴

 

苦労したこと

 

運用してみて分かったこと

  • サーバー側の応答が遅いと「もっさり感」が3倍増する
  • アプリを使って投稿までしてくれる人のほとんどはiPhoneユーザー

 

まとめとバージョン2に向けて

今までのノウハウを結集してバージョン2を開発中。サーバー側はnode.jsを利用して、アプリはYouTubeアプリみたいな感じにする予定。

Titanium + WordPress + node.jsでマルチプラットフォームなサービスを少人数かつ短期間で構築できる手応えを感じてるので、WordPressとJavaScriptに自信があるWebエンジニアの次のステップとしてTitaniumとnode.jsをオススメしたい。

 

< Related Posts >

2013年12月2日月曜日

Google Play BooksへPDF形式を登録・出版(電子書籍化)

teniteo-mini愛知県中心に発行しているフリーペーパー「teniteo」の東京版「teniteo mini」を無事出版できた。

iPhone, Android向けのteniteoアプリも利用者が増えてきたので、以前から要望のある「フリーペーパー自体をスマフォで見れるようにしたい」というのをGoogle Play Booksでどの程度実現できるか試してみた。

詳しくは公式ヘルプで。

利用登録後、ブックスパートナーで設定できる配信先は2つ。

Google Play
→ 主にスマフォ向け
「Playストア」で検索でき、購入後Androidの「Playブックス」で読める。
Googleアカウントで紐付いていて、いろんなプラットフォームで読む方法が提供されている(Web, Android, iOS)
Google ブックス
→ 主にPC向け
Googleの書籍検索から検索・プレビューが出来るようになる。
プレビュー出来る範囲を指定可能。
Flash版のデジタルブックと比べて、本のような動きは出来ないけど問題なく読める。
Googleの検索に引っかかるようになるのは大きい。

40ページ(46MB)のPDFファイルをアップロードして処理完了するまで、約1時間かかった。

ページごとのPDFをアップロードすることも可能。その際はファイル名をガイドラインに従う必要がある。

 

結局2時間経ってもGoogle Play、Google ブックスに表示されなかったので、次の日(約22時間後)確認したら表示されてた。

 

でも「要対応」に次のエラーが表示されていて、Google Playから購入できない(価格は「無料」に設定)。

この書籍は次の理由で掲載されていません:

  • 価格情報がないか、適切ではありません

 

「Google Playの設定」から価格のところで国コードを入力する箇所に「WORLD」としていたのが原因みたい。「JP」に変更してしばらくしたら無料でダウンロードできるようになっていた。

最初原因が分からずペイメントセンターも登録したのでこちらも必要かもしれない。

 

< 2014/07/04 Modified >
日本語名のPDFをアップロードすると24時間以上経っても「処理中」のままだったので注意。英字のみにアップロードし直すと数時間で公開された。

 

< Related Posts >

2013年11月21日木曜日

nodejsからPHPを実行してWordPressのユーザー認証

nodejs_wordpress-usernodejsを使ってiPhone, Androidアプリ用のRest APIを開発する際に、WordPressのデータベースを使ったユーザー認証をしたかったので調査。

環境: CentoOS 5.10, node.js 0.10.21, php 5.4.21

最初はPHPでやっていることをJavaScriptで再現しようとしたけど、ソースコードを読んで無理そうだと諦めた。

なので、nodejsからPHPを外部コマンドとして呼び出して返り値を受け取ることにした。

nodejsから外部コマンドを実行するのは"child_process"を使うらしい。

 

nodejsから実行するPHPファイル。

wp_checkpassword.php

<?php
/**
* WordPress Check Password for CommandLine
*
* @usage
*   # php wp_checkpassword.php --hash="hash" --password="password" --path="/path/to/wordpress"
*/

$options = getopt(null, array('hash:', 'password:', 'path:'));

//
// Validation
//
if (empty($options['hash']) ||
    empty($options['password']) ||
    empty($options['path'])) {
  exit('option error');
}


//
// @see wp-includes/pluggable.php line:1448
//
$check = false;
require_once($options['path'] . 'wp-includes/class-phpass.php');
// By default, use the portable hash from phpass
if ($wp_hasher = new PasswordHash(8, true)) {
  $check = $wp_hasher->CheckPassword($options['password'], $options['hash']);
}

echo json_encode($check);
?>

 

このPHPファイルを呼び出す側。

var command = [];
var process = require('child_process');
// Get the Password Hash from Database.
var user_pass = '$P$BpIMHINnR/9y.e90cMuY3Af0eIWZ6Z1';

command.push('php');
command.push('php/wp_checkpassword.php');
command.push('--hash="' + user_pass.replace(/\$/g, '\\$') + '"');
command.push('--password="' + pass + '"');
command.push('--path="' + config.wordpress.path + '"');

process.exec(command.join(' '), function (err, stdout, stderr) {
  stdout = JSON.parse(stdout);
  if (stdout) {
    console.log('Login Success!');
  }
});

「user_pass」はPOSTされたユーザーID(メールアドレス)からSQLを実行してwp_users.user_passを取得してくる必要あり。

取得したハッシュ値はそのままだと「$」の部分をLinuxのシェルが解釈してしまうのでエスケープする。

 

< 2014/01/07 Modified >
送信するパラメータをシングルクォーテーションで囲めば「$」をエスケープする必要はない。

command.push('--password=\'' + pass + '\'');

JSON.stringifyした値も渡せるので、こっちの方が良さそう。

 

応用すればWordPressの便利関数を使える。

新規ユーザー登録や新規投稿などはWordPressにパイプした方が楽かもしれない。でも値の受け渡し方法を考えないといけないか。。。

 

 

< Related Posts >

2013年11月12日火曜日

[Titanium Mobile]Performance改善のためApplicationの設計を見直す

performance_upAndroid, iPhoneアプリが一段落したので、次期開発に向けてアプリの設計とより良いパファーマンスを得られる書き方など調べ直したときの覚書。

環境:Titanium SDK 3.1.3.GA

まず公式ドキュメント

アプリのサンプルも公開されてた。

でもこれ2年間更新されてない(SDK v1.8.1)ので、abcsWriterの方がいいかも。

両方とも「名前付き関数(named function)」を多用しているので無名関数(nameless function, anonymous function)とどっちがいいか調査。

名前付き関数の方が速いらしい。

var hogeFunc = function() {};

このような無名関数を基本使っていたのでショック。今後は名前付きにしよう。。。

 

< 2013/11/20 Modified >

ChariTiというアプリが非常に参考になる。

lib/core.js, lib/http.js, utilities.jsとかヨダレが出そうになるぐらい。別記事で詳細を紹介する予定。

 


去年のCODESTRONG(カンファレンス)のビデオを見てみた。

今後気をつけること。

  • setterを使うよりプロパティでアクセスした方が速い
  • "透明"はコストが掛かるので常に背景色を設定した方が速い

 

関連した記事も見つけた。これは実際やってみる。

 


公式ドキュメントからリンクされてたこちらの記事はTitanium Mobile(CommonJS)におけるオブジェクト指向の記述方法をサンプルで分かりやすく解説している良記事。

 

余力があるなら下記記事もチェック

 

 


作ったアプリでメモリリークがないかチェックする方法

限られた開発期間の中でもチェックできるような体制にしたい。

 

< Related Posts >

2013年11月8日金曜日

携帯(スマフォ)2台持ちなら激安SIM月額490円がお得

ktai_smartphone_charge最近激安SIMがあることを知ったので、契約して使ってみた。

参考サイト

契約したのはこちら。

概要

  • 初期費用:3150円
  • 月額:490円
  • ドコモ回線
  • 回線最大速度100kbps(ドコモのXiは最大150Mbps)
  • 転送量制限なし
  • 高速化するオプション有り
  • 1年縛り、2年縛りとかがないので気軽に試せる

 

切り替える前のドコモ料金はこちら。

ガラケー(F-01C) 基本使用料
(FOMAタイプSS_バリュー)
+1年割り
+ファミリー割引
924円
ガラケー(F-01C) パケ・ホーダイ ダブル定額料 372円
スマフォ(Galaxy S2) 基本使用料
(Xiデータプランフラットにねん)
3791円
スマフォ(Galaxy S2) SPモード 300円

 

これをガラケー+激安SIMにすると

ガラケー(F-01C) 基本使用料
(FOMAタイプSS_バリュー)
+2年割り
924円
スマフォ(Galaxy S2) ServersMan SIM LTE 100 490円

 

単純計算で毎月3973円安くなる。

 

100kbpsでも通勤途中は録画して転送した動画を見ているので問題なし。体感的には「ちょっと遅いかな?」という程度。電車の中の繋がりにくさは同じ。

今度利用者数が増えると遅くなりそうな予感。。。

「Xiデータプランフラットにねん」の解約金1万円を払っても変更した方が断然お得。ただ自分のスマフォが他社のSIMに変更出来るかは要確認。

「パケ・ホーダイ ダブル定額料」を解約すると「Xiデータプランフラットにねん」が正規料金になってしまうので、月末(3日前ぐらいからOK)にドコモショップで手続きする必要がある

 

< 2013/11/28 Modified >
ドコモショップに行ってきたら解約当月は必ず「Xiデータプランフラットにねん」の正規料金を請求されるので、月末に行こうが関係ない。

日割りに出来ないので、新しいSIMカードが届いたらすぐ解約しても大丈夫。値段は変わらないので月末まで持っててもいいかも。

前の担当者は研修生だったので対応があやふや。やっぱり慣れている人だとサクサク話が進むので早い。

 

ServersMan SIMカードは申し込んでから届くまでに1週間掛かった。

 

導入のタイミングが遅すぎたドコモメール(@docomo.ne.jp)も使わない。

 

< Related Posts >

2013年11月7日木曜日

nginx + node.js + pm2でアプリ向けのREST API環境を構築

nginx_nodejs_pm2前回の記事でWeb APIについて勉強し、モバイルアプリからのリクエストはNode.jsで捌くことにした。そのために環境を構築したときの覚書。

環境:CentOS 5.10, Node.js 0.10.21, nginx 1.4.3, pm2 0.6.5

 

< 2014/05/30 Modified >
CentOS6版も書いたのでそちらも参考に。

 


1.Node.jsをインストール

< 2013/12/09 Modified >
本番環境の場合は実行ユーザーで作成した方がいいので、この記事の最後の方を参照。

前の記事を参考にnvmでインストールする。

# nvm install v0.10.21
# nvm alias default 0.10.21

 


2.「Hello World」を作成

プロジェクトディレクトリに移動
# cd /home/project/

ExpressというNode.js向けのフレームワークをベースにする。

restifyというREST Webサービス用に特化したモジュールもあるけど、開発のスピードと下記ベンチマークを参考にExpressを選択。

expressjsの公式ドキュメント通りに「Hello World」を作る。
# vi package.json

{
  "name": "hello-world",
  "description": "hello world test app",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "3.x"
  }
}

# npm install

# vi app.js

var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('hello world');
});

app.listen(3000);

アプリ起動
# node app

別コンソールからアクセスして確認
# curl -i http://localhost:3000/

 


3.nginxを設定してブラウザから外部からアクセス

既にnginx + php-fpm + WordPressの環境があるので、リバースプロキシの設定をして外部から参照可能にする。

WordPressのサブディレクトリで動作させたかったので、ファイルが存在しなかったときのパーマリンクの動作を修正。

# vi /etc/nginx/conf.d/hoge.conf

server {
    listen       80;
    server_name  wordpress.hoge.net;

    ### Reverse Proxy for API
    location /api/ {
        rewrite ^/api/(.*)$ /$1 break;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:3000;
    }

    ### if the file is not found, forwarded to index.php (permalinks)
    set $rewrite_flg "false";
    if (!-e $request_filename) {
        set $rewrite_flg "true";
    }
    if ($uri ~ "^/api/") {
        set $rewrite_flg "false";
    }
    if ($rewrite_flg = "true") {
        rewrite ^/(.*)$ /index.php?q=$1 last;
    }
}

 

ブラウザからアクセスして確認
http://wordpress.hoge.net/api/

「hello world」が表示されるはず。

 


4.PM2をインストールしてnodeアプリをデーモン化

最後に常時起動させておくようにデーモン化する。

foreverよりpm2の方がクラスタリング(複数プロセスを使った負荷分散)も出来ておすすめらしい。

参考サイト

 

インストール
$ npm install -g pm2

すると下記エラー

gyp ERR! configure error
gyp ERR! stack Error: Python executable "python" is v2.4.3, which is not supported by gyp.
gyp ERR! stack You can pass the --python switch to point to Python >= v2.5.0 & < 3.0.0.

pythonのバージョンが古いらしい。メッセージにある通り「--python」オプションを利用してみる。

$ yum install python26
$ npm install -g pm2 --python=python26

起動する
$ pm2 start app.js -i max

Warningが出た。

PM2 [ERROR]  [Warning], you're using the 0.10.x node version, it's prefered that you switch to fork mode by adding the -x parameter.

node v0.10.xではstopしたときにポートを開放しないので、「fork mode」での動作がオススメらしい。詳しくは下記。

再起動
$ pm2 stop all
$ pm2 start app.js -x

動いているプロセスを表示
$ pm2 list

何が出来るかヘルプをみる
$ pm2 help

 

ファイルを監視して自動で再起動するのはまだ開発中ということなので、しばらくはnode-devを使って開発していた方がよさそう。

 

< 2013/12/09 Modified >
本番環境はrootで動かすと恐いのでnodejs実行用のユーザーを作成する。あとで権限の設定をするためにwwwというグループに所属させる。
# groupadd www
# useradd node -G www
# passwd node

所属グループの確認
# groups node

apacheユーザーの所属グループの変更
# usermod -G www apache

apacheユーザーだけが書き込み権限持っていた場所をwwwグループにも権限を与える
# chown apache.www -R /path/to/wordpress/wp-content/uploads
# chmod 775 -R /path/to/wordpress/wp-content/uploads

ユーザー切り替え
# su - node

ここからはnvmのインストールからやり直し。

ちなみにpm2は「-u」オプションで起動ユーザーを指定することができる。
$ pm2 -u apache start app.js -x

でもpm2で起動している場合「Permission denied」でファイルの書き込みに失敗する。node-devの場合は成功するのでまた今度調査。

 

< 2013/12/12 Modified >
nginx + php-fpmで動いている環境もuser=apche, group=wwwで動作するための設定を追記。(今まではuser=apche, group=apache)

php-fpmの設定
# vi /etc/php-fpm.d/www.conf

group = www

nginxの設定
# /etc/nginx/nginx.conf

user  apache www;

sessionの書き込みディレクトリの権限(/etc/php-fpm.d/www.confに記述)
# chown apache.www -R /var/lib/php/session/

※YUMでPHPが更新されたときに権限が変更されることがあったので注意。

phpMyAdminが下記エラーで起動しなくてハマった。

2013/12/12 18:44:47 [error] 3653#0: *188 readv() failed (104: Connection reset by peer) while reading upstream
2013/12/12 18:44:47 [error] 3653#0: *187 recv() failed (104: Connection reset by peer) while reading response header from upstream

念のためnginxのキャッシュディレクトリも権限を変更する
# chown apache.www -R /var/cache/nginx/*

 

< 2013/12/27 Modified >
接続元のIPアドレスを取得したかったので、X-Forwarded-Forの設定を追記。

 

 

< Related Posts >

2013年11月6日水曜日

iOSアプリをDistributeするときに120x120が必要になった

app-store_120x120iconTitanium Mobileで作成したアプリをストアに送信する「Validation」をしたときに下記エラーが出るようになった。

Missing recommended icon file - The bundle does not contain an app icon for iPhone / iPod Touch of exactly '120x120' pixels, in .png format.

120x120のアイコンが必要になったらしい。

環境: Titanium SDK 3.1.3.GA

参考にしたサイト。

 

上記サイトを参考に

  • Resources/iphone/appicon-60.png
  • Resources/iphone/appicon-60@2x.png

を用意したらValidationが通った。

 

< Related Posts >

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 >

2013年9月26日木曜日

猫のトイレ臭い対策でデオトイレを買ってみる

DSC00339普通の猫トイレを使っていたけど、1週間ほどで臭くなりだして、ニャンコも嫌がっている様子。

揃えた猫用品は前の記事を参照。猫2匹、5ヶ月のオスとメス

調べてみると重曹(ベーキングパウダー)を下に敷くと臭いが抑えられると聞いてやってみた。

確かに臭いが控えめになった気がする。。。けど、トイレが綺麗になるわけもなく、2週間で猫砂をまるっと替えているのが現状。

何とかならないものかと調べてみて、今度はシート交換式のデオトイレを買ってみた。

154521-1

おしっこの場合は下のシートが吸収してくれるので、掃除がかなり楽になる。

うんちは相変わらず臭い。こっちでうんちした場合はなぜか砂をかけてくれない。砂が大きいから?

前の猫トイレと両方おいておくと、前のトイレを優先的に使うみたい。猫砂の感じがお気に入りらしい。前の猫砂をデオトイレで使いたいが、砕けてシートの上に落ちてしまう。

総体的には買って良かった。

おしっこをデオトイレ、うんちを前の猫トイレでしてもらえると大変助かります。

 

< Related Posts >

2013年9月20日金曜日

[Titanium] iOSとAndroidで地図アプリ(Google Maps)を起動

map-app_from_titaniumアプリ内の地図と地図アプリを連携すると便利なので、パラメータを渡して起動する方法を調査。

環境: Titanium SDK 3.1.1.GA

参考にしたのは下記。

 

実際書いたコードを下記に抜粋。

iOSの場合はグーグルマップアプリがインストールしてあれば、そちらを優先して開く。
Androidの場合はおなじみのアプリを選択する。

緯度と経度をクエリとして渡した方がピンが立つので分かりやすい。

if (this.isAndroid) {
    // Google Map
    url = [];
    url.push('http://maps.google.com/maps');
    //url.push('?ll=' + this.region.latitude + ',' + this.region.longitude);
    url.push('?q=' + this.region.latitude + ',' + this.region.longitude);
    url.push('&z=16');
    Titanium.Platform.openURL(url.join(''));
    return true;
}

if (this.isIos) {
    // Google Map of Native App
    url = [];
    url.push('comgooglemaps://');
    //url.push('?center=' + this.region.latitude + ',' + this.region.longitude);
    url.push('?q=' + this.region.latitude + ',' + this.region.longitude);
    url.push('&zoom=16');
    if (Titanium.Platform.canOpenURL(url.join(''))) {
        Titanium.Platform.openURL(url.join(''));
        return true;
    }

    // Native App
    url = [];
    url.push('http://maps.apple.com/');
    //url.push('?ll=' + this.region.latitude + ',' + this.region.longitude);
    url.push('?q=' + this.region.latitude + ',' + this.region.longitude);
    url.push('&z=16');
    Titanium.Platform.openURL(url.join(''));
    return true;
}

 

< Related Posts >

2013年9月19日木曜日

[Titanium] Google Maps API v2用Androidモジュールを設定

google-maps-v2_titanium_android-moduleTitanium Mobileで作成したiOSアプリ、Androidアプリ内にGoogle Mapを表示して、店舗情報をプロット表示するために調査したときの覚書。

環境: Titanium SDK 3.1.1.GA

Titanium公式ドキュメントを読む。

iOSでは「Titanium.Map」
Androidでは「Modules.Map」というモジュール
を使うらしい。

iOS用にはKitchenSinkを参考にすれば難しくないと思う。ここからはAndroid用のモジュールを使えるようにするまでの手順。

 

Android用のモジュールに関する公式ドキュメントはこちら。

このモジュールはTitanium 3.1.0以上が必要なので注意。

 

簡単に手順をまとめると。

1.Google Play Services SDKをインストール

Android SDK Managerを起動して「Extras」 → 「Google Play services」をインストールする。

 

 

2.Google APIs Consoleに登録してAPI Keyを取得

Google APIs Consoleにアクセスして「Google Maps Android API v2」をONにする。

Google APIs Consoleの「API Access」 → 「Create new Android Key...」からアプリに埋め込まれているFingerPrintを入力

開発用のFingerPrintは下記コマンドで確認できる(パスワードはなし)。S
$ keytool -list -v -keystore ~/Library/Application\ Support/Titanium/mobilesdk/osx/3.1.1.GA/android/dev_keystore

すでにアプリを公開しているなら、keystoreファイルを作成しているはずなので、同じコマンドで確認できる。
$ keytool -list -v -keystore /path/to/keystore

詳しくは公式ドキュメントで。

複数行登録出来るようなので、開発用も同じAPI Keyにしてみた。FingerPrintとセミコロンのあとに入力するpackage nameはtiapp.xmlの「id」。

 

 

3.tiapp.xmlにAPI Keyとモジュールを設定

公式ドキュメントにあったのをそのまま貼り付け。ただGPS機能は使わないので除外。

<android>
    <manifest>
        <!-- Allows the API to download data from Google Map servers -->
        <uses-permission android:name="android.permission.INTERNET"/>
        <!-- Allows the API to cache data -->
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
        <!-- Allows the API to access Google web-based services -->
        <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
        <!-- Specify OpenGL ES 2.0 as a requirement -->
        <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
        <!-- Replace <com.domain.appid> with your application ID -->
        <uses-permission android:name="<com.domain.appid>.permission.MAPS_RECEIVE"/>
        <permission android:name="<com.domain.appid>.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
        <application>
            <!-- Replace "PASTE YOUR GOOGLE MAPS API KEY HERE" with the Google API key you obtained -->
            <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="PASTE YOUR GOOGLE MAPS API KEY HERE"/>
        </application>
    </manifest>
</android>

読み込むモジュールも記述

<modules>
    <module platform="android">ti.map</module>
</modules>

 

 

4.使ってみる

var MapModule = require('ti.map');

win.add(MapModule.createView({
    mapType: MapModule.NORMAL_TYPE,
    animate: true,
    region: {
        latitude: 35.136942151841716,
        longitude: 136.90021680351,
        latitudeDelta: 0.05,
        longitudeDelta: 0.05
    },
    userLocation: false
}));

 

最後に開発してて気づいたことをいくつか

  • regionに緯度と経度は負の値を設定すると「Invalid Region」と怒られる(iOS)
  • scrollViewの中に入れるとうまく動作しない(Android)

 

 

< Related Posts >

2013年9月18日水曜日

リニア長野県駅「新飯田」の(大まかな)位置が公表されたので、Google Mapsに描画してみた

私の実家の近くに駅ができると聞いていたので気になっていた駅の場所。本日だいたいの位置が公表されたので、Google Mapsの機能を使って書いてみた。

情報元はJR東海の公式ホームページ

下記地図で枠が表示されない場合はこちらから。

153号線に隣接すると思うから、パチンコダイナムとドラッグストアの間ぐらいかな?

実家から歩いていけなくはないけど、個人的にはもう少し東の方がよかった。

2027年完成予定。

2013年9月11日水曜日

anyDensity="false"から脱出するためにAndroidの画面サイズ関連を理解する

screen-adjust-for-androidTitanium Mobileで開発していると、iOSアプリで確認してからAndroidアプリで確認してみると、レイアウトが崩れてしまうことが多い。

当初は「anyDensity="false"」に設定して誤魔化してきたけど、どのAndroid端末でも同じユーザーインターフェイスになるように画面サイズに関する資料を読んでみたときの覚書。

まずは公式ドキュメントを読む。

用語と概念を理解する

Screen size
画面サイズ
端末の物理的な画面の大きさ。
Androidでは、すべての画面サイズを4つに分類している。

small
normal
large
xlarge (extra large)
Screen density
画面密度
画面に対するピクセル数の密度。
単位はdpi (dots per inch)
ディスプレイではピクセルとドットが1体1で対応するので、ppi (pixel per inch)でも同じ意味になる。(wikipedia
Androidでは、全ての画面密度を4つに分類している。最近1つ増えた。

ldpi (low)
mdpi (medium)
hdpi (high)
  端末例)Samsung S2 (SC-02C), Xperia arc (SO-01C)
xhdpi (extra high)
  端末例)Samsung S3 (SC-06D), Xperia A (SO-02E)
xxhdpi
  端末例)Samsung S4 (SC-04E), HTC J One (HTL22)

参考:Androidアプリーリソース画像サイズ&種類ー : Excite Designer's Blog
参考:最新スマホ26機種徹底比較|スマートフォンガイド
参考:画面サイズと画面密度のシェア率 | Android Developers
Orientation
オリエンテーション
画面の向き。
横長か縦長か。
Resolution
画面解像度
画面のピクセル数の総数。
横ピクセル数x縦ピクセル数(例:1024x768)で表記される。
開発するときは画面のサイズと密度のみを意識し、解像度を意識することはない。
Density-independent pixel(dp)
密度非依存ピクセル
画面密度に影響されない仮想的なピクセル単位。
これが見た目の長さになる。
px = dp * (dpi / 160)
この「dp」単位を用いて画面レイアウトすべき。dipも同じ意味

 

Titaniumのデフォルトでは
Androidは「pixel」
iOSは「dp」
を使う。詳しくは公式ドキュメントで。

開発するときに長さを指定する箇所は共通関数を使う記述するようにしていると楽。

frameView = Titanium.UI.createView({
    width: Titanium.UI.FILL,
    height: Titanium.UI.SIZE,
    top: this.$.utils.len(20) // ← 各クラスに必ず渡す「$」に共通関数を定義してある
});

 

< 2015/07/28 Modified >
tiapp.xmlでデフォルトの単位を指定出来る。最近は新しいプロジェクトを作成するとデフォルトで「dp」が設定してある。

<property name="ti.ui.defaultunit" type="string">dp</property>

 


画面密度に対応した画像を用意する

iOSのRetina対応は倍の大きさの画像を同じディレクトリに「@2x」をつけて置いとけばいい。これはTitaniumではなくiOS開発のルール。

Androidの場合は指定のディレクトリを用意しておけば自動で読み込んでくれる。

 

Androidは「9-patch」という仕組みがあるので、要素に合わせて背景画像が伸縮する場合も綺麗に表示できる。

 

アイコンの作成に関するTipsも参考になる。

 

 

< Related Posts >

2013年9月10日火曜日

Google Maps API v3を使って地図上に店舗情報をプロットする

google-maps-api-v3Google Mapに店舗情報をプロットする開発したときの覚書。1年前の下書きを元にしているので情報が古いかも。

環境: Google Maps API v3

やりたい事

  • 緯度と経度を元にGoogle Map上にプロットする
  • プロットしたときのアイコンを独自のアイコンにしたい
  • 表示される吹き出しもいい感じにしたい
  • 表示された店舗情報の数・位置によって、地図上の縮尺をいい感じにしたい
  • たくさんの情報がプロットされたとしてもいい感じに表示したい
  • 住所から緯度と経度を取得したい。逆も。

こんな風に実現できた。

image

 

まずはGoogleの公式ドキュメントを読む。

 

地図を日本語表示したい場合は「language=ja」を追加する

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false&language=ja">

 

住所から緯度と経度を取得するには、下記を参考に。

 

Google Mapに渡せるQuery Parameterは下記に情報があったけど、今はなくっているみたい(2013年9月9日時点)

 

jQueryで簡単に使えるようなライブラリがやっぱりあった。

でも使ってない。

 

近くに情報があったときにまとめて表示するには、下記ライブラリを使う。

これのMarker Clusterer。サンプルがあるので分かりやすい。

 

その他開発するときにハマったのは、Google Mapを読み込む際にElementが非表示だとうまく動作しないので注意。

この場合は表示した段階で地図が読み込み完了しているか判断する必要がある。

 

Google Mapをライセンス上使いたくない場合は下記のようなサービスを利用してみてもいいかも。

 

< Related Posts >

2013年9月9日月曜日

Androidアプリの画面(UI)設計をする際に読んでおきたい資料

android-design-patternsアプリの画面設計する際にどんなUIにするべきか調査したときの覚書。役に立ちそうなサイトの紹介

 

Android Interaction Design Patterns
Androidのデザインパターンを紹介。
それぞれの利点と欠点があり、サンプルアプリを掲載されていてわかりやすい。

 

Draw 9-patch | Android Developers
「NinePatch」を活用すれば、吹き出しや角丸デザインも恐くない。
ちなみにiOSでは同じ仕組みはない。外部ライブラリを使えば出来るみたい。

 

Android Asset Studio
9-patchやアイコンなどを生成してくれるオンラインサービス。

 

Android UI Patterns: Watch this: Google I/O 2013 - Android Design for UI Developers
Google I/O 2013のセッション記事。UI設計に関する動画へのリンクがある。
Android 4.0からのデザインガイドラインの説明。

 

Android UI design patterns: Google I/O 2010
Google I/O 2010のUI設計に関するセッション動画。
まだAndroid2.3系も多いので、この辺の方が役に立つかも。

 

他にもGoogle先生に「App UI Design Pattern」などで聞くといろいろ参考になる情報が出てくる。

 

< Related Posts >

2013年8月27日火曜日

Titanium Studioで"L"のWarningを消したい

titanium_validator-warningTitanium Studioのバリデーション機能を使って構文チェックしているときに"L"(Titanium.Local.getString()のショートカット)がずっとWarning表示されるので非表示するやり方を調査。

環境: Titanium Studio 3.1.2

まずはバリデーション機能を有効にするやり方

Titanium Studio → Preferences → Studio → Validation

JSLint Validatorにチェックを付ける。

image

プロジェクト内を全て再チェックしたい場合は、Project → Clean...

 

'L' was used before it was defined.

がたくさん表示されて見にくいので、フィルターの設定をする。

Titanium Studio → Preferences → Studio → Validation

JSLint Validatorを選択して、下記Filterを追加。「Missing 'new'.」はお好みで。

Missing 'new'.
'L' was .+

image

Strictモードで書いていると未定義の変数があるだけで落ちてしまうので(Android)、Titanium Studioのバリデーション機能は便利。

ファイルの先頭にJSLintのオプションを記述することも出来る。詳細はJSLint: The JavaScript Code Quality Tool

/*jslint eqeq:true, nomen:true, devel:true, plusplus:true*/

 

< Related Posts >

2013年8月25日日曜日

猫を向かい入れるために猫用品を揃える

mei_korosukeシンガポールから帰国して、結婚もしたし、念願の猫ちゃんを向かい入れることにした。

環境: 1LDK(ペット共存型マンション), 先住犬1匹(メス:トイプードル:2歳)

向かい入れたのは仔猫2匹(オスとメスの兄弟:雑種:生後4ヶ月)。

お世話になったのが、犬や猫の保護活動をしている下記NPO団体

譲渡会を定期的に開催しているので、見学に行くといろいろと丁寧に教えてくれる。詳しくは下記で。

今回私が用意(購入)したものを参考程度に載せてみる。

ジャンル 商品 コメント
ケージ

41fqV4Mx0QL._SL500_AA300_

ペットケージ 2段 PEC-902 ホワイト【アイリスプラザオリジナル】

8480円

結構でかい。
鉄製で丈夫だけど、プラスチックの方がシェルターでも使ってるし良かったかも。
プラケージ 810(1段)・812(2段)・813(3段) ベージュ・イエロー・ピンク
Amazonでも売ってる。
トイレ

31x9sVNPdzL._SL500_AA300_リッチェル コロル ネコトイレ 48 ブラウン

1029円

ケージ内用に購入。
問題なく使ってくれたし満足
トイレ 31ncJ x9 GL._SL500_AA300_散らかりにくいネコトイレ CNT-500 ライトブラウン

3781円
リビング用に購入。
先住犬がいても安心してトイレ出来るように。
一応使ってくれるけど、まだリビングには設置してない。
猫砂 41S1NjLXEnL._SL500_AA300_ペグテック トフカスサンドK 7L × 4個【まとめ買い ケース販売】

3120円
猫砂としては問題なし。
しばらくするとおしっこの臭いがきつくなるけど、猫砂の下に重曹を敷いたらかなり軽減されるようになった。
爪とぎ

51EPz1qZ66L._SL500_AA300_mju: (ミュー) ガリガリサークル

1398円

下にタオルを敷いて、ほぼベット化してる。
ボランティアの預かりの人も使ってた。
爪とぎ

41GPueziJrL._SL500_AA300_mju: (ミュー) ガリガリウォール

1980円

これもよく使ってくれてるので買って正解。
周りが噛んで壊すのでガムテープで補強してる。
爪切り

41prINgSYrL._SL500_AA300_ドギーマン ハニースマイル 猫用カーブ爪切り

558円

抱っこするときに前足を触るようにして慣れさせてる最中。
爪の出し入れも素早く出来るように練習中。
フード皿 31rS0B-cGmL._SL500_AA300_ヘルスウォーター フードボウル M

1785円 x 2
2個購入。
大きさもちょうど良かった。
水飲み皿 31XjCSqUZBL._SL500_AA300_ヘルスウォーター ボウル M

1890円
ちょっと大きめ。
Sサイズにすれば良かった。
ネコタワー 31BQiNdkPBL._SL500_AA300_キャットウォーク

13610円
リビングに設置。
猫が登ると揺れるけど、本猫たちは気になってない様子。
見た目的にもグッド。
首輪 img58893693HomeChoker Drop 1cm幅チョーカー(バックルタイプ)

1550円 x 2
名前と電話番号を入れてくれるので、迷子札にもなる。
これ書いてる時点ではまだ到着してない。

51MQ 8ziFkL._SL500_AA300_ナチュラルバランス ウルトラ プレミアム キャットフード 6.3ポンド 2.85kg

3110円

ボランティアの人も使ってるフード。
最初の印象は、臭いがきつい。
食い付きはいい。
あとで購入した下のフードに切り替えるか考え中。

31ziKFvNHYL._SL500_AA300_ヒルズ 猫用 c/d マルチケア ドライ 4kg

4500円

塩分控えめ。
値段も手頃。

トイレ 154521-1

ユニチャーム1週間消臭・抗菌デオトイレ フード付き本体セット (アイボリー)

1680円

8月追加購入。
おしっこの掃除は劇的に楽になる。

猫のトイレ臭い対策でデオトイレを買ってみる

合計するとだいたい5万円ぐらい。

 

当初は仔猫1匹だけ引き取ろうと思っていたけど、4匹の兄弟のうち2匹残っていたので、1匹にするのは可哀想だと思い(ボランティアの人の説得もあり)2匹引き取ることにした。

実際飼い始めてみると、仕事に出ているときに兄弟で遊べて寂しい思いをさせずに済むので正解。

名前は
三毛(メス)が「メイ」
黒(オス)が「コロスケ」

今後、このブログにたびたび登場する予定。

 

< Related Posts >

Related Posts Plugin for WordPress, Blogger...

Blog Archives