Meditation Noteアップデート作業中(2)

リリース済みのアプリのアップデート作業ということでサクっと終わると思っていたのですが、ことあるごとにはまってしまい悪戦苦闘しています。さぼってるわけではないんですが、スキル不足というか集中力が続かないというか。。。
アプリを制作する上でAngularJSと英語がわからないことの不便さも痛感します。いまさらですがAngularJSの勉強をしようかと思っています(英語は来世で)。

進捗

とりあえず、このアップデート作業で何をしていたのか、制作日記から抜粋し振り返ってみます。

  • 10/25 アップデート作業を開始する
  • 10/28 v1.0.0のファイルデータの変換関数完成。前機能の削除、管理テーブルの変更
  • 11/3  日付・時間表示形式設定機能完成
  • 11/8  グラフ機能完成。ブログにAdSense広告が表示されるようになってうかれる
  • 11/9  メモ機能完成。アメリカ大統領選挙。アンドロイダーの公認デベロッパー登録が完了してうかれる
  • 11/14 ニフティバックエンドを利用した機能追加
  • 11/15 レイジーリピート導入
  • 11/16 Onsen UI v2に移行

グラフはずっとflotr2を使っているのですが、今回はじめて棒グラフと線グラフを一緒に表示することにしたのでちょっと時間がかかってしまいました。あと、ニフティバックエンドを使ってみたくて、いろいろ調べたりサンプルを作って勉強したりもしてました。
現在Onsen UI v2対応とマテリアルデザイン化を行っているところです。
この作業に意外と手間取っています。

Onsen UI v2への移行

Onsen UI v1からv2への移行自体は割とスムーズにいきました。Onsen UIドキュメント「Onsen UI 1 系からの移行」や、Monaca公式ブログ「Onsen UIをバージョン1から2へ移行するには」にわかりやすい説明があります。ただ私の場合(localkit)、「JS/CSSコンポーネントの設定画面で Onsen UI をいったん削除する」とあったのですが、インストールしたコンポーネントの一覧に Onsen UI がなかったため、そのまま Onsen UI v2.0.3をインストールしました。そうしたところ、アプリの画面がへんてこに。調べてみると、なぜか v1.3.8 の CSS ファイルを参照しているらしく、Onsen UI を削除してから再度インストールをしたら正常に動作するようになりました。

マテリアルデザイン

Onsen UI v2をインストール後アプリを起動すると、自動的にマテリアルデザイン化されるようです(IDEのプレビューは ons.platform.select(‘android’); を実行すると対応します)。最初、マテリアルデザインに違和感があり、元のデザインに戻そうかと考えたのですが、何度も見ているうちに慣れてきたというか逆にシンプルさが気に入り、今回アプリをマテリアルデザインに対応させることにしました。
Onsen UIコンポーネント(ons-xxx)は自動的にマテリアルデザイン化してくれるのですが、それ以外の要素(div, li, …)は手動で対応させる必要があります。今、この作業をOnsen UI Theme Rollerを参考にしながら行っています。例えば、ulリストは以下のような記述になります(Material List引用)。

<ul class="list list--material">
  <li class="list__item list__item--material">
    <div class="list__item__center list__item--material__center">
      <div class="list__item__title list__item--material__title">Orange</div>
      <div class="list__item__subtitle list__item--material__subtitle">Sweet fruit that grows on trees.</div>
    </div>
  </li>
  <li class="list__item list__item--material">
    <div class="list__item__center list__item--material__center">
      <div class="list__item__title list__item--material__title">Pear</div>
      <div class="list__item__subtitle list__item--material__subtitle">Funny-shaped fruit.</div>
    </div>
  </li>
</ul>

クラス名はBEM(Block Element Modifier)を適用しているので慣れてない私にはどこで切れてるか見分けるのが大変。目がしょぼしょぼしてきますが、これを自分で作成するのはもっと大変なわけで、こういうサンプルは非常にありがたいです。

なお、マテリアルデザインについてはグーグルがガイドラインを公開しています。
・公式サイト: Material design
・日本語のドキュメントはこちらからダウンロードできます。

おわり

来週リリースを目標に明日から本気出します。

リリースしたアプリの起動がある日突然遅くなった話

昨日 11/2 お昼前、いっぷくしようと思い、自作アプリ Smoking Note を立ち上げようとしたときのことです。
… アプリの起動が妙に遅い
スプラッシュスクリーンが消えた後も、時刻などの動的に描画する要素がなかなか表示されない。ちょっと許容できない遅さで、たまたまかなと思い何度か立ち上げなおしても状況は変わらず。アプリの起動後の動作には問題がなく、広告自体もちゃんと表示されるのですが、ただただ遅い。

アプリのキャッシュをクリアしても、スマホを再起動してもだめ。
「いやいや、今日ついさっきまで普通に起動してたのに、冗談でしょう?」と軽く現実逃避しながら昼食をとり、気を取り直して再度アプリを立ち上げてみても、やっぱり起動が異常に遅い。

このとき、めっちゃ焦りました。さーっと血の気が引く感じ。

突然動作が変わる原因として、広告配信かファイル関連くらいしか思いつかなくて、私が使用している広告 admob について現在なにか起こっていないか、ネットでずっと調べてました。admob の表示には cordova プライグインの cordova-admob-pro を使っているので、これについても調べたのですが、それらしい情報はどこにもなく、admob への問い合わせ先も見つからない。

で、デバッグ開始です。
実機での起動時の動作確認のため、ちょっとめんどいけど仕方なし。
まず、ソースを変更せず(アプリ名だけ変更)デバッグビルドで構築して実機にインストールし、現象が再現するかを確認。
うん、再現します。間違いなく。
この時点でファイルなしでも発生することが確認できました。
また、広告をテスト広告に変更しても同様に発生しました。
次に、ブレークポイントは貼れないのでコンソール文とアラート関数を埋め込み、ビルド・インストールし動作確認。
これを繰り返してやっとのことで発生個所を特定しました。

/*** test 2016/11/02 ***/
window.alert("init_ad in");
  if(window.AdMob) AdMob.prepareInterstitial({
                     adId: admobid.interstitial,
//                     isTesting: true,
                     autoShow: false
                   });
window.alert("init_ad out");  // 上記の alert 表示後の
                              // この alert 表示が異常に遅い!

上記のインタースティシャル広告作成関数でプログラムがしばらく止まるんです
この関数自体は非同期関数のようにすぐに返ってくるはずなんですが、この日このとき、なぜかすぐに返ってこない。

で、特定はできたけどこれからどうしようと考えながらいっぷくしようと Smoking Note を立ち上げたら …
なおってる!
なんかしらないけど、普通に起動しました!
このとき、午後 18:16 。
まるで夢のような出来事でした。
こうゆうケースが現実にありましたということで、ご参考まで。

Meditation Noteアップデート作業中

現在、瞑想アプリ「Meditation Note」のアップデート作業を行っています。このアプリは私が初めて作成したアプリで、これまでにほとんどダウンロードされていないのですが、思い入れがとても強いアプリです。瞑想関連のアプリはすでにたくさんありますし、現在も新しいタイプのアプリがリリースされ続けているので、PLAYストアで「瞑想」で検索しても表示すらされない状態です。それでも、もともと「自分で使いたい」という想いで作った記念すべき初アプリなので、少しでもいいものにしたいと思いアップデートすることにしました。

まず、今回グラフを追加しようと思い、ソースを調べました。2作目、3作目のアプリでグラフを使ったことがあるので今回は楽かなと思っていたのですが、ソースを見て固まってしまいました。

… グラフに必要なデータである日付と時間が一つの文字列になってる …

// 日本語版
record: {
  date: "2016/10/31(月) 09:00",
  ...
}

// 英語版
record: {
  date: "Mon. Oct.27, 2016, 09:00 am",
  ...
}

作成当初グラフ化なんて考えてもいなかった(そんな余裕がなかった)からか「日付は表示するだけだから」と文字列にしてしまいました。グラフは、横軸を日付、縦軸を累積時間や回数にしようと思っているので、これを、

record: {
  date: {
    y: 2016,
    m: 9,
    d: 31,
    w: 0,
    s: {
      h: 9,
      m: 0
    }
  },
  ...
}

のような構造にして、同じ月にあたるレコードの時間と個数を集計できる形にしないと。

元の文字列から値を取り出す方法としてまず思いつくのが slice()などを使う方法。文字列の先頭から年にあたる4文字を取り出し、そこから一つ飛ばして、月にあたる2文字を取り出し、さらに、、、って、できないことはないんですけど、なんかイヤな感じが。文字列のインデックスを指定しなくちゃいけないので、ソースコードがごちゃごちゃしちゃうなと。で、悩んだ挙句、正規表現を使うことにしました。前に使ったことはあったのですが、ものの見事にすっかり忘れていて、本読みました。
ソースはこんな感じになりました。

result = date.match(/[^/() :.,]+/g);
if (mdt.lang_jp) {
  // "2016/10/27(木) 9:00"
  // [0]/[1]/[2]([3]) [4]:[5]
  record.date.y = Number(result[0]);
  record.date.m = Number(result[1]);
  record.date.d = Number(result[2]);
  record.date.w = Number(WEEK[result[3]]);
  record.date.s.h = Number(result[4]);
  record.date.s.m = Number(result[5]);
} else {
  // "Thu. Oct.27, 2016, 9:00 am"
  // [0]. [1].[2], [3], [4]:[5] [6]
  record.date.y = Number(result[3]);
  record.date.m = Number(MONTH[result[1]]);
  record.date.d = Number(result[2]);
  record.date.w = Number(WEEK[result[0]]);
  record.date.s.h = Number(result[4]) + ((result[6] === "pm") ? 12 : 0);
  record.date.s.m = Number(result[5]);
}

正規表現で「/」、「(」、「)」、「 」、「:」、「.」、「,」以外にマッチするパターンを見つけて配列に格納します。この抽出処理がたった一行で済むので、かなり便利です。
正規表現を使うことで複雑な処理を簡潔に記述するということは、些細なことのようでけっこう重要な気がします。なんとか使いこなせるようになりたいです。