MapActivityがない?
しばらくAndroidから離れている間にAndroidStudioがどんどんバージョンアップを繰り返していってるみたいなので、EclipseからAndroidStudioに乗り換えることにした。
GoogleMapを使ったアプリでも作ってみるかと、
MapActivityを継承しようとしたんだけど・・・・MapActivityが見つからない。
調べてみると、MapActivityはGoogleMapAPIv1のAPIで、v2ではMapFragmentを使うんだとか。
http://stackoverflow.com/questions/22340762/mapactivity-could-not-be-found-android-studio-0-5-1
知らんかった・・・・。
Galleryから取得した画像のExifメタタグが読み込めない
IntentでGalleryを呼び出して、選択した画像のメタタグを読み込み、GPS情報等の情報を取得するプログラムを作ってみた。
メタタグの読み込みはExifInterfaceクラスを用いる。
インスタンス生成にはJPEGファイルのディレクトリが必要なので、
Galleryから取得したURIをContentResolverでディレクトリ文字列に変換したものを設定することにした。
Galleryからのコールバックメソッドの部分を以下に示す。
public void onActivityResult(int requestCode, int responseCode, Intent data) { if (requestCode == REQUEST_GALLERY && responseCode == RESULT_OK) { // URIを取得 Uri uri = data.getData(); // ContentResolverを用いてURIが示す画像ファイルの情報を取得 Cursor c = getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null); String filePath = null; if (c.moveToFirst()) { int index = c.getColumnIndex(MediaStore.Images.Media.DATA); // 画像ファイルのディレクトリを取得 filePath = c.getString(index); } try { // ExifInterfaceインスタンスを生成 ExifInterface exif = new ExifInterface(filePath); // TODO タグ情報を取得 } catch (IOException e) { e.printStackTrace(); } } }
GalaxyS4(4.2)では取得できるのだが、Nexus7(4.4.2)では以下のようなエラーが発生する。
03-12 22:34:01.571 21283-21283/net.atlabo.sample.exif E/JHEAD﹕ can't open '/storage/emulated/0/Download/20140309_172716.jpg’
調べてみたら、こんなことが書いてあった。
http://stackoverflow.com/questions/21857327/exifinterface-jhead-cant-open-error-android
どうやらAndroidManifest.xmlにSDカード書き込み権限を付与してやらないといけないらしい。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
機種依存なのかAndroidAPIなのかは調べてないが、これで解決。
家族でグリーンランド遊園地に行ってきた 〜フリーパス?回数券?〜
グリーンランドで遊びまくってきたので、このブログの趣向とは異なるが、メモ書きついでに書いておく。
3/9(日) 晴れ
風が少し強く肌寒かったが、天候もよくまずまずの日だった。
家族で行ったので、自分と妻、娘(7歳)、息子(5歳)の4人。
フリーパスを購入した方がお得なのか、それとも回数券を購入した方がお得なのか、検証してみた。
・人が多く、待ち時間が長ければ、アトラクションにあまり乗れない?
・子どもたちもいるし、回数券が多く必要な絶叫系のアトラクションは乗らない?
こんな考えから、回数券の方がお得なのかなというのが、行く前の考えだった。
でも、せっかく楽しみに来たのに、回数券の残量を気にしながら遊ぶのもなぁ・・・・と思い、結局フリーパスにした。
経路や所要時間等前日に下調べをしておき、計画通りに開園の9:30に入場、閉園の17:30に退場した。
入園料+フリーパスの料金は以下のとおり。
おとな(高校生以上) | 5,400円 |
こども(3歳以上中学生以下で120cm以上) | 4,400円 |
こども(3歳以上中学生以下で120cm未満) | 3,300円 |
シニア(65歳以上) | 3,300円 |
うちはおとな2名、こども(120cm未満)2名で、計17,400円
ちなみに、入園料だけだと以下のとおりとなる。
おとな(高校生以上) | 1,600円 |
こども(3歳以上中学生以下で120cm以上) | 800円 |
こども(3歳以上中学生以下で120cm未満) | 800円 |
シニア(65歳以上) | 800円 |
3月1日〜6月1日までは春催事料金となり、入園料がおとな200円、それ以外が100円高いようだ。
入園料のみだと我が家の場合、4,800円
この他に回数券を購入してアトラクションを楽しむことができる。
回数券は30枚綴りで1枚あたり100円、1枚単位だと110円となる。
フリーパス込みと入園料の差額は12,600円となるため、1枚100円換算で126枚分以上使用すれば元が取れることになる。
さて、時間内に実際に乗ったアトラクションはというと・・・・・。
アトラクション | 回数 | 1回に必要な回数券 | 金額 |
---|---|---|---|
サラマンダー伝説 | 4回 | 5枚 | 2,000円 |
スカイシップ | 4回 | 2枚 | 800円 |
ドラゴンリバー | 3回 | 7枚 | 2,100円 |
GTゴーカート2人乗り | 2回 | 4枚 | 800円 |
スカイリフト | 4回 | 3枚 | 1,200円 |
魔女のフライングトリック | 4回 | 4枚 | 1,600円 |
スーパースライダー | 4回 | 3枚 | 1,200円 |
バンパーボート(2人乗り) | 2回 | 5枚 | 1,000円 |
スフィンクスコースター | 8回 | 3枚 | 2,400円 |
スプラッシュ | 2回 | 4枚 | 800円 |
ミニバイキング | 3回 | 2枚 | 600円 |
デンジャーメイズ | 4回 | 3枚 | 1,200円 |
ロードトレイン | 4回 | 3枚 | 1,200円 |
てんとう虫コースター | 16回 | 3枚 | 4,800円 |
グランパスジェット | 6回 | 5枚 | 3,000円 |
メリーゴーランドランデブー | 4回 | 3枚 | 1,200円 |
スカイジェット | 4回 | 3枚 | 1,200円 |
マーメイドパラダイス | 4回 | 3枚 | 1,200円 |
ブラックホールコースター | 14回 | 6枚 | 8,400円 |
アンパンマンハッピースカイ | 3回 | 3枚 | 900円 |
働く車ドリフトレーシング | 8回 | 3枚 | 2,400円 |
フリースタイル | 4回 | 3枚 | 1,200円 |
メキシカンハット | 4回 | 3枚 | 1,200円 |
ウォーターショット | 3回 | 3枚 | 900円 |
ティーカップ | 2回 | 2枚 | 400円 |
急流すべり パニックジャングル | 10回 | 5枚 | 5,000円 |
インディカート2人乗り | 2回 | 4枚 | 800円 |
ウエスタン列車 | 4回 | 2枚 | 800円 |
大観覧車レインボー | 4回 | 6枚 | 2,400円 |
飛ぶゾウくん | 2回 | 2枚 | 400円 |
ルクソールマジック | 4回 | 5枚 | 2,000円 |
リフト | 4回 | 2枚 | 800円 |
※回数は1人1回で1カウント。4人で1回乗れば4回とカウント。
回数券1枚あたり100円換算で、金額にして55,900円分の回数券を使ったことになる。
身長制限もある中で絶叫系のアトラクションにはほとんど乗っていないけど、
寒かったからなのか、人の入りがそんなに多くなく、
どのアトラクションもそんなに待つこともなく乗れたので、かなり得した気分。
待ったと言えば、昼下がりのブラックホールコースターで20分くらい待ったけど、
それくらいのもんで、ここも夕方行ってみたらガラガラだった。
今回乗った中で満足したアトラクションは
1位 | ブラックホールコースター | 5歳から乗れるジェットコースターということで家族全員楽しめた |
2位 | 急流すべり パニックジャングル | 上記と同じで、年齢・身長制限なく4人乗りボートに乗れた |
3位 | グランパスジェット | 110cmから乗れるジェットコースターで、7歳の娘が大興奮。 |
逆に残念だったのは
1位 | サラマンダー伝説 | 電子銃で的を撃つというアトラクションだったけど、当たらないし地味 |
2位 | ルクソールマジック | 1回行ったらもういいかな |
3位 | デンジャーメイズ | ここも1回行ったらもういいかな |
開園から閉園まで遊ぶ場合はフリーパスが圧倒的にお得なことがわかった。
近所で年間2回以上行くなら年間フリーパスなんだろうけど・・・・。
CodeIgniterで入力チェックを実装する
CodeIgniterには入力チェックを行うAPIが組み込まれている。
入力チェックのためのライブラリの読み込みを行い・・・・
$this->load->library('form_validation');
入力チェックルールを設定する。
$this->form_validation->set_rules('userId', 'ユーザID', 'required')
setRuleメソッドは3つの引数が必要になる。
第1引数・・・リクエストパラメータ名
第2引数・・・エラーメッセージに埋め込む文字列
第3引数・・・入力チェック
第3引数に入る文字列は以下を参照。
http://codeigniter.jp/user_guide_ja/libraries/form_validation.html#tutorial
1つのパラメータに複数の入力チェックを設定したい場合は、パイプ(|)を用いてチェック文字列を連結する。
ルールの設定を行った後は、
$this->form_validation->run()
で入力チェックを実施できる。
入力チェック結果はBooleanの結果を返却する。
TRUEの場合は検証結果OK、FALSEの場合は検証結果NGを表す。
CodeIgniterでログ出力
ログ出力するためには、application/config/config.phpの以下の部分を設定する必要がある。
$config['log_threshold'] = 0;
コメントが書いてあって、説明を見ると以下のようになっている。
0 = Disables logging, Error logging TURNED OFF
1 = Error Messages (including PHP errors)
2 = Debug Messages
3 = Informational Messages
4 = All Messages
0がログ出力無効で、徐々に範囲が広がっていき、4を設定すると全てのメッセージを出力するようだ。
注意すべきは2と3。
2を設定すると、ERRORとDEBUGレベルのメッセージを、
3を設定すると、ERROR、DEBUGに加え、INFOレベルのメッセージを出力することになる。
ん?何か逆じゃない??
ちなみに、ログは以下のようにすることで出力することが可能
log_message(‘debug’, “Hello World”);
第一引数にはログレベルを設定する。
レベルはdebug,info,errorのいずれか。
ログのデフォルトの出力先は、application/logsとなる。
ディレクトリのアクセス権として書き込み権限を付与しておく必要がある。
Androidのtoast(トースト)みたいなやつをブラウザ上で実現するためのライブラリ
ブラウザ上でtoastを実現するJavaScriptライブラリを探してみた。
toastr
https://github.com/CodeSeven/toastr
こんなのを見つけた。
簡単そう。
追加ボタンを押したら・・・
こんなモーダルダイアログを用意して、必要事項を入力後・・・
登録ボタンを押すと、「ユーザを登録しました」みたいなメッセージのtoastを表示する。
そんなコードを書いてみた。
ユーザのテーブルとモーダルダイアログのHTMLコードは以下の通り。
追加ボタンを押すことでUserControllerクラスのopenModal()が呼び出され、モーダルダイアログが開かれる。
モーダルダイアログはテンプレートとして用意してある。
<div class="container" ng-controller="UserController"> <div class="row"> <div class="col-lg-12 text-right"> <button type="button" class="btn btn-default" ng-click="openModal()"> <span class="glyphicon glyphicon-plus">追加 </button> </div> </div> <br/> <div class="row"> <table class="table table-striped" ng-init="getUserList()"> <tr> <th>ID</th> <th>名前</th> <th>メールアドレス</th> <th> </th> </tr> <tr ng-repeat="user in userList"> <td>{{user.user.id}}</td> <td>{{user.user.name}}</td> <td>{{user.user.mailAddress}}</td> <td> <button type="button" class="btn btn-default"> <span class="glyphicon glyphicon-pencil">編集 </button> <button type="button" class="btn btn-default"> <span class="glyphicon glyphicon-trash">削除 </button> </td> </tr> </table> </div> </div> <script type="text/ng-template" id="useraddModal.html"> <div class="modal-header"> <button type="button" class="close" ng-click="closeModal()" aria-hidden="true">×</button> <h4 class="modal-title" id="modalLabel">ユーザ追加</h4> </div> <div class="modal-body"> <form role="form" class="form-horizontal"> <div class="form-group"> <label for="userId" class="col-sm-4 control-label">ユーザID</label> <div class="col-sm-6"> <input type="text" id="userId" ng-model="userId" class="form-control" placeholder="ユーザID"/> </div> </div> <div class="form-group"> <label for="userName" class="col-sm-4 control-label">ユーザ名</label> <div class="col-sm-6"> <input type="text" id="userName" ng-model="userName" class="form-control" placeholder="ユーザ名"/> </div> </div> <div class="form-group"> <label for="mailAddress" class="col-sm-4 control-label">メールアドレス</label> <div class="col-sm-6"> <input type="text" id="mailAddress" ng-model="mailAddress" class="form-control" placeholder="メールアドレス"/> </div> </div> <div class="form-group"> <label for="password" class="col-sm-4 control-label">パスワード</label> <div class="col-sm-6"> <input type="password" id="password" ng-model="password" class="form-control" placeholder="パスワード"/> </div> </div> <div class="form-group"> <label for="passwordConfirm" class="col-sm-4 control-label">パスワード(確認)</label> <div class="col-sm-6"> <input type="password" id="passwordConfirm" ng-model="passwordConfirm" class="form-control" placeholder="パスワード(確認)"/> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-8 text-right"> <button type="submit" class="btn btn-default" id="useradd_add_button" ng-click="addUser()">登録</button> </div> </div> </form> </script>
次にUserController.js
openModal()ではモーダルダイアログを開く処理を記述している。
この時、UseraddControllerをバインドするようにしている。
var UserController = function ($scope, $resource, $modal) { $scope.userList = null; $scope.getUserList = function() { $resource("http://localhost/ProjectsWeb/contents/samplejson/userlist.json").get( function(data) { $scope.userList = data.userList; console.log($scope.userList); }); }; $scope.openModal = function() { var modalInstance = $modal.open({ templateUrl: 'useraddModal.html', controller: UseraddController }); modalInstance.result.then(function() { }, function() { }); } }
最後にUseraddController.js
モーダルダイアログの登録ボタンが押されたら、addUserが呼び出される。
toastr.success('ユーザを追加しました');
の部分でtoastを表示している。
var UseraddController = function ($scope, $modalInstance) { /* * モーダルを閉じる */ $scope.closeModal = function(ret) { $modalInstance.close(ret); } /** * ユーザを追加する * @returns {undefined} */ $scope.addUser = function() { var userId = $scope.userId; var userName = $scope.userName; var mailAddress = $scope.mailAddress; var password = $scope.password; var passwordConfirm = $scope.passwordConfirm; // TODO 入力チェック // TODO ユーザ追加 $scope.closeModal(true); toastr.success('ユーザを追加しました'); } }
詳しくは下記を参照すれば、表示を変更する方法が書いてある。
https://github.com/CodeSeven/toastr