前回のエントリでは、Cordovaの開発環境を整えました。これで早速コーディングが出来ます。今回のエントリでは、実際のコーディング・・・ではなく、メインの部分を作る以外の部分で、Cordovaアプリ制作上のノウハウを集めてみました。色々と嵌まるポイントや制限事項などもあるので、作る前にこれらのノウハウを事前に知っておくと、無駄に頭をショートさせなくて済むのではないかと思います。

ちなみに、Cordovaのバージョンは6.4.0で確認をしています。主にconfig.xmlの設定法やライブラリの利用によるGUIの設定関係についてここではまとめています。

目次

アプリ周りの整備(config.xml)

config.xmlでアプリの基本的な設定を施すことが可能です。しかし、このconfig.xmlですが、AndroidとiOSとで使える項目とそうでない項目があったりします。ですので、1ソースで全部に対応というのが難しい点です。config.xmlのみビルド時に差し替えるように、複数用意しておくと良いでしょう。

アイコンを変更する

アイコン変更でウェブを探索してみると、新旧含めて様々な情報が出てきますが、どれを試しても変更出来ませんでした。というか、公式ドキュメントに書かれてる通りに変更しても変わらない・・・(公式ドキュメントの読みにくい日本語機械翻訳は辞めて欲しいですね)。config.xmlファイルがプロジェクト直下にあるので、ここに設定を書けば反映するというのが、変更方法としてウェブにはあるのですが、どうも、オカシイ。こちらのサイトを参考にさせていただきました。

ということで改めて調べてみました。

  1. プロジェクト直下のconfig.xmlがあるディレクトリにresというフォルダを作成する
  2. 大きな背景色が透明のPNG画像を用意する(今回は512×512のサイズの画像を用意しました)
  3. こちらのサイトで2.で用意したpng画像をchoose fileをクリックしてアップロード
  4. しばらく待つと幾つかの大きさに変換された画像が出て来る。Androidをクリックする
  5. MDPI〜XXXDPIまでの5種類が生成されてるので、それぞれ、mdpi.png〜xxxdpi.pngとして保存する。ldpiサイズ(36×36が無いのでそこだけ、GIMPでも使ってリサイズして用意しておく)
  6. 5.で保存したpngファイル達を1.のresフォルダ内にコピーする
  7. config.xmlを開いて以下のコードをplatform name=”android”のセクション内に追加する

さて、ウェブにある情報によると、これで後はbuildなりrunすればOKみたいな書き方なので、実際にやってみたら、変わっていませんでした・・・。そこでresフォルダ内を見てみるとmipmap-hdpiなどのフォルダと共に、中にicon.pngという名称でアイコンが入っていました。これらのフォルダ毎、platforms/android/resのフォルダ内に上書きコピーしてみました。

そして、改めてcordova run androidコマンドを実行してみると、アイコンが変更されていました。

図:なぜかresフォルダ内に生成されたフォルダ群

図:キノコのアイコンが作ったアプリです。

スプラッシュスクリーンを追加する

あってもなくても良いのですが、昔からプログラムの起動時に表示するものの1つとしてスプラッシュスクリーンがあります。Microsoft Excelだとか、スマフォのアプリだとAmazonなどの起動時に出るあのロゴマークとバージョン表記のようなものです。元々は起動するまでの間の作業中を意味するものとして、ユーザに状態をお知らせする為のものだったのですが、スマフォでも使われてるものはたくさんあります。

このスプラッシュスクリーンなのですが、起動時の一瞬だけなのに、設定とそのための画像ファイルの用意がアイコン同様面倒です。なので、それほど起動に時間を要するわけじゃないアプリならば、別段装備しなくても良いものです。それでも用意したい場合には、プラグインを導入する必要性があります。画像の用意についてはAndroid Studio付属のdraw9patch toolを使うのが普通のようですが、面倒なので今回はSimple Nine-patch Generatorを利用させていただきました。9patch画像の仕組みや得手不得手は9patch入門というサイトが非常にまとまっています。

9patch画像の用意

すでに用意してる人は問題ないのですが、今回自分は以下の手順で該当の9patch画像を用意しました。9patch画像とはpng画像を9つのマスに分割して、分割点より外側をデバイスの解像度に合わせて伸縮するよう指定した特別な画像です。別にこの画像でなくても良いのですが、様々なデバイスに対応させる為にこのような面倒なフォーマットを使う事シーンがこのスプラッシュスクリーンです。

画像はいらすとやさんの生ハムメロンの画像を使いました。但しこのイラストの大きさではちょっと大きすぎます。また、アプリの名前も入れたいので以下のサイズになるように、生ハムメロンの画像とアプリ名を入れることにしました。使用したアプリケーションはLibreOffice DrawとGIMPです。Libredraw上で縮小した画像とアプリ名を追加してコピーし、GIMPにて300×300の空のキャンバスに貼り付けただけのシロモノです。png形式でエクスポートしておきます(splash.pngとしました)。

これで元になるsplash.pngが出来たので、Simple Nine-patch Generatorにて画像を変換します。select imageボタンを押してsplash.pngを指定したら開始です。今回は何も考えず、画像と文字がスケールしないようにそこだけ指定しました。この時、source densityはxxxhdpiを選択しておきます。そして、Download.zipをクリックすると5種類の画像に変換されたものがダウンロード出来ます。 ldpiは無いのですが必要ならば自分でそのサイズのものを作る必要があります。

図:簡単に9patchイメージが作れるスグレモノ

さて、downloadしたzipを解答するとすでにresというフォルダ内にさらに細かく分類した形で画像が入っていますが、各DPIのファイルを縦横用の名前を付けて、プロジェクト直下のresフォルダに入れます。これでとりあえず、スプラッシュ用画像の準備は完了です。次のセクションでは、これらの画像をconfig.xmlでそれぞれ指定する記述を追加します。

図:縦横合計10枚のsplashを用意した。

プラグイン導入と設定

まずは、プラグインを導入します。ターミナルを起動しプロジェクトまで移動したら以下のコマンドを入力します。

次にconfig.xmlへ以下のコードを追加します。ちなみに、作成した画像類はプロジェクト直下につくったresというフォルダに格納しています。それぞれファイル名は横用が例:splash-land-ldpi.9.png、縦用がsplash-port-ldpi.9.pngという形で配置しています。

1行目はスプラッシュ画面をアスペクト比に基づき修正してくれる設定です。2行目はスプラッシュの起動時間です。ms単位で設定しますが小さすぎると表示されなくなりますので注意。5000を指定したので、5秒間表示されます。他にも

という設定があるのですが、これは最初の1回だけで次回以降スプラッシュを起動しないという設定なので、普段は使いません。さて、resに配置した画像を使うようにする設定をさらにconfig.xmlへ追加します。

platformセクションがすでにあるならばその中に追加する形で記述しましょう。さっそく、cordova run androidを実行してみました。しかし、アイコンの時のように失敗しました。resフォルダ内に画像を収めたdrawable-land-hdpiといったフォルダと画像が生成されたのですが、cordova標準のスプラッシュが表示。ということで、これら生成されたフォルダ類をplatforms/android/resのほうのフォルダの中に移動させました。改めて、cordova run androidで実機テストをすると表示されました。

図:見事な失敗。画像が収まらなかった

というわけで、表示はされましたが、失敗ですね。適当につくるとこんなもんです。なので、画像は300×300よりもう少し小さく、且つ画像周りの余白ももう少しツールで変換する時に取っておけばよかったと思います。しかし、これでスプラッシュが完成しました。

外部サイトへ接続

アプリから外部サイトへの接続は、例えば内部ブラウザで外部サイトを表示させたりする事例を思い浮かべますが、それだけではなく、jQueryのgetJSONメソッドやREST APIにスクリプト内からアクセスする場合でも、用いられています。Cordovaではこれらをセキュリティ上の理由から特定のサイトにのみ接続可とする事ができます。デフォルトでは、全サイトにフルアクセス可能になっています。

config.xmlの中にあるaccess originと呼ばれる項目や、allow-navigation、allow-intent hrefと呼ばれる項目がそれで、ワイルドカードを使った制御や複数のサイトの接続許可を設定する事が可能です。

上記の設定にする事で、http、https接続に於いてgoogleのサービスにだけ接続許可という形になります。同じ構文を複数行書けば、それらについて許可するという形になります。これらはホワイトリストと呼ばれ、cordova-plugin-whitelistというプラグインで実現されています(6.4.0ではデフォルトで入っています)。

バックグラウンド処理について

CordovaのAndroidアプリ専用の設定です。

この設定はアプリがバックグラウンドになった状態(他のアプリが全面に出てる状態)の場合にどうするか?という設定です。デフォルトではTrueの設定になっているので、例えばアプリで何かを継続的に動作させてるようなケースの場合、そのままだとバックグラウンドになってもずっと動作し続けます。音楽や動画ならともかく、定期的にデータを取りに行くような処理をJavaScriptでやらせていた場合、ユーザは走ってる事に気が付きません。

よって、よほど必要性がないのであれば、設定はfalseにすべきです。以下の設定をconfig.xmlに追加すればOK。

スクリーンの向きを固定する

アプリによっては、デバイスの向きによって自動回転したりするものもあれば、縦固定や横固定のものがあります。これらはプログラムの仕様上の理由でそうなっているのですが、Cordovaでもその設定を追加する事が可能です。ですが、最近のアプリというかユーザの使用方法として横にすることはあまり好まれないようです。よって、使うとしても、縦固定などだけになるでしょう。デフォルトではデバイスの向きで回転するようになっています。

デフォルトでは記述自体がないので、回転した向きによって変わるようになってるので、自動回転に戻したい場合には、この記述を削除すればOKです。

ライブラリの利用について

CordovaはHTML5アプリケーションが作れると言っても、そのままでは素のHTMLとCSSでゴリゴリと書くことになってしまいます。しかし、実際にはjQueryなどのライブラリ等を利用することで、モバイルのGUIを実現するのが当たり前ですので、これらを使えるようにして置かなければなりません。また、今時のスマフォ特有のUIの実現方法は、Cordova特有のものではないので、ライブラリでいかに実現するか?という事になります。

jQuery Mobile等を使えるようにする

jQuery等のJavaScriptライブラリは、GoogleもCDNとしてホスティングしていますので、Cordovaで利用する時には、URLで指定すれば特にプロジェクトに含めなくとも利用する事が出来ます。この場合、そのスマートフォン端末はネットに接続出来てる状況でなければなりません。つまり、オフラインでは使えないという事です。CDNで用意されてるjQuery Mobileを使えるようにするには、index.htmlの<head>セクション内に以下のコードを追加します。

しかし、アプリは必ずしもネット接続状態で使うものとは限りません。計算機なのにオフラインだと使えないというのも不便な話です。ですので、これらのJavaScriptファイルおよびCSSファイルをプロジェクトに含めてしまうのが良いでしょう。但し、jQueryは1.x系や2.x系、最近では3.x系などもあり、自分が利用するjQueryプラグインのバージョンに合わせたものをダウンロードしましょう。新しければ良いというものでもありません。通常は、1.12.xのバージョンをダウンロードします。

  1. 対象のプロジェクト内のwwwフォルダを開く
  2. jQueryのサイトから、必要なバージョンのjsファイルとして保存しましょう
  3. jQuery Mobileのサイトから、jQuery Mobileのjsとcssファイルの二種類をダウンロードします。
  4. jsファイルは、1.のjsフォルダ内に。cssファイルは1.のcssフォルダ内に入れます。
  5. index.htmlには以下のようなコードを追加する

これで、心置きなくindex.html内で普通にjQueryとjQuery MobileのUIライブラリ類が使えます。jQueryプラグイン類も同様の手順です。

ヘッダーと固定方法

ヘッダーとはアプリの一番上にあるバーで、通常スクロールさせても動かない固定されたメニュー等がある場所です。HTML5アプリの場合この部分も全てHTMLであるため、そのままでは、アプリをスクロールすると、ヘッダまで上のほうに移動してしまいます。そこでこれを固定化してあげる必要があります。以下のようなスタイルのアプリで、idがtopmanという部分を固定化させます。

以下のCSSをheadセクションに追加してあげます。

ポイントは、

  1. topmanのpositionはfixedにする
  2. topおよびleftを0で設定する
  3. もちろん幅は100%で指定する
  4. contents部分はtopの高さ40pxが指定されてるので、その分だけ上にmargin-topに40pxを指定する
  5. z-indexを999に指定して、最前面とする。これをしないと、スクロール時にボタン類や画像がヘッダの上に被さってしまう。
  6. overflow:hiddenをtopmanとcontentsの両方に指定。これをしないと、リンク類がクリックできなくなる。

これで固定化出来ました。固定された領域内にボタン類や検索窓、サイドバーのボタン等を設置する事になります。また、これでアプリをスクロールしても、ヘッダ部分は常に固定表示されますので、メニューにアクセスすることが出来ます。

図:スクロールさせてもバッチリ表示

フッターのボタン類の実現

ヘッダーが固定出来ると次に欲してくるのが、フッター部分。多くのアプリでも、ここはメインの機能へアクセスする為のボタン類などが配置されてる事が多いでしょう。そこでここも固定化し、ボタン類を配置して見たいと思います。また、通常はdivboxなどを使って、綺麗な配置をするべき所ですが今回は、今まで配置していたボタン類を、jQuery Mobileのグリッド機能で配置してみたいと思います。

まずは、footer用のCSSをheadセクションに追加します。

これで、アプリの最下部に50px分の領域が固定化されました。スクロールせずとも初めからフッター部分は表示され、スクロールしても固定表示されたままになります。次に、既存のボタン類はjQuery Mobileのグリッド機能を利用してfooter部分に配置します。といっても、クラス指定した<div>の中に格納するだけで実現可能です。最大5個まで横並びで配置が可能です。

ポイントは、

  1. ui-grid-bクラスの指定をすると3個分の均等配列をしてくれます。
  2. ui-block-aクラスが1個目のグリッド、ui-block-cクラスが3個目のグリッドになります。でも、Divboxでデザインを作ったほうがキレイだと思います。
  3. ボタン類には、ui-btn ui-corner-allクラスを付けて起きます。

これでボタン類がフッターセクションに固定化されました。自分は今後、divboxでデザインを組み、div自体にリンクを貼るようにしてここにメニューを作りたいと思っています。

図:ダサいけれど、サマになってきました。

イベント処理

スマートフォンにはPCのアプリとは全く異なる様々なイベントがあります。通知関係やらタッチパネルでの操作、他のアプリとの連携などなど。このセクションでは、何かをしたら何かが起きるというイベント処理に関してまとめてみました。他にもあるかとは思いますが、主にメジャーに利用する地味にな裏方役みたいな機能が中心です。プラグインを利用した派手なアクション等に関しては、また別の機会にまとめようと思います(例えば、Dropbox連携などはやってみたい)。

タッチパネルのイベント

HTML5アプリケーションに取って欠かすことの出来ない機能が、タッチイベント。様々なタッチイベントを取得してプログラムの動作を行わせるのは、アプリケーションで最も重要なアクションです。CordovaもHTML5アプリケーションである以上、このイベントの処理は重要な要素です。マウスのクリックイベント等と基本的には同じ仕組みなので、難易度は高くありません。但し、1つの領域に複数のイベントを設定すると、判定させるための処理が複雑になるので、複数のイベントを設置しすぎない事がポイントです。

今回はDIVタグで作った四角いエリア内でタッチパネルイベントを取得して処理を行わせてみました。以下のHTMLコードとCSSはタッチパネル捕捉用のDIVタグとその装飾部分となります。

シングルタップイベント

これからこのidがtouchmanというdivタグエリアに対して、jQueryにてイベント設定を行います。まずは、シングルタップ。単純に該当エリアをタッチした場合のイベント処理です。

ポイントは以下の通り

  1. boxに値を取得する場合、配列の0番目という形でないと取得出来ません
  2. シングルタップのイベントは「touchstart」です。返り値はtouchHandlerで取得します。

図:タッチした時の反応

ダブルタップイベント

ダブルタップイベントはマウスのダブルクリックのようなものですが、1つの領域に複数のイベントを設定している場合、そのままでは先にシングルタップのイベントが発動してしまいます。そこでタイムアウト設定を加えてタイムアウトするまでの間にシングルタップされたのか?ダブルタップされたのかを判定する仕組みを入れる事で、2つをきちんと区別する事が出来ます。

ポイントは、

  1. グローバル変数にタップフラグ用の変数とタップ判定用のインターバル時間用の変数と初期値を入れておく
  2. タップ後にtapIntervalの値分だけ時間を待ち、さらにその間にタップされた場合にはダブルタップの処理とするよう処理を分岐しています。
  3. e.preventDefault();はiOSにおいて画面の揺れを防ぐ為のコードです。

ロングタップイベント

ロングタップとは、いわゆる長押しイベントのことです。特定の要素を一定時間以上押し続けた時に発動するイベントで、通常のタップイベントと判定分岐させて使うケースが多いイベント処理です。処理自体はダブルタップの時の処理に近い処理を記述します。

ポイントは、

  1. ロングタップ判定はコードの一番最期に配置しておくこと
  2. シングルタップの処理は終わったらreturnで終わらせてしまうこと。
  3. タイムアウトクリア用のclearFunctionをそれぞれのタップイベントの最初に実行すること。
  4. tapIntervalの値は少し長めに。今回は700msを指定しました。

実装しようとして結構嵌ったポイントです。ロングタップだけで実装するということはあまりなく、通常はシングルタップと共に実装するので、このようなフラグ処理と処理する順番、returnで終わらせてしまう処理などを入れてあげなければなりません。

フリックイベント

左右に画面をスライドさせる動作がフリックですが、このイベントを装備するためには、2つのイベントハンドラーが必要です。フリックを必要とするイベントに他のタッチイベントを加えると動作判定が複雑になるので、注意が必要です。

ポイントは、

  1. touchmoveとtouchendの2つのイベントハンドラーを追加します。
  2. タッチ中イベントはdiv内に文字列をinnertHTMLで表示しています。
  3. touchstartで始まり、touchmoveで動作中を取得、touchendでタッチの完了を取得するという手順になります。
  4. 返り値のeのtypeというプロパティからどんなイベントが発動したのかを取得出来ます。それをswitch文で分岐しています。
  5. このコードだけでは、左も右もどちらも1つのフリックとして処理されてしまいます。

QUO.jsを利用する

これまでのコードを見てもわかるように、素のJavaScriptで用意されてるタッチイベントで、イベントを取得したり判定させたりと言うのは結構大変です。マウス向けのClickイベント等(onDblClick等々)も使えるのですが、反応がワンテンポ遅いので通常、スマフォ向けのUIでは利用しません。そこで、これらHTML5に於ける、タッチパネルの様々なイベントを簡単に扱えるようにしてくれるのが、このQUO.jsです。

他にもHammer.jsTouchyjsなどもあるのですが、メジャーどころということで今回はこれを使ってみたいと思います。まずは、GithubよりClone or DownloadでZIPでダウンロード。解凍後に入ってるquo.jsというファイルをCordovaプロジェクト内のwww内にあるjsフォルダにコピーします。そして、inde.htmlのheadセクションに以下の1文を追加します。

QUO.jsが対応してる様々なタッチイベント等は以下のようなものです。ほぼメジャーなタッチイベント系を簡単に取得が出来るので、Cordovaアプリでも導入したい一品だと思います。

  • タッチ、タップ、ダブルタップ、ロングタップなどのタップ系イベント
  • マルチタッチジェスチャ(2フィンガータッチ)
  • 上下左右のスワイプジェスチャ
  • 2本指を使ったドラッグ、回転、ピンチ等

構文はjQueryっぽい構文ですが、jQueryプラグインではありません。また、jQueryとのバッティングを防ぐ為に、$$(“#touchman”)のように$を2つ記述するスタイルになっています。なぜか、最新のv3.0.7だとうまく動かせなかったので、v2.2.0をGithubのアーカイブから拾ってきました。

上記のスクリプトを記述し、idがtouchmanのDIVに2つイベントを登録してみました。これだけの構文で、長押しとダブルタップの2つのイベントを簡単に取得が可能です。素のJavaScriptよりも格段にコードの可読性が向上し、煩雑さがなくなりました。素のJavaScriptの場合、最初にキャッチすべきイベントの順番を考えないといけないので、これはありがたいです(ちなみに、素のJavaScriptの場合、touchstart > touchmove > touchendの順でフラグを活用しないとこれは実現できません)。

図:ロングタップしてみた。

ダイアログの表示

CordovaではHTML標準のalert関数が使えるので、特に何もせずともメッセージダイアログが出せます。しかし、ネイティブのダイアログではないので、ちょっとデザイン的にアレな所があったりします。そこで、ネイティブのダイアログを呼び出すことの出来るcordova-plugin-dialogsというプラグインがあります。導入するにはターミナルを起動し、プロジェクトのフォルダまで移動してから以下のコマンドを入力する必要性があります。

主に三種類のダイアログを呼び出す事が可能です。

ごく普通のダイアログ(alert)

いわゆる「OK」ボタンがあるだけの通知するダイアログです。以下のスクリプトで呼び出せます。

閉じた後に実行する関数とは、まさにダイアログのボタンを押して閉じた後に実行する関数です。通常使用する場合には以下のような事例になります。

startmanという関数内でダイアログを呼び出しています。この関数を例えばボタンに割り当てて実行すると、ダイアログが表示されて、最期にafterburner関数が発火して、コンソールログにログが残るわけです。

図:朝の挨拶ダイアログが出現

図:本心はconsole.logに出てきます。

確認用ダイアログ(confirm)

いわゆる「はい」「いいえ」の選択式ダイアログで、Androidでは最大3個までボタンを指定が可能です。また、「はい」の場合の処理と「いいえ」の場合の処理をそれぞれ用意しておく必要性があります。以下のような事例で使用します。

ポイントは以下の通り。swtich文などでbuttonIndexの値を元に処理を分岐させましょう。

  1. 押したボタンの返り値は何個目のボタンなのかの番号が返ってくる
  2. ダイアログ外をタップするとダイアログが閉じるが、その場合は0が返ってくる

図:確認ダイアログはとても重要

入力ダイアログ(prompt)

ただメッセージを表示するのではなく、ユーザに問に対して入力を求めるインプットダイアログです。その為、確認ダイアログの返り値に加えて、ユーザの入力内容も取得出来るので、それらを考慮した分岐を作ってあげる必要があります。promptには、これまでのメソッドの内容に加えて、デフォルトの入力値を表示する項目があります(下記のコードの「はまち」がソレ)。

入力値を受取表示する仕組みですが、更に入力内容がおかしいかどうかのチェックなども付け加えると尚良いでしょう。

図:入力を促し、返り値をalertで表示してる様子

ビープ音を鳴らす(beep)

これはダイアログの表示にともなって使う構文で、以下の1文だけです。音源は指定できないみたい。

2と入ってる部分は鳴らす回数。Androidの標準の通知音が出るようです。HTML5のサウンドを鳴らす仕組みのほうが便利だとは思います。

Push通知機能

スマフォではメール等ではおなじみの「Push通知機能」です。メールが届いてるよ!というお知らせと共に、通知領域にその内容が表示されるわけですが、これは通常サーバが必要となります。そのサーバですが、Google Cloud Messaging for Androidを利用したり、AppleのApple Push Notification Service、NiftyのmBaaSサービスなどが利用されてるようです。

今回はGoogle Firebase NotificationとGoogle Apps Scriptを利用して通知メッセージを送り、cordova-plugin-fcmというプラグインを利用して、通知機能を実現してみたいと思います。尚、今回のこの機能は結構構築に手間が掛かります。よって通知を配信するGoogle Apps Script + Firebase Notificationについては別記事に独立させました。この項目では、その記事で入手するgoogle-services.jsonが必要になるのでその記事も参照して下さい。

さて、Cordova側なのですが、この機能を利用する為にはプラグインが必要なので、まずはそれをターミナルからインストールします。該当のプロジェクトのフォルダまで移動したら以下のコマンドを入力します。

今回は配信にFirebase Notificationを利用するので、別記事にあるようにそこでプロジェクトを作成し、google-services.jsonを入手します。また、サーバーキーを入手したら、Google Apps Script側でFirebase Notificationに通知をするコードを記述し、準備を終えておきます。ここでは、google-services.jsonのファイルを処理するのですが、

  1. 該当のプロジェクトのフォルダを開く
  2. platforms¥androidのフォルダを開き、その中にgoogle -services.jsonファイルを入れる

これでファイルの処理はOK。次にindex.jsへコードを記述します。devicereadyイベントの後でないと動作しないので、書く場所に注意。自分は、onDeviceReady()以下に記述をしました。まずは通知が送れるかどうかをチェックする為の準備です。事前にheadセクションにてcordova.jsは読み込んでないと動作しませんので注意。

まずはこの状態でcordova run androidで実機に送り込みます。そしてChrome Debuggerでリモートデバッグしてみると、consoleに何やら長い文字列が出ているはずです。これがテストで利用する、その機器のTokenです。この文字列をコピーして取っておきます。

送り方等は別記事に全て記述してあります。その際、アプリ側には以下のコードに書き換えて、再度cordova run androidでアプリを送り込む必要があります。上記のTokenを取得するコードは消してしまいます。

さて、コードを記述して送り込んだら、一旦アプリはバックグラウンドにしておきます。この状態で、コピーしておいたTokenを使って、Firebase Consoleで特定の機器としてそのTokenを指定してメッセージを送ってみて下さい。無事に届いたら成功です(通知とアプリ側ではalertが表示されます)。しかし、Notificationというのは特定の個人にだけ送るものではないので、このまま使いません。ここでポイントになるのが、上記のコードのFCMPlugin.subscribeToTopic(‘/topics/calcman’);の1行。Firbase側に「このトピックは受信するよ」ってお知らせしてるコードです。

これで運営者側はこのトピックに送れば、Tokenなど使わずTopic受信者全員にPush配信が可能になります。

図:スリープ復帰画面と通知領域に来た内容

ローカル通知機能

ローカル通知機能とは、サーバを必要とせずアプリから単体で通知領域に通知を出す機能です。例えば、音楽プレーヤーであれば「○○を再生中」だとか、キッチンタイマーであれば「時間が来たよ」とダイアログではなく通知でお知らせする機能です。Pushのように運営者から送りつけるものではありません。

この機能を利用するには、cordova-plugin-local-notificationsプラグインを導入します。ターミナルを起動し、該当のプロジェクトまで移動したら以下のコマンドを入力します。

さて、このプラグインはdevicereadyイベントの後でないと動作しないので、書く場所に気をつけて下さい。大きな機能は、速攻通知と予約通知の2つです。使う上で注意しなければならない点があるので、そこも抑えましょう。また、この通知はアプリ側からイベントがある度に呼ぶものなので、関数にしておいて呼び出すほうが便利だと思います。ですので、index.html内にスクリプトを記述しています。

速攻で通知する場合

ポイントがいくつかあります。

  1. soundではwww直下にmp3ファイルを入れています(file://はwwwの直下がルートになります)。(soundsフォルダを作って入れようとしたら、Buildで失敗しました)。フォルダを作ること自体は問題ないようですが、file://sounds/crank.mp3とするとダメのようです。iconも同様です。
  2. file://やres://でAppに含めたファイルを指定できますが、res://の場合、platforms/android/res/drawable/がルートになるようです。res://icon.pngでdrawable直下のicon.pngとなります。こちらは正しく画像も音声も指定出来たので、file://での指定ではなく、res://で指定のほうがよさそうです。
  3. iconではオンライン上のpng画像を指定。サイズは32×32で作りました。
  4. idなのですが、通知する度にidの値は変更しないと、1回目の通知の後の2回目以降の通知が表示されなくなってしまいます。ですので、変数にしておいて、通知する度に増やしてあげなければならないので、グローバルに変数を取り、notificationを発行する度にidを増やすようにしました。
  5. 今回はbuttonタグにこの関数を実行するように仕組んでみました。
  6. data以下にcatなんてつけてますが、通知が来た時にレスポンスデータに含めてくれます。これを元にAlertを出したり、通知が出たら、dataの値を元に別のアクションを実行するなんてことが可能です。
  7. Push通知するプラグインは、アプリがフォアグラウンドにあると通知してくれないので、通知をこれで受け取って表示してあげるなんてのも手です。

図:ボタンを押すと「起動したよ」という通知が出る

予約通知

ポイントがいくつかあります。

  1. atという項目が増えて、時間指定しています。tomorrow_at_1_15_amなので、明日の午前1時15分という指定になります。
  2. every: 30という指定にすると、30秒毎という指定になります。
  3. firstAt: tomorrow_at_8_am,という指定にすると、毎朝午前8時にという指定になります。その場合、every: “day”の指定も必要です。yearやmonthなんて指定もあります。

予約通知のキャンセル・アップデート

また、予約した通知をキャンセルしたり変更する場合には以下のメソッドを使います。この時、予約時のIDが重要になります。

上記のコードでnidに指定したIDの予約をキャンセルします。nidの部分には[1,2]といったような配列も指定出来ます。

上記のコードで予約してある通知をすべてキャンセルします。

上記のコードで予約済みのIDが10の通知の内容をアップデートしています。

アイコンのバッジ

iOSの場合にはApache CordvaによるPush通知の実装 iOS版の記事によると、いわゆる通知の一種であるバッジが装備出来るようなのですが、Androidはバッジの表示は、ホームアプリ(例えばGoogle Nowランチャーだったり、GoランチャーEXだったり色々ある)に依存してるようで、仕様が統一されてるわけじゃないようです。そのため、実装は出来るが動くかどうかは使ってるランチャーに対応してるかどうかという事になるみたい。ShortcutBadger Check Toolにてバッジ表示テストが出来るならば、対応してるということのようです。shortcutbadgerの情報はこちらかどうぞ。

※Androidエミュレータでは動作しませんでした。

※ZenfoneでもランチャーがGoogle Nowだと対応していませんでした。

自分のスマートフォンはZenfone3で標準搭載のZenUI Lancherというものですが、対応していたので、対応させてみました。この機能を実装するにはまず、プラグインを導入しなければなりません。ターミナルを起動し、該当のプロジェクトまで移動したら以下のコマンドを入力。cordova-plugin-badgeというものを導入します。

これで終わりというわけではありません。プロジェクトに付属のindex.jsというファイルがjsフォルダに入ってるので、これを編集します。index.htmlではこのjsファイルを読み込むようにheadセクションに記述を忘れないように。

このプラグインは、document.addEventListenerのdevicereadyイベントの後でないと動作しないので、書く場所に注意。上記のreceivedEventは36行目付近に記述されていますが、cordova.plugins.notification.badge.set(10)で10というバッジが表示されるようになります。これらを例えば通知イベントの後にセットしてみたり、他のメソッドを使って、増加や減少、document.addEventListenerのpauseイベントの時に発動させるなど、色々出来ると思います。

図:自分のスマフォはOKでした。

内部ブラウザの装備

スマートフォンで他のアプリからリンクをクリックした時にChromeアプリやSafariなどが起動するのではなく、アプリ内でブラウザを開くシーンがあると思います。アプリの内部で別にブラウザを立ち上げてるわけですが、アレを実現する機能です。Cordova自体がブラウザなのでそちらで開いても良いのですが、その場合アプリに戻れないのが不便なのと、戻るボタン等を使用するAndroidの流儀からしたら、使いにくい挙動になってしまうので必須とも言える機能です。

また、今回、Google Apps Script側でモバイルアプリ画面を実装するつもりなので、Cordova側でOAuth2.0認証やらの機能を実装するのが面倒ということもあって、導入しています。この機能を利用するためには、プラグインを導入しなければなりません。ターミナルを開き、プロジェクトのフォルダまで移動したら以下のコマンドを入力します。

設定等は特にありません。後は、index.htmlにボタンなりリンクを貼ってタップした時に開かせるだけですが、その時の開かせ方がポイントです。今回はリンクに関数を指定して、開かせる方法を取っています。

openWindowという関数を用意して、リンクをクリックすると実行する仕組みです。URLはGAS側で用意したページを指定しています。window.openで開くのですが、ここで注意点です。1つ目の引数は対象のURLですが、2つ目の_blankで内部ブラウザで開きます。_systemだと外部ブラウザなのでChromeなどが立ち上がる事になります。_selfだとCordovaでそのURLを開きますが、ホワイトリストの制限を受け、またアプリの画面に戻れません。

3つ目はオプション事項をいくつか指定する場所なのですが、今回はlocationというオプションでyesを指定しています。これは、内部ブラウザのURL欄や戻るボタン類を表示するかという設定になります。ただ無くてもAndroidの戻るボタンで戻れるので、noでもOKです。その他オプション項目はこちらのサイトを参考にしてみてください。

今回はGASで作成したページを表示してるので、最初の一回ログインを求められますし、承認を要求してきますが二回目以降は求めてきません。この辺りをCordovaで実装するのは非常に面倒なのと、アプリのメイン部分をGAS側に切り離せるのはメリットの1つなので、今後これでGAS側にjQuery Mobileを用いてUIを作ってみようと思っています。

図:内部ブラウザで表示中の様子

カスタムURLスキームへの対応

カスタムURLスキームとは、他のアプリケーション等から特定のアプリケーションを起動して、パラメータを渡す仕組みです。普通のリンクのような書式で、「kinoko://」みたいな文字列から始まるもので、その後に続く値を渡して、処理をさせるスマフォならではの仕組みです(iTunesなどでも採用されていますが)。メール等にこれらリンクを貼り付けて送り、使用者はリンクをクリックするだけで、例えば該当の番号のレコードの情報を一発でアプリで開けるといった具合になります。

この機能を実現するには、以下の作業をします。まずは、プラグインを導入します。ターミナルを起動し、該当のプロジェクトまで移動したら、以下のコマンドを入力。インストールは数秒で完了します。今回はkinokoというスキームを作るので、それを指定しています。

これで終わりというわけではありません。以下の作業をします。

  1. config.xmlへ<allow-intent href=”kinoko:*” />という設定を追加する。これで他のアプリから呼び出せます
  2. index.htmlへ受け取る為の関数を追記する(handleOpenURLという名前で作成)

次に受け取る為の関数をscriptセクションに追記します。cordova.jsは事前にheadに書いておきましょう。

続いて、テストをしてみます。

  1. cordova run androidでテスト実行。但し起動したアプリは一旦閉じておく。
  2. Android端末にQRコードリーダーアプリを入れる
  3. URL Scheme Test Toolにて自分で作ったカスタムURLスキーマと文字列を足して、QRコードを生成する。今回は、「kinoko://testman」として作りました。
  4. 2.のQRコードリーダでそのURLを読み取らせる
  5. 無事にアプリが起動して、文字列がalert表示されたら成功。
  6. あとはこの関数をカスタマイズして、パラメータを分解して受け取るような仕組みにすると、複数のパラメータを設定しkinoko://testman?param1=simejiのように渡せてアプリに細かく指示を出せるようになります。

iOSの場合には、これだけでは起動しないようで、以下のmetaタグをindex.htmlのheadセクションに記述しておく必要があります。default-srcのkinoko:の部分が書き換える対象になります。

図:今回作成したカスタムURLスキームのコード

他のアプリを起動する

cordova-plugin-customurlschemeプラグインによって、他のアプリから自分のアプリのカスタムURLスキームを使って呼ばせる事はできました。しかし、一番用途が多いのは他のアプリのカスタムURLスキームを使ってのアクションでしょう。但し、他のアプリのカスタムURLスキームは公開されていないケースも多いので、連携したいと考えてても出来ないケースもあるので注意が必要です。

この機能を実現するには、com.lampa.startappというプラグインを使う方法とWebintentを使う方法の2つがあります。今回は前者のプラグインを使った手法を実装してみたいと思います。ターミナルを起動して自分のプロジェクトまで移動したら以下のコマンドを実行します。

次にコードを書くわけなのですが、このコードはボタンなどのアクションの後に発動させるわけなので、index.htmlの中にでも記述します。今回はLineに投稿するボタンを用意しました。LineのカスタムURLスキームに関する情報は、こちらで公開されています。ちなみに、LINEが入っていないとエラーになりますので、今回はGoogle PlayストアのLINEのインストールページを開くようにエラートラップしました。

ポイントは、

  1. packageはそのアプリのパッケージ名を入れてあげます。LINEだとjp.naver.line.android、Google Playだとcom.android.vendingとなります。
  2. URIに引数等含めてURL Schemeに渡して上げる文字列を指定します。
  3. 上記のコードでは、LINEが入っていない場合、Google PlayでLINEダウンロード画面に移行します。Google Playの入っていない端末の場合にはエラーのメッセージが出るようにしています。

ちなみに、uriに続けてencodeURIComponent(“テスト”)を繋げてみたのですが、LINEが起動はしても投稿は出来ませんでした。Google MapsなどはencodeURIなどで渡せるのですが、まぁ出来ないものは仕方ありません。公式サイトには出来るみたいな事が書かれているのですが・・・。とはいえ、今は基本投稿関係はOAuth2.0認証をさせてやらせるというのが主流ですから、アプリを起動してというやり方はスマートではないのかもしれません。

関連リンク

Pocket
このエントリーをはてなブックマークに追加
Bookmark this on Yahoo Bookmark
Pocket