monacaでデータベースを使う
monacaアプリでデータベースを使いたい!
ということでデータの永続化について調べた(ノ゚ω゚)ノ*.オオォォォォォォ
いろいろ選択肢があるよう(ノ゚ρ゚)ノ ォォォ・・ォ・・ォ
どんなアプリ
- 読みたい本をストックするアプリ
- 読みたい本リストをデータベースに保存したい
- なのでそんなリッチな機能はいらない
選択肢
Web SQL Database
Indexed Database API
ご参考までに比較記事
thinkit.co.jp
LocalStorage
- キーバリューストアー型
- データベースというよりはデータを「保存すること」を目的にしていると思う
- 逆に言うとシンプルなので扱いが簡単
SQLite(ネイティブから直接使う)
どうしましょ
読みたい本リストを保存したいだけなのでLocalStorageで充分な気がしますが、とりあえずリレーショナルデータベース使いたい。(キーバリュー使ったことない)
何年か前にネイティブアプリを作ってた時にSQLite使ってたので、慣れてるCordova-sqlite-storageを、と思ったのですが、私はmonaca無料プランで開発してるのでプラグインの導入はできず。
ではWeb SQL Databaseか、と思いましたが6年も前にW3Cが放棄してるのか。。。どうしよう、と思っていたところ、「HTML5-ハイブリッドアプリ開発入門」に以下の記載が!
標準化されない機能を使うには不安があるかもしれませんが、iOSやAndroidで利用されているレンダリングエンジンであるWebKitにはすでにWebSQLが実装されており、WebKitからWebSQLが取り除かれる予定はないと開発者によって明言されています。
[iOS/Android対応] HTML5 ハイブリッドアプリ開発[実践]入門 (Software Design plus) : 久保田 光則, アシアル株式会社 : 本 : Amazon.co.jp
ならばよかろう、ということでWeb SQL Databaseを使うことにしました_( _・ω・)_
monaca IDEのgithub連携でgitignoreする
今日軽くつまづいたのでメモ
monaca IDEで.gitignoreが編集できない
monaca IDEからgithubに連携しているソースコードでAPIキーを使っている箇所は、
pushした後に
cont API_KEY = 1234567890
から
cont API_KEY = 【APIキー】
という風に毎回githubで直接編集していたのですが、なんともイケてない。
APIキーだけ別のファイルに書き出してそいつをignoreすればいいっしょ!と思い、monacaで.gitignoreを作成すると
というダイアログが出力されてmonaca IDEからは編集できない、ファイルの表示もされない、でもファイルの実体はあるっぽい。
(commit & push したらgithubに.gitignoregが追加されていた)
monaca開発でのAPIキーの扱いについて
現在頭を悩ませているのがAPIキーの扱いです。
今回のようにgithubでAPIキーを公開したくないだけなら、
で終了です。
でもビルドしたアプリを公開するとなるとどうでしょうか。
monacaのメインはあくまでもhtml、JavaScriptなのでchromeデバッガでデバッグできてしまいます。
つまり”別ファイル(JS)”もロード先のhtml/JSをデバッガで見れば判明してしまいます。
もっというとJS以外のファイルに設定を保持したとしても、APKファイルを解体すればファイルの内容ってみれちゃいますよね確か。。。
対応としては、APIキーを使用する処理をサーバーサイドに寄せて(web API)にしてmonacaで作ったアプリから呼び出せば良いのですが、monacaで完結させる良い方法はないですかね。。。(クライアントサイドでAPIを呼び出すwebアプリも同様)
everNoteにストックしたノートをtwitterにリマインドする
日頃の情報収集や調べごとで気になった記事はevernoteにストックしてるんですが、実際のところ後から見ないことが多い。。。
するとこういうことがよく起こる
あのメソッドでどう使うんだっけ?と思って調べる
↓
あれこの記事見たことがある?
↓
_人人人人人人人人人人人人人人人人人人_
> evernoteにストックしてた <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^^Y^Y^Y ̄
ということでevernoteからランダムでノートを取得してtwitterにリマインドするbotを作りました。
evernoteのAPIを使う
会員登録をすると、テスト環境でAPIにアクセス可能なAPIキーが貰えます。
実装は公式リファレンスに詳しくかいてあるのでほぼそのままコピペ
Ruby(sinatra)を使います
Getting Started with the Evernote API - Evernote Developers
コピペで実装
everApi/everApi.rb at master · susunshun/everApi · GitHub
OAuth部分はこんな感じです
JSONでノートの内容を返してくれるようになりました。
$ curl http://localhost:4567/random {"title":"【vim】行番号の表示・非表示","url":"http://qiita.com/spyder1211/items/c5dd49a3a799bd146599"}
botでリマインド
hubotを使います。
herokuでshをキックしてそこからhubotのscriptを動かします。
#!/bin/sh export HUBOT_TWITTER_KEY="XXXXX" export HUBOT_TWITTER_SECRET="XXXXX" export HUBOT_TWITTER_TOKEN="XXXXX" export HUBOT_TWITTER_TOKEN_SECRET="XXXXX" export HUBOT_NAME="susunshun_o" // hubotを動かす bin/hubot -a twitter --name susunshun_o
もしくはherokuに直接環境変数を設定してもよいです。
qiita.com
hubot本体は以下
shushubot/everTask.coffee at master · susunshun/shushubot · GitHub
かんせいーいヽ(´▽`)/
いまはtwitterの閲覧頻度が多いのでtwitterにリマインドするようにしていますが、hubotを生かしてslackやその他チャットツールと連携してもよいかもですね。
(やるかわかんないけどそのためにevernoteのAPIを独立させた)
herokuを用いたbotの常時運用について
やあ(´・ω・`)
勉強会で発表したものの、ブログにおこしてないトピックが何個かあるので書いてくよ。
botの常時運用
以前evernoteノートの記事をランダムにチョイスしてつぶやくbotを作りました。(記事は後日書きます)
botを常時稼働させる環境として、以前はherokuが一強でしたが
ある日を境に無料枠では18時間/日という制限がついてしまいました。。。
(残念ですが、むしろ無料というのが虫のいい話ですもんね)
AWSでEC2立てちゃう等々、やりようはありますが、
ここではあくまでも「herokuで」、「無料枠で」、運用する方法を紹介します。
といってもかなりごり押し感満載なので参考までに。。。
herokuの制約
1時間以上アクセスがないとsleepする
じゃあ1時間に1回アクセスすればいいじゃん、ということでheroku schedulerというアドオンを使います。
elements.heroku.com
これでherokuにアクセスするコマンド(curl)を毎時実行してsleepを防ぐわけです。
18時間/日しか動かせない
じゃあ18時間以内に抑えればいいじゃんということで、今度はprocess schedulerというアドオンを使います。
elements.heroku.com
これでアプリを二つデプロイして、各々以下の設定をします。
アプリを二つデプロイするところがだいぶごり押しですが、めでたく無料枠で常時運用が可能です!
やったね!
社内ハッカソンでプレゼンがんばった話
半年前の社内ハッカソンでは結果は20数チーム中7位と、なんともいえない結果でした。。。
あれから半年、またハッカソンが開催されたので、振り返り用として反省点、やったことを書きます。
プレゼンをがんばったのでアプリの話ではなく、プレゼンの話が主です(。・ω・。)
前回の反省
デモ
前回はアイデア的には悪くない、アプリの完成度も高かった、と思うのですがデモで失敗しました。。。(ノ_-。)
冷蔵庫の在庫をタグ管理するアプリを作ったものの、デモでは読み取り端末にタグをピッとタッチしただけ。
聞いてる側はそのアプリがどういう風に使われるのかイメージが難しかったとおもいます。
こまけぇことはいいんだよ!
ハッカソン共通で言えることですが、
- プレゼンが短い(今回は4分or5分)
- 発表チームが多い
ということがあり、あまり難しい内容をつらつらと発表してもおじさん達の頭には入っていきません。
前回はアプリ概要からビジネスモデル、技術要素とてんこ盛りの5分にした結果、
結局アプリの魅力が伝わりきらなかった気がします。
つまり
こういうことです。
今年のハッカソン
こんなものを作ったよ
対象物をアプリで撮影すると、自分と属性が似ているユーザのクチコミを引っ張ってきてくれる
というアプリを作りました。
PVを入れる
聞き手にイメージを持ってもらうためにプレゼン中のデモに加えてプロモーションムービーを作成しました。
撮影のためにハッカソン中に本屋へ行ったりwww
ムービー作成は他のメンバーに任せたのですがガチクオリティのPVを作ってくれてマジ感謝ヾ(○´□`○)ノ"
インパクトがあるプレゼンよりも理解されるプレゼン
最近の流行りとして、スライドいっぱいに写真を表示して一言だけ文字が書いてある、というものがあります。
こういうのです。
今回のハッカソンでも何チームかがそのようなスライドでした。
オシャレですしで個人的には好きなのですが、この方法は短時間で聞き手に「理解させる」というよりも「インパクトを残す」、という点に利があると思っています。
発表するチーム数が多いので、なんとなくイメージには残ってるけど結局何だったっけ?ということになりかねません。
今回は「インパクトを残す」役割はPVに任せ、スライドでは「理解させる」ことが重要と捉え作成しました。
↓こういう点はいつも心がけるようにしています。
予選と本選でプレゼンの構成を変える
今回実は予選と本選にわかれており、プレゼンの時間や審査員が異なっています
そこで予選と本選でプレゼンの構成を変えました。
◼︎予選(20チームくらい)
時間:4分
審査員:参加者、ハッカソン運営
プレゼン構成:
問題提起
↓
解決のアプローチ
↓
アプリ説明
↓
デモ
↓
PV(short ver.)
↓
技術要素
とにかく時間がないのでPVはデモの補足説明的なポジションでデモの直後に入れています
◼︎本選(予選から選抜された6チーム)
時間:5分
審査員:社長、役員、スポンサー企業様
プレゼン構成:
★PV(full ver.)
↓
問題提起
↓
解決のアプローチ説明
↓
アプリ説明
↓
デモ
↓
技術要素
↓
★締めの言葉的なフリートーク
コンセプトやイメージを最初に刷り込むためにPVを先頭に持ってきています。
最後には締めの言葉的なことを言うアドリブタイムを設けました。
時間が足りず最後の方は早口、挙句の果てにタイムアップで途中で切られる、というチームが続出する中、
うちのチームは時間通りで余裕を持ってプレゼンを締めることができたので有効な策でした。
スライドとアプリのデザインを統一する
スライドに違和感を出さないために、スライドとアプリのデザインや配色は統一しています。
ビジネスモデルはプレゼンから省いて質疑で受ける
プレゼンは前述の通り5分しかないので、ビジネスモデルの説明は完全にカットしました。
説明しなけりゃ逆に質疑応答タイムで聞いてくるだろうと予測して、発表外のスライドとして用意。
結果は。。。!?
5つの賞のうち2つを受賞することができました!
最優秀賞は逃したものの、ダブル受賞→賞金王です。
プレゼンがどこまで評価に寄与したかは分からないですが、確実に加点要素にはなっていたはずです。
アイデアは浮かぶか浮かばないか、不確実性がありますが、プレゼンはポイントを押さえていれば誰でもクオリティを上げられると思うので、ハッカソンといえど今後も力を入れておきたいところです。
また、今回は同期(3年目)4人でチームを組んで参加しました。
若い奴らが社内の大きなイベントで目立つということは会社的にもとても良いことだと思うので、今後も受賞狙ってプレゼン頑張ります('∇'*)
hubot導入めも (インストールからherokuアップロードまで)
hubot(というかbot)が面白そうだということで触ってみた。
hubotってなにさ?
「botを作るだけだったらフレームワークなんて使わんでも簡単にできるよ、twitterのbot用ツールとかあるし」
そう思った方、正にそうです。
ただhubotは様々なチャットツールに対応しています。
hubotとチャットツールをつなぐ役目を担うモジュール「Adapter」を切り替えることで、
botの処理を1回書くだけで様々なチャットツールに対応させることができます。
イメージこんなん(勉強会で使った資料から抜粋)
やること
- Node.jsインストール
- hubotインストール
- hubot起動
- adapterインストール
- herokuデプロイ
- (おまけ)Cronで動かす
ちなみに今回いろいろと調べながら導入作業をしていたのですが、
この記事が全般的にとても参考になりました。マジ感謝。gihyo.jp
Node.jsインストール
node.jsのバージョン管理をしやすくするためにNodebrewをインストールします。
$ brew update
$ brew install nodebrew
インストールの過程でパスを通してね、というメッセージが出ます。
Add path: export PATH=$HOME/.nodebrew/current/bin:$PATH To use Homebrew's directories rather than ~/.nodebrew add to your profile: export NODEBREW_ROOT=/usr/local/var/nodebrew
ということでパスを追加(bashの場合)
$ vi ~/.bash_profile
$ source ~/.bash_profile
nodebrewを最新版に更新
$ nodebrew install latest
使用するバージョンを指定する場合には以下
$ nodebrew use v4.2.1
$ node -v
v4.2.1
hubotインストール
ではではhubotをインストールしましょう( ´ ω ` )
$ sudo npm install -g hubot coffee-script
hubotを召喚します
$ hubot --create myhubot
なんかでた
'hubot --create' is deprecated. Use the yeoman generator instead: npm install -g yo generator-hubot mkdir -p myhubot cd myhubot yo hubot See https://github.com/github/hubot/blob/master/docs/index.md for more details on getting started.
どうやら「createはもう古いぜyeomanを使えよfuck」ってことらしいですqiita.com
ということでそのままコマンドを・・・叩きこむっ!
$ npm install -g yo generator-hubot $ mkdir -p myhubot $ cd myhubot $ yo hubot
召喚成功するとヤツが登場します。
_____________________________ / \ //\ | fuXX you. | ////\ _____ | What’s up, man ? | //////\ /_____\ \ / ======= |[^_/\_]| /---------------------------- | | _|___@@__|__ +===+/ /// \_\ | |_\ /// HUBOT/\\ |___/\// / \\ \ / +---+ \____/ | | | //| +===+ \// |xx| ※一部改変あり
hubot起動
hubotを起動してデフォルトで備わっているコマンドを試してみる
$ ./bin/hubot
するとhubotと対話モードになります。
コマンド一覧を表示する
myhubot>myhubot help myhubot animate me <query> - The same thing as `image me`, except adds a few parameters to try to return an animated GIF instead. myhubot echo <text> - Reply back with <text> myhubot help - Displays all of the help commands that myhubot knows about. myhubot help <query> - Displays all help commands that match <query>. myhubot image me <query> - The Original. Queries Google Images for <query> and returns a random top result. myhubot map me <query> - Returns a map view of the area returned by `query`. myhubot mustache me <query> - Searches Google Images for the specified query and mustaches it. myhubot mustache me <url> - Adds a mustache to the specified URL. myhubot ping - Reply with pong myhubot pug bomb N - get N pugs myhubot pug me - Receive a pug myhubot the rules - Make sure myhubot still knows the rules. myhubot time - Reply with current time myhubot translate me <phrase> - Searches for a translation for the <phrase> and then prints that bad boy out. myhubot translate me from <source> into <target> <phrase> - Translates <phrase> from <source> into <target>. Both <source> and <target> are optional ship it - Display a motivation squirrel
パグの画像を返してくれる'ああ^~こころがぴょんぴょんするんじゃあ^~'なコマンドがあるらしいので試してみる。
myhubot> myhubot pug me - Receive a pug myhubot> http://24.media.tumblr.com/tumblr_mc4u6lwZHr1qf4k86o1_500.jpg
hubotの終了はexit
myhubot>exit
hubotに何かさせたいときはscriptディレクトリ配下にXXX.coffeeを作成して処理を書きます。
※CoffeeScriptで書きます
script配下にhello.coffeeというファイルを作成し、挨拶したら爽やかに返してくれるスクリプトを書いてみましょう
module.exports = (robot) -> robot.respond /HELLO$/i, (msg) -> msg.send "fuck you"
挨拶してみる
myhubot> myhubot hello myhubot> fuck you ^ ^
前衛的な挨拶ですね。
adapterインストール
adapterというのはHubotとチャットツールをつなぐモジュールのことです。
デフォルトで提供されているものもあれば、自分で作ることもできます。
今回はtwitterのadapterを導入
$ npm install hubot-twitter --save && npm install
twitterは起動時に環境変数としてAPIキー等を渡す必要があるので、sh起動時に必要なものは設定するようにしましょう。
この記事を参考にさせていただきました。qiita.com
#!/bin/sh export HUBOT_TWITTER_KEY="自分のAPI key" export HUBOT_TWITTER_SECRET="自分のAPI secret" export HUBOT_TWITTER_TOKEN="自分のAccess token" export HUBOT_TWITTER_TOKEN_SECRET="自分のAccess token secret" export HUBOT_NAME="自分のbotの名前" bin/hubot -a twitter
'bin/hubot -a twitter'の'-a'はadapterを明示的に指定する際のオプションです。
これでローカルでhubotを起動してtwitter上で動作するようになりました。
herokuデプロイ
herokuから参照するprocfileの編集。前述と同じ理由でtwitterのadapterを指定。
bin/hubot -a twitter
ここで一旦gitにコミットしておく
$ git init $ git add . $ git commit -m "initial commit" $ git remote add origin git@XXXXXXXX
いよいよherokuにデプロイ
$ heroku login $ heroku create $ git push heroku master
shでsetしたものと同様の設定をherokuにも行ってあげます
$ heroku config:add HUBOT_TWITTER_KEY="自分のAPI key" $ heroku config:add HUBOT_TWITTER_SECRET="自分のAPI secret" $ heroku config:add HUBOT_TWITTER_TOKEN="自分のAccess token" $ heroku config:add HUBOT_TWITTER_TOKEN_SECRET="自分のAccess token secret"
(おまけ)Cronで動かす
hubotは基本的に特定の発言に対して特定の動作を行いますが
Cron使って定時起動 > 自発的に発言できるようにしたいなぁ、と。
以下を参考にしてCronで動くようにしました。qiita.com
まずCronを導入するためにpackage.jsonに以下を追記
"cron": "^1.0.5", "time": "^0.11.0"
Scriptは参考記事ほぼまんまでこんな感じで。
Cronで毎分10,20,・・・50秒のときにツイートを行うという簡単なもの。
module.exports = (robot) -> cronjob = new cronJob( cronTime: "00,10,20,30,40,50 * * * * *" start: true timeZone: "Asia/Tokyo" onTick: -> d = new Date min = d.getMinutes() sec = d.getSeconds() message = "#{sec}secなう!" robot.send {user:{user:'XXXXX'},screen_name:'XXXXX', room: 'Twitter'}, "#{sec}秒なう!" )
これで一通りの導入、動作確認は完了。
これを使って何か作ってみよう。
はてな記法使ってるんだけどshのシンタックスハイライトの効き方がとても。。。微妙です。
twitterのadapterについて
ここで導入したtwitterのadapterはStreaming APIを使用してタイムラインを探索しています。
以前私の記事で取り上げましたが、Streaming APIは全ツイートを取得できるわけではないので稀に漏れが発生することに注意ですsusunshun.hatenablog.com
ハッカソンデビュー
先日、社内のハッカソンイベントに参加してきました!
ハッカソン自体、初参加なのでいろいろ学ぶべきところは多かったです。。。
ハッカソンって何さ?
端的に表現すると、
”ハック” × ”マラソン” = ”ハッカソン”
です
短期間(今回は2日)でサービスの考案、開発、プレゼンまでを行って、アイデアと技術を競い合うというイベントです
今回つくったもの
今回は「未来(2017〜2020年)」がテーマです。
うちのグループでは以下のようなサービスを作りました。
- ICタグで冷蔵庫の在庫管理
- Webから在庫情報を閲覧可能
- 賞味期限が近い食材を使ったレシピを推薦
わいが担当したのは
です。
ICタグで在庫管理 〜ICタグリーダー
理想は有効範囲が広いRFIDリーダーを使いたかったのですが、開発期間が短いこともあり今回はNFCで妥協することにしました。(最大の妥協)
NFCリーダーは最近のandroidならばどの端末にも組み込まれているので、androidアプリとして実装しています。
あくまでもプロトタイプなので、色々な理想を忘却して最大限実装を簡略化しています
- 商品タグのIDを読み込む
- http://XXX.com/api/【商品タグID】にリクエスト送信、API側で商品タグIDを抽出、在庫更新
ソースはこんな感じ
public class MainActivity extends Activity { //APIのURL private static final String sURL = "http://hackson-10-112187.nitrousapp.com/api/v1/stocks"; StringBuilder sb = new StringBuilder(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView text = (TextView)findViewById(R.id.tag_id); //EXTRA_ID出力領域 TextView text_tag = (TextView)findViewById(R.id.tag_tag); //EXTRA_TAG出力領域 // インテントの取得 Intent intent = getIntent(); String action = intent.getAction(); if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) { // NFCからID情報取得 byte[] ids = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID); for (int i=0; i<ids.length; i++) { sb.append(String.format("%02x", ids[i] & 0xff)); } text.setText(sb.toString()); // NFCからTAG情報取得 Tag tag = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String techStr = ""; for (String tech : tag.getTechList()) { techStr = techStr + tech + "\n"; } if (techStr.equals("")) { techStr = "no techList."; } //TechListを表示 text_tag.setText(techStr); } //GETリクエスト new Thread(new Runnable() { @Override public void run() { try { HttpClient httpClient = new DefaultHttpClient(); //APIにリクエスト送信 HttpGet httpGet = new HttpGet("http://XXXX.com/api/" + sb.toString()); HttpResponse httpResponse = httpClient.execute(httpGet); String str = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); } catch(Exception ex) { } } }).start(); } }
ICタグで在庫管理 〜API
APIは以前Grapeで作成したものを持ち込んでちょろっと改修しようと思ってたのですが、デモ環境で動かず5時間の苦戦のうえ泣く泣くあきらめました。。。
結局Railsで作成したWebアプリのコントローラーでリクエストを受けることにし、30分くらいで作成。
APIなのでコントローラーからは独立させたかったのですが。。。
所詮プロトタイプなのでそういうこだわりは捨てて手っ取り早く実装しちゃうのが吉ですね
開発・デモ環境について
gitを準備する時間も惜しいということで今回はnitrous.ioというオンラインのIDEをチームで使用しました。
結構優れもので、同じソースを複数人で改修していても他の人の追記部分がリアルタイムで反映されるため手軽に共同開発するには向いていると思います!
ただ今回は失敗でした。。。というのも
- 備え付けのLAN環境が激遅で他人の改修が自分の編集画面に反映されるのに遅延が多発、結果コーディングしたはずの箇所が消えるということが何回も起きました
- LAN激遅につき、コーディングしてる最中に何回も画面が読み込み中になり作業が止まる
- 挙句の果てに実装して保存、サーバを起動しても追記内容がサーバに反映されていない
等々、今回の設備環境には向いてなかったみたいです。
やはりgitを入れとくべきでしたと反省。
完成
朝04:30までプレゼンの準備、フロントの作成等黙々と作業をした結果、こんなのができました。
(デザインのクオリティが予想してたよりも遥かに高い!Webアプリ担当の方おつかれさまでした)
終えてみての感想
システムの完成度は重要じゃない
サービスのコンセプト、魅力的なプレゼンが極めて重要だと感じました。極端な話、実装はモック程度でよい気がします。今回うちのチームは実装に大半の時間を費やしたのでここをプレゼンのブラッシュアップにあてればよかったですね。