アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

Onsen UIが生まれたきっかけ



本記事はOnsen UI Advent Calendar 2016のエントリーです。Onsen UIが生まれたきっかけについて、簡単に紹介したいと思います。

当時PhoneGapといわれていたCordovaに足りなかったもの



2009年頃からWebViewを用いた、今でいうHTML5ハイブリッドアプリ開発をしていた訳ですが、当時のデバイスはパフォーマンスも低く、ブラウザーの機能が貧弱だったことも相まって、満足のいくアプリをHTML5「だけ」で作ることがほぼ不可能と言ってもいい状況でした。

思い返すとiOS 4Android 1.6の時代です。まだposition:fixedも使えず、CSSトランジションも怪しい動きをしていました。

一方で、コンテンツをHTML5で記述することのメリットは多く、アプリのマルチプラットフォーム対応や、サーバーからの動的配信で内容をアップデートすることができるなど、この分野の可能性を感じていました。

それがPhoneGap/Cordova/Monacaにつながっていくわけですが、とはいえUIWebViewだけでは、iOSAndroidのネイティブUIにかなう表現ができなかったのは事実です。

そこでネイティブUIフレームワーク



そこで2010年からMonacaを開発するに当たり、どのようにハイブリッドアプリでUI部分でブレークスルーを実現するかが特に大きな課題だと考えていました。その結果、私たちのチームが開発したのは「ネイティブUIとUIWebViewを組み合わせる」というアプローチです。

具体的には、コンテンツの中身はUIWebViewで記述しつつも、ナビゲーターやタブといったネイティブなトランジションが圧倒的に有利な部分はネイティブで描画する、という仕組みでした。

PhoneGapの拡張エンジンとして、オープンソースでリリースしました(メンテナンスはしていませんが、いまでも公開は続けています)。



このフレームワークでは、複数ページをスムーズに遷移するため、マルチWebView構成になっていました。ようするに、次のページに遷移した場合には別のWebViewが作られ、ページスタックが作られます。

ネイティブUIフレームワークの課題からOnsen UIへ



ただしこの仕組みには一つ大きな問題がありました。それは、WebViewが複数に分かれるため、JavaScriptでスコープを管理するのが大変難しくなったということでした。新しいページが全く別のJavaScriptインスタンスとして表示されるため、同じアプリであるにもかかわらず、ページ間でリソースを共有することが難しかったのです。

また、JSON形式でUI定義を記述できる仕組みとしていましたが、その結果デザインのカスタマイズに弱く、多様な表現をしたいアプリにとって制約になってしまうことも問題でした。

一方、iOS 7やAndroid 4が登場しフラットデザインが主流になるなか、WebViewでフルにUIを実装することの現実味が帯びてきました。そこで、社内で議論を行った末、これまで作っていたネイティブUIフレームワークを捨て、Onsen UIに移行するという決断を行いました。

これからのOnsen UI



最初はAngular 1のディレクティブ機能を使って実装したOnsen UIですが、当初は日本語の文献も全くなく、Angularは難しすぎるのではないか?という危惧もありました。しかし一方で、Angular以上にうまく部品をコンポーネント化できる仕組みがなく、Angularを選定したという経緯があります。

昨今ではCustom Elementsも安定したことから、Onsen UI 2.0よりAngularへの依存をなくし、ピュアなWeb Componentsフレームワークとなりました。そのメリットを生かし、Angular 2やReactへの対応とともに、Vue 2といったメジャーなフレームワークのサポートを進めていきたいと考えています。

ぜひ進化するOnsen UIにご期待ください。そして、日本発の世界的フレームワークの挑戦に向けて、GitHubのスターで応援ください!

第8回Apache Cordova勉強会が開催されました

CordovaやPhneGapといったハイブリッドアプリ開発に興味のあるエンジニアが多数集まる第8回Apache Cordova勉強会が西新宿のニフティ社にて行われました。80名近くの方々に参加いただき、大いに盛り上がった会となりました。



こちらはそのレポート記事になります。



Cordova/Electron の構造を知る



ソニー株式会社 関 康治さん





最近、デスクトップ向けのハイブリッドアプリ開発環境として知られるようになってきたEletronとCordovaの相違点について紹介されていました。



CordovaプラグインではどのようにしてネイティブとJavaScriptが通信を行っているのかについて紹介しました。特に面白いのはAndroidiOSで手法が異なるということです。AndroidについてはOSの提供しているWebViewをそのまま使います(後述するCrosswalkは異なります)。



JavaScriptからネイティブへの通信は2つあります。一つは_cordovaNativeを使う方法で、2つ目はPromptというOS標準のAPIをコールする方法です。対して、JavaScriptで処理を受け取る時にはハック的な手法が存分に使われています。まずポーリングで、50msごとに確認する方法を使っています。さらにLOAD_URL方式として、webViewにあるLOAD_URLにJavaScriptを埋め込んで実行する。最後にONLINE_EVENT方式。ネイティブで強制的にオンラインとオフラインを切り替えます。デフォルトはONLINE_EVENT方式となっています。



Crosswalkを使った場合。Androidアプリの中にCrosswalk(ブラウザ)を梱包します。使えるAPIが固定化されるメリットなどはありますが、プラグインの通信については特に変わりません。



iOSの場合。最近のiOS9からUIWebViewからWKWebViewに変わりました。それに伴って、通信方式が変わっています。iOSでは標準で用意されているので、JavaScriptからネイティブは簡単です。UIWebViewでは逆(ネイティブからJavaScript)はハックがふんだんに使われています。まずiframe方式で、iframeのハッシュを書き換えることでメッセージが飛ばします。さらにXHR方式で、ローカルでAjaxをやっているような感じの動きをします。iOS9のWKWebViewはメッセージハンドラーを使って簡単に通信しています。



なお、CordovaはUbuntu向けにも開発できるのですが、これはUbuntu Oneという携帯電話向けOS用に開発されています。実装としては、Qtに依存しています。UbuntuではメッセージAPIを持っているのでスマートにデータの送受信ができます。



最近ではテレビなどにもブラウザが含まれるようになっています。そこでCordovaを使って他のプラットフォーム向けにアプリ提供ができないかどうか試してみました。その場合、問題になるのは利用するブラウザを自前で用意しなければならないことと、JavaScriptとネイティブの通信方法を確保するのが困難でした。



そこでElectronに注目しました。ElectronはWindows/Mac OSX向けのネイティブアプリが作れます。コンパイルしてできあがるバイナリはNode とChromiumを足した感じ。Chromiumとnodeは良い感じに通信してくれます。Cordovaのハック的なやり方に比べると随分スマートになっています。



なお、Electronのリスクとしては、開発を一人でやっている、Chromium、nodeが入っているので重い、Chromiumのセキュリティアップデートよりちょっとタイムラグがあるといった点になります。



CordovaとElectronはwebViewの調達方法が違うというのが今回の結論でした。似たような技術ですが、取り組みがまったく違うようです。



質問としては以下がありました。



ソニーのグラスやデバイスといったプロダクトにCordovaに組み込んだことありますか?



製品としては答えられません。実験的な実装であれば、Cordovaを社内的に使っています。



Cordova × EdTech



エレファンキューブの支倉常明さん





まず事例の紹介がありました。学校の授業用ツールのカンガルー(iPad向けApp Store)になります。ある問題に対して、特徴挙げていきつつグルーピングします。マインドマップ的な、授業中に使う思考ツールです。アプリはCordovaで作られていて、データはlocalStorageに保存するようになっています。



このアプリを開発したきっかけは、新潟大学教育学部附属新潟小学校の片山 敏郎 先生の要望から始まったとのこと。そこに多くの教師が参加しつつ、実際に開発できるのですが人が支倉さんしかいなかったので開発することにしたとのことです。



Cordovaを使ってみて実感するのは開発が爆速であるということ。Web上でも動くようにしたので、確認がとてもスムーズに進む。



さらに別な事例として◯◯を紹介しました。◯◯は海外向けの日本語教育アプリです。UIはOnsen UIを使っており、元々iOS/Android/Webサイトの3環境で使いたいという要望があったそうです。アプリ側の特徴としては、動画や音声をダウンロードするようになっています。



なお、WebViewなのでvideo/audioタグで問題ないかと思ったそうなのですが、Androidではうまく再生できない不具合にハマったとのこと。結局、Cordovaのプラグインを使っているのですが、Webブラウザでも動かすために分岐処理によって使う仕組みを切り替えるようにしているそうです。



ただ、その甲斐もあってワンソースでiOS/Android/Webブラウザに対応しています。



その他の機能として、受講者の学習履歴を閲覧したり、お知らせ/スケジュール配信といった機能があります。サーバサイドはPHPで作ってあるとのことです。



その他の問題として、ID/PWの仕組みを用意するとAppleがとりあえずリジェクトするそうです。また、課金の仕組みを用意していても問題になります。iCloudのバックアップは25MBまでしか使えないので、動画などを保存するとすぐにいっぱいになります。回避策としては、特定のメタデータを書き込むと除外できます。



ニフティクラウド mobile backend × Cordova





ニフティクラウド mobile backendエヴァンジェリストでもある筆者の登壇です。まずニフティクラウド mobile backendについて説明しました。いわゆるmBaaS(mobile Backend as a Service)の一つで、サーバサイドで必要になる機能をまるっと提供することでアプリ開発を高速化します。また、無料から使えるので開発コストを低コスト化することにもつながります。



主な機能はデータストア(データベース)、ファイルストア(ストレージ)、会員管理、プッシュ通知、スクリプトがあります。スクリプトは最も最近出てきた機能で、node.jsベースのコードでmBaaSを拡張できるようになります。



JavaScript SDKを提供しており、Cordovaと絡めて動かすこともできます。このセッション中でのデモは失敗したのですが(失敗した理由はCordovaのセキュリティ上のメタタグを設定し忘れたためです)、Cordovaプロジェクトへの組み込みはBower/npmを使って簡単にできます。



JavaScript SDKさえ組み込んでしまえば、ごく短いコードでデータをクラウド上に保存できるようになります。






Cordova勉強会は今後も行われるとのことで、ぜひ登壇者を募っているそうです。興味がある方は連絡してみてはいかがでしょうか。

Cordova/ReactNativeアプリのライブアップデートを実現するCodePushを試す

Monacaアプリをはじめとする、いわゆるCordovaアプリはハイブリッドアプリと呼ばれる仕組みをとっています。それはネイティブコードでHTML5アプリをラッピングしているのですが、HTML5/JavaScript/スタイルシートの部分についてはコンパイルされていません。つまり、動的に差し替えることができれば、アプリストアによる審査やアプリのアップデートを必要とせず、コンテンツを差し替えることができるようになります。



そうした機能はMonacaエンタープライズ版で提供しているのですが、今回はMicrosoft社がリリースしたCodePushを使って同様の操作を試してみたいと思います。



事前に必要なもの



CodePushはNode.jsを使いますので予めインストールされていることとします。また、今回はCordovaアプリを使いますので、





npm install cordova -g


としてCordovaコマンドをインストールしておきます。



CodePushのインストール



まずCodePushをインストールします。





npm install -g code-push-cli


次に設定を行います。CodePushにアカウントを作成します。





code-push register


そうするとブラウザが開きますので、GitHubMicrosoftアカウントを使ってユーザ登録します。結果としてOAuth2のトークンが取得できますので、それを入力します。





$ code-push register
A browser is being launched to authenticate your account. Follow the instructions it displays to complete your registration.

Enter your access token:  eyJ.....0=

Successfully logged-in. Your session token was written to /Users/nakatsugawa/.code-push.config. You can run the code-push logout command at any time to delete this file and terminate your session.


アプリを登録する



次にアプリを登録します。





$ code-push app add CodePushDemo
Successfully added the "CodePushDemo" app, along with the following default deployments:
┌────────────┬───────────────────────────────────────┐
│ Name       │ Deployment Key                        │
├────────────┼───────────────────────────────────────┤
│ Production │ a8xg..............................kix │
├────────────┼───────────────────────────────────────┤
│ Staging    │ 6PAb..............................kix │
└────────────┴───────────────────────────────────────┘


そして、Cordovaでアプリを作成します。





$ cordova create HelloWorld io.monaca.demo.hello


作成したら、プラットフォームを追加します。今回はiOSを使います。





$ cd HelloWorld
$ cordova add platform ios


CodePushプラグインをインストールする



ではここからCodePushプラグインのインストールと設定を行います。まずプラグインをインストールします。





$ cordova plugin add cordova-plugin-code-push


次にconfig.xmlを次のように修正します。valueのところは先ほど生成したCodePushのキー(プロダクトまたはステージング)と差し替えます。





<platform name="android">
    <preference name="CodePushDeploymentKey" value="YOUR-ANDROID-DEPLOYMENT-KEY" />
</platform>
<platform name="ios">
    <preference name="CodePushDeploymentKey" value="YOUR-IOS-DEPLOYMENT-KEY" />
</platform>


最後に index.html を編集します。





<!-- 元 -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *" />

<!-- 修正後 -->
<meta http-equiv="Content-Security-Policy" content="default-src https://codepush.azurewebsites.net/ 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *" />


config.xmlでアクセスできる外部URLを制御している場合は、





<access origin="https://codepush.azurewebsites.net" />
<access orogin="https://codepush.blob.core.windows.net" />


を追加しておきます。



試してみる



では実際に試してみます。まずiOSアプリとしてシミュレータで実行します。





$ cordova run ios --simulate


次に現状のコードをCodePushに送信します。





$ code-push release CodePushDemo (プロジェクトパス)/platforms/ios/www 0.0.1


アプリ名は自分で取得したものを指定してください。0.0.1は任意のバージョン番号です。



そしてコードを修正します。 codePush.sync(); がCodePushへバージョンのチェックを行い、最新番があればアップデートして反映してくれるコードになります。





codePush.sync();
alert("Bug fixed!");


コードを更新したら、まず (プロジェクトパス)/platforms/ios/www 内に反映します。





$ cordova prepare


終わったら再度CodePushに登録します。





$ code-push release CodePushDemo (プロジェクトパス)/platforms/ios/www 0.0.1


この時大事なのはバージョン番号は同じということです。バージョン番号が異なるものはアップデートできません。つまりちょっとしたコードの修正にして欲しいということでしょう。



再度アプリを起動すると自動的に新しいコンテンツを取得し、反映してくれます。なお、この反映はアプリを再起動(一旦メモリからも落とす必要があります)しないと反映されませんので注意してください。







CodePushの機能



CodePushではリリースされたコンテンツが蓄積して保存されていますので、バージョンを差し戻したり、履歴を一覧で見ることができます。そこでは最新コンテンツに反映しているかどうかも測定ができます。





$ code-push deployment history CodePushDemo Staging
┌───────┬──────────────┬─────────────┬───────────┬─────────────┬──────────────────────┐
│ Label │ Release Time │ App Version │ Mandatory │ Description │ Install Metrics      │
├───────┼──────────────┼─────────────┼───────────┼─────────────┼──────────────────────┤
│ v1    │ 5 hours ago  │ 0.0.1       │ No        │             │ Active: 0% (0 of 2)  │
│       │              │             │           │             │ Total: 0             │
│       │              │             │           │             │ Rollbacks: 1         │
├───────┼──────────────┼─────────────┼───────────┼─────────────┼──────────────────────┤
│ v17   │ 2 hours ago  │ 2.0.3       │ No        │             │ Active: 50% (1 of 2) │
│       │              │             │           │             │ Total: 1             │
└───────┴──────────────┴─────────────┴───────────┴─────────────┴──────────────────────┘






CodePushはCordovaの他に、ReactNativeにも対応しています。コンテンツを差し替えるとまったく別なアプリにすることもできますが、ユーザビリティ的にもそれは控えた方が良いでしょう。また、プラグインをアップデートしたり、追加する場合にはアプリ自体の刷新が必要になるので注意が必要です。同じアプリを用いたベータ版配布にも使えそうです。



なお、Monacaではエンタープライズ版向けに類似のIn-Appアップデーター機能を提供しています。ぜひご覧ください!



CodePush

Visual Studio CodeでMonacaアプリを開発する

Microsoftが開発しているプログラミングエディタがVisual Studio Codeです。Atomをベースにしたエディタとなっており、元々幾つかの機能が組み込まれているのが特徴となっています。さらに機能拡張にも対応しているので機能追加も可能です。



今回はMicrosoft社がリリースしたCordova Toolsというプラグインを使ってみたいと思います。これはVisual Studio Code上でCordovaアプリを開発できるようにするものです。ファイルの配置を変えればMonacaアプリの開発でも使えそうなので、Monaca Localkitで開発する際のエディタとして使ってみるのが良さそうです。



事前準備



まずNode.jsがインストールされている必要があります。そして、コマンドプロンプトやターミナルでcordovaをインストールします。





npm install -g cordova


次にiOSをターゲットする場合、Mac OSX側でライブラリをインストールします。WindowsではiOSに対応したデバッグは未対応です。Homebrewを使うのが推奨されています。





brew install ideviceinstaller ios-webkit-debug-proxy


これで準備は完了です。



インストール



Visual Studio Codeを立ち上げて、Ctrl+Shift+P(Mac OSXの場合はコマンド+Shift+P)を押します。そして出てきたフローティングで install と入力します。そうするとInstall Extensionが一番上に出ますのでエンターキーを押します。





ext install と出たら、cordovaと入力します。そうするとCordova Toolsが出るので、エンターキーを押してインストールを行います。進捗は出ませんが、しばらく待つとインストールが完了します。





プロジェクトの作成



Monacaプロジェクトを作成します。なお、LocalKitを対象としていますので注意してください。プロジェクトを追加したら、別途作成しておくCordovaプロジェクトのplatforms/ios(またはplatforms/android)以下のファイルをMonacaアプリのplatforms以下にコピーしてください。



Visual Studo Codeでプロジェクトを開く



ではVisual Studio Codeを立ち上げて、Monacaアプリのプロジェクトを開きます。このようにIDE風にファイルやフォルダが表示されます。



行の左側をクリックしてブレイクポイントを設定できます。





デバッグは左側にある虫のアイコンをクリックします。そしてSelect Debug EnvironmentでCordovaを選択してください。





そうすると左上に環境の選択が出ます。iOS/Androidのシミュレータやエミュレータ、そして実機での実行が選択できるようになっています。





さらにコンソールをつなげてJavaScriptを実行させることもできます。





Visual Studo Codeの機能について



Visual Studo Codeを使って変数の一覧、ウォッチ、コールスタックそしてブレイクポイントの設定ができます。まだリリースされたばかりとあって不安定な(ちゃんとブレイクしないなど)ところもありますが、MonacaやCordovaアプリを本格的に作り込んでいく際にはとても役立ちそうです。








Visual Studio Codeは最初からGit連携やデバッグ機能があり、プログラミングエディタとして十分な機能が備わっています。Atomがベースとあって、最近のモダンな開発に最適なエディタとなっています。ぜひVisual Studio Codeを使ってMonacaアプリの開発を進めてみてください。



Apache Cordova development lands on Visual Studio Code | The Visual Studio Blog

第7回Apache Cordova勉強会に行ってきました

11月16日、第7回Apache Cordova勉強会が日本マイクロソフト セミナールームにて行われました。今回はマイクロソフト Visual Studio Client Toolsチーム シニア・プログラム・マネージャー Ryan Salva氏が来日するのに合わせて実施されました。



最初はそのRyan Salva氏の発表でした。



エンタープライズ企業におけるCordovaソリューションの提供について



ガートナーの発表しているMagic Quadrant for Mobile Application Development Platformsからの引用としてグラフが提示されていました(via Mendix Named a Visionary in Gartner 2015 Magic Quadrant for Mobile Application Development Platforms)。





このグラフは左から右に行くほど完成度が高く、開発者にとって必要な機能が揃っているということになります。



上下はベンダーのビジョンの完成度を表しています。この上位(右上の四角の中)にある殆どの企業(全20社中9社)がCordovaソリューションを持っています。企業規模はもちろん、Cordovaの完成度が高いことも分かります。



そして別なデータとしてビジョンモバイルの調査によるとCordovaは他のマルチプラットフォーム技術に比べて2倍以上採用ケースが多いとのことです(via Cross-Platform Tools 2015 - VisionMobile





そしてハイブリッドアプリを使っているアプリ(一部でも)は代表例として次のようになっています。なお、これはCordovaを採用しているという意味ではありません。





このように数多くのアプリにおいてハイブリッドアプリ構成は行われています。



Cordovaに関する主な不満については以下のようになります。会場でもそれぞれ不満を感じている方がいらっしゃいました。



  1. ドキュメント
  2. コアプラグインでないものは品質が悪い
  3. バージョンが上がると動かない


なお、この解決手段としてコントリビュートしてくださいというのがRyan Salva氏の答えでした。Cordovaはオープンソース・ソフトウェアであり、不満に思う点があれば開発に参加できるのが大きなポイントです。



実際、Cordovaにコントリビュートしている主な企業は以下の通りです。





これらの企業に加えて多くの個人開発者も参加しています。そして参加の具合ですが、





という暗黙のルールがあります。そのためiOS9が発表されるとAdobe社のコミットが増え、MicrosoftWindows 10、そしてAndroidも最新版のOSに合わせた開発が行われるとのことです。それぞれ貢献時期は異なるものの、年間を通して同じくらいの貢献度であるというのが良い点とのことです。エンタープライズにおいてCordovaを使っていく上で、各企業がきちんとメンテナンスしてくれることで5年後、10年後の安心感につながるとのことです。



Cordovaのサイトに来るユーザ層は、



  • インド
  • アメリカ
  • ブラジル
  • 中国


が多く、日本からももっとアクセスして欲しいとのことです。Cordovaのダウンロード数は着実に伸びており、過去2年間で2倍に達しています。特にエンタープライズ分野で伸びています。



実際にCordovaで開発しているプラットフォームは、



  1. Android
  2. iOS
  3. Windows


という順番になっています。さらにすでに最新のCordova5が最も多く使われています。



Web技術を使えるとあって、多くのフレームワークが存在しますが、アプリの評価と比べると



  • Backbone 5.8
  • Zepto 5
  • Ionic 4.2
  • Dojo 4.1
  • Angular 3.8


といった順番になっています。jQuery Mobileなどは古いフレームワークであるために動作が重かったり、機能がモダンなプラットフォームに対応していないことが多いそうです。そのためフレームワークの種類に限らず、新しいフレームワークを採用しましょう。



今後のCordovaのロードマップですが、



  1. ドキュメント
  2. プラグインの品質システム
  3. バージョン統合
  4. ネイティブAPIサポートまでの期間短縮


といった順番で考えられているとのことです。



質疑応答では以下の質問が寄せられました。



Electronについてはどうか?



まだまだバギーではないか。CordovaとしてもElectronをサポートするかどうかという話は出たか、今は未定。



エンタープライズ・モバイルアプリにおけるハイブリッドアプリ開発



続いてジェーエムエーシステムズ 中居さんによる**エンタープライズ・モバイルアプリにおけるハイブリッドアプリ開発**の発表です。



スマートデバイスの業務利用増加しているとのことです。理由としては、



  1. セキュリティ懸念よりもビジネス競争力
  2. 単なる便利ツールから武器へと変化している
  3. モバイルアプリの寿命が長期化


昔はデバイスの契約が2年で切れるので、それまで使えれば良かった。今は5年くらいは使い続けられるシステムでないといけない。そこでハイブリッドアプリに注目が集まっている。



ジェーエムエーシステムズさんの開発手法については、



  • ネイティブアプリ
  • ハイブリット開発
  • Webアプリ


の3パターンをクライアントニーズによって使い分けている。iOSアプリのネイティブ開発案件が多いが、ハイブリッドアプリ開発も急激に増えている。数年前はパフォーマンスが悪かったり、一部の機種で動かないような不具合があったので一旦ハイブリッドアプリ開発は中断していた。



なぜハイブリッドアプリ開発が増えているか?理由としては下記が考えられる。





今はマルチデバイスが必須では内が、将来に備えているケース。ハイブリッドアプリはネイティブに劣らないレベルでハードウェアの性能が向上している。昔から一部はクロスプラットフォーム開発フレームワークがあったが、ホビーレベルだったが、今は品質が上がっている。また、Swift/Objective-Cエンジニアの数があまりに少ないため採用しづらい問題も。



ハイブリッドアプリフレームワークに求めるもの。



  • マルチデバイス対応がちゃんとしている
  • OSのバージョンアップ対応が速いかいなか
  • サポートの充実


ジェーエムエーシステムズ社ではMonacaIBM MobileFirst Platformを使っている。Cordovaを直接使わないのはサポートがあるから。



Cordovaで作る!センサと超小型BLEモジュールを用いた簡単IoTアプリ開発



最後は慶應義塾大学 伊藤さんによるCordovaとセンサー、BLEモジュールを用いたIoTアプリ開発に関するプレゼンでした。



Cordovaはスピーディーに開発できるのが良い。自作アプリとしてはAppCubeなど。今回はセンサー × BLE × Cordovaを組み合わせて簡単なIoTを実現するデモです。



作ったのはWaterTrackerというアプリで、コップの下に圧力センサーを置いて、その値をスマートフォンに送信するもの。スマートフォン側はBLEで値を受け取り、コップの残量を可視化。Cordovaを使っているので簡単なJavaScriptのメソッドでできる。



WaterTrackerのソースコードはGitHub上にあります






エンタープライズ(対企業)においてハイブリッドアプリの需要が伸びているのはよく感じられる方が多いのではないでしょうか。スマートフォンは移動中にも使えるデバイスですし、タブレットは現場に持ち込んで作業するのに最適です。



Cordovaの性能が向上したことで、リッチなUI/UXや高速動作よりもまず素早く開発できて、かつマルチプラットフォームに提供できるハイブリッドアプリはますます需要が増しそうですね。

Cordova 5でCrosswalkプラグインを使ってみた

こんにちは、Monacaチームの細井です。

現在、Monacaチームでは、現在に公開されている Cordova 5への対応の調査を行っています。
Cordova 5(Android Platform 4.x)で変更点の中でも注目なのは、Androidのハイパフォーマンス版で使用しているCrosswalk WebViewエンジンがCordovaプラグイン化されたことです。

従来は、CrosswalkエンジンがCorsswalk用のCordovaに組み込まれていたため、Cordovaのバージョンを安易に上げられないといった問題がありました。
プラグイン化したことにより、CordovaとCrosswalkのバージョンに依存関係がなくなり、アップデートが容易になりました。

本記事では、CordovaコマンドでCrosswalkプラグインを使用する手順を紹介します。


Crosswalk プラグイン


https://github.com/crosswalk-project/cordova-plugin-crosswalk-webview


検証バージョン


Cordova: 5.2.0
Android Platform: 4.1.1


使ってみた




// 適当なサンプルプロジェクトを作成
cordova create XwalkTest

// Android Platformを追加
cordova platform add android

// Crosswalkプラグインを追加
cordova plugin add cordova-plugin-crosswalk-webview

// Androidアプリでビルド
cordova build android


以上。
ユーザエージェントでWebViewのバージョンを確認してみます。


alert(navigator.userAgent);




WebViewがCrosswalkになっています。

また、Crosswalkプラグインのバージョン1.3.0から、自由にCrosswalkのバージョンを指定してビルドすることができるようになりました。
※8月28日時点では、Cordova Plugins Registryのバージョンが1.2.0なので、gitからプラグインを追加しています。

以下のように、plugin add時にパラメータを指定することでバージョンを指定できます。



cordova plugin add https://github.com/crosswalk-project/cordova-plugin-crosswalk-webview.git --variable XWALK_VERSION="org.xwalk:xwalk_core_library:14+"
(cordova plugin add cordova-plugin-crosswalk-webview --variable XWALK_VERSION="org.xwalk:xwalk_core_library:14+")


add後、config.xmlを確認すると、以下のプレファレンスが自動的に追加されています。
このプレファレンスがCrosswalkのバージョン(この場合14+)を指定しており、ビルド時に対象バージョンのCrosswalkエンジンを取得してきます。



<preference name="xwalkVersion" value="org.xwalk:xwalk_core_library:14+" />


このバージョンは、plugin addした後でも自由に変更することができます。
また、以下のようにvalueに「_beta」を付けることで、BetaバージョンのCrosswalkエンジンを取得することもできます。



<preference name="xwalkVersion" value="org.xwalk:xwalk_core_library_beta:15+" />


Crosswalkのバージョンはこちらを参照


おわりに


便利になったCrosswalkエンジン。Monacaで今後どのように提供させていただくか検討中ですので、しばしお待ちくださいませ!

LEGOでRaspberry Piケース "Cordovaくん" を作ってみた

こんにちは、Monacaチームの細井です。
まだまだ、クソ暑い日が続きますが、皆様いかがお過ごしでしょうか。

さて今回は、夏休みの宿題っぽい感じで、「LEGORaspberry Piのケースを作ってみた」という内容をお送りします。


■ テーマ



Monacaチームのある方から、Raspberry Pi買ったからLEGOでケース作ってください、と依頼を受ける。
LEGOなのでテーマ決めないとなー、と思い、せっかくなのでMonacaチームっぽいテーマにしようと思い、決定したのがコレ。


■ 作ってみた



正式名称は知らないのですが、「Cordovaくん」という名前で作りました。

Cordovaくんは、立方体なのですが、ケースなので直方体に。


Cordovaくんの顔が蓋になっています。パカー。


Raspberry Piのデフォルトケースをそのまま入れられるようになっています。



■ 細かいところ



真上から。


緑と赤の部品は、ラズベリーを表現しています。
椅子に座ってる人は、PCでCordovaアプリを開発してるエンジニア。


横と背面には、各端子を差すための穴を設けています。


ドアを開けると、直接配線することも可能です。
ちなみに、上部から出てる赤いケーブルの先は、温度と湿度のセンサーになっているので、Cordovaくんはbotになってオフィスの温度を教えてくれます。


■ おわりに



たまにLEGOをやると普段と違う脳が使われるような気がします。
さすがに業務中にLEGOはできないですが、アシアル社員らしい遊び心を忘れないよう、こういうこともしていきたいですね!


■ お知らせ



Monacaチームでは現在、新規開発メンバーを大募集中です。詳しくはこちらを参照ください!
https://ja.monaca.io/careers.html

MonacaアプリでInstagramに写真を投稿する!

こんにちは、渡辺です。

今回は、「vstirbu/InstagramPlugin」プラグインを利用してInstagramと連携するサンプルアプリを作ってみたいと思います。今回のプラグインは、利用方法が非常に簡単なので、はじめてプラグインを利用する人に是非チャレンジしてもらいたいです。

■利用するプラグイン


vstirbu/InstagramPlugin
( https://github.com/vstirbu/InstagramPlugin )

■サンプルプロジェクトについて


 サンプルプロジェクトでは、下の2つを対象にInstagramへ連携するアプリを作成します。連携できるものは、写真だけでなく、Canvas要素も連携することができます。
(1)写真の連携では、カメラで撮影したものをそのままInstagramへスグに投稿できるものを実装します。
(2)Canvas要素の連携では、Canvasで書いた星を投稿します。

また、このプロジェクトはMonacaテンプレートの「最小限のテンプレート」をもとに作成しています。

 

Instagramに連携できるもの


  (1) カメラで撮った写真
  (2) Cavas要素



 

・サンプルプロジェクトの動作確認環境


  ・iPhone6 (iOS 8.1.2)
  ・GALAXY Note 2 SC-02E (Android4.3 )
  ・デバッグビルドしたアプリで確認済

■準備


 準備としては、サンプルプロジェクトを作成する前に、まず、Instagramアプリを先にインストールして、Instagramへの登録を完了させておいて下さい。また、作成するプロジェクトでは下記のプラグインが有効となっていることが必要となります。

 ・Fileプラグイン(org.apache.cordova.file)
 ・Cameraプラグイン(org.apache.cordova.camera)
 ・MonacaPlugin(mobi.monaca.plugins.Monaca)

プラグインのインストール


  こちらの過去記事に記述したましたので、参照ください。

■端末にInstagramがインストールされていることを確認する


isInstalled( )で、端末にInstagramが既にインストールされているかどうかを確認することができます。変数installedに確認結果が返ってきます。



Instagram.isInstalled(function (err, installed) {
    if (installed) {
        console.log("Instagram is", installed); 
    } else {
        console.log("Instagram is not installed");
    }
});


Instagramへ連携する


  

ー 写真を撮って投稿する



まずカメラを起動させる処理を用意します。「show_pic( )」でカメラを起動させる処理( navigator.camera.getPicture( ) )を行っています。「navigator.camera.getPicture( )」の第一引数では、カメラでの撮影が成功した場合に実行する処理を定義しています。今回は、カメラで撮った写真をそのままInstagramへシェアしたいので、「share_pic( )」を呼び出して、その中で「share( )」を実行しています。



  show_pic: function()
    {
        navigator.camera.getPicture(this.share_pic, this.fail,
        {
            quality: 50,
            destinationType: Camera.DestinationType.DATA_URL,
            targetWidth: 400,
            targetHeight: 400
        });
    },
  fail: function(msg)
    {
        alert(msg);
    },
    share_pic: function(data)
    {
        Instagram.share("data:image/jpeg;base64," + data, 'example caption', function(err) {});
    }


  

Canvas要素を投稿する


次は、Canvas要素をシェアする方法です。この処理は、サンプルプロジェクト起動時に描画される星をタップした時に実行されるようにしました。「Instagram.share( )」では、Instagramへ連携する対象の要素idを第一引数に指定しています。第二引数は、オプションとなっていてタイトルを設定します。



    share_canvas: function()
    {
        Instagram.share('instagram', 'canvas element share', function(err) {});
    }


■サンプルプロジェクトのデバッグ方法


外部のプラグインを利用したプロジェクトをデバッグする場合は、ストア版Monacaデバッガーではなく、「カスタムデバッガー」を作成する必要があります。「カスタムデバッガー」の作り方は、通常のビルドと同様の画面で「デバッガーのビルド」を選択して作成します。



※ストア版Monacaデバッガーでは、コアプラグインと呼ばれる組み込み済のプラグインが利用できます。一方、コアプラグイン以外のプラグインを利用する場合は、外部プラグインを組み込むことができるカスタムデバッガーを作成する必要があります。

■サンプルプロジェクトのコード


index.html




<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <link rel="stylesheet" type="text/css" href="css/style.css" />
    <script src="components/loader.js"></script>
    <title>Instagram plugin project</title>
</head>

<body>
    <canvas id="instagram" onclick="app.share_canvas();"></canvas>
    <button class="button--cta" onclick="app.show_pic();">Get a Picture</button>
</body>
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript">
    app.initialize();
</script>

</html>


app.js




var app = {
    // Application Constructor
    initialize: function()
    {
        this.bindEvents();
    },
    bindEvents: function()
    {
        document.addEventListener('deviceready', this.onDeviceReady, false);
    },
    onDeviceReady: function()
    {
        app.receivedEvent('deviceready');
    },
    receivedEvent: function(id)
    {
        this.draw_star();
        Instagram.isInstalled(function(err, installed)
        {
            if (installed)
            {
                alert("Instagram is installed!!");   
            }
            else
            {
                alert("Instagram is not installed");
            }
        });
    },
    draw_star: function()
    {
        var canvas = document.getElementById('instagram');
        var ctx = canvas.getContext('2d');
        ctx.canvas.width = window.innerWidth;
        ctx.canvas.height = window.innerHeight - 200;
        ctx.fillStyle = "rgba(250, 220, 0, 0.6)";
        star(ctx, 100, 100, 90, 5, 0.5);

        function star(ctx, x, y, r, p, m)
        {
            ctx.save();
            ctx.beginPath();
            ctx.translate(x, y);
            ctx.moveTo(0, 0 - r);
            for (var i = 0; i < p; i++)
            {
                ctx.rotate(Math.PI / p);
                ctx.lineTo(0, 0 - (r * m));
                ctx.rotate(Math.PI / p);
                ctx.lineTo(0, 0 - r);
            }
            ctx.fill();
            ctx.restore();
        }
    },
    show_pic: function()
    {
        navigator.camera.getPicture(this.share_pic, this.fail,
        {
            quality: 50,
            destinationType: Camera.DestinationType.DATA_URL,
            targetWidth: 400,
            targetHeight: 400
        });
    },
    fail: function(msg)
    {
        alert(msg);
    },
    share_pic: function(data)
    {
        Instagram.share("data:image/jpeg;base64," + data, 'example caption', function(err) {});
    },
    share_canvas: function()
    {
        Instagram.share('instagram', 'canvas element share', function(err) {});
    }
};


style.css




html,
body {
    width: 100%;
    height: 100%;
    margin: 0px;
    background: #222;
}
#canvas-container {
    width: 100%;
    text-align: center;
}
canvas {
    display: inline;
}


■参考情報


・vstirbu/InstagramPlugin
  https://github.com/vstirbu/InstagramPlugin
・vstirbu/instagramplugin-example
  https://github.com/vstirbu/instagramplugin-example

■お知らせ


Monacaチームでは現在、新規開発メンバーを大募集中です。詳しくはこちらを参照ください!
https://ja.monaca.io/careers.html

第6回Apache Cordova勉強会 に参加してきました

Cordova/PhoneGap、Monaca向けの勉強会が、2015年6月19日(金)飯田橋IIJ本社 セミナールームにて開催されました。
毎回盛況なユーザ会も今回で6回目となりました。それでは、レポートいってみます。



セッション1: AngularJS入門





AngularJS超入門



まずは、AngularJSの超入門。ちょっと時間が押していたため早足でしたが、一通りの作成方法がプレゼンされました。





AngularJS超入門



発表者: アシアル 岡本さん



超入門というわりには、とくにディレクティブの説明とその利用方法について、バージョンの違いなどが詳しく説明されました。そして最後に、TODOアプリの紹介で締めくくられました。



ざっくりでしたが、AngularJSのcontrollerやFactoryからの、フロントエンドへのバインディング機能は、わずかなコーディング量で実現できるのは素晴らしいと改めて感じさせてくれるプレゼンでした。



セッション2: Cordovaプラグイン開発ライブコーディング



続いて、Cordova女子の登場です。





Animate.cssデモ



壇上は一気に、女子モード全開…プレゼン資料が一面ピンク色でした。



NTTコムウェア 佐藤玲奈さん(右)・古澤麻衣子さん(左)



Crosswalkについて



古澤さんによる、AndroidにおけるWebviewの描画機能の差異を埋めるための、ViewクライアントCrosswalkの紹介です。





NTTコムウェア 古澤さん



発表者:NTTコムウェア 古澤さん



Cordova5.0からプラグイン化され、より簡単に利用出来るようになりました。Android OSバージョンによる表示がうまく統一できないなどで悩むまえに、Crosswalkを利用してみる方が良いかと思います。



楽しいプラグインの基本的な作り方



佐藤さんによる、「プラグイン開発」についての説明です。





NTTコムウェア 佐藤さん



発表者:NTTコムウェア 佐藤さん



プラグインってなに?」という説明から、プラグインを通して、Native機能を実際に利用するところまでを説明されました。丁寧ではありましたが、次回はライブコーディングにチャレンジして貰いたいです!



セッション3: Cordova Plugin をもっと簡単に!



続いて、Cordova Pluginのひな形生成ツールの紹介です。





Sony 関さん



発表者:ソニー 関さん



Plugmanというツールはあるけれど。。。



Plugmanとは、Corodva Pluginのひな形を作ってくれる、コマンドラインツールです。簡単にできるとは言え、問題点も多く、「引数が多く長い」「正しく引数の順序を守らないと動かない」などを抱えているそうです。そこで、YeomanによるCordova Plugin generatorを作ってみたということです。



Plugin開発において、ひな形だけならば、そんなに必要性を感じていませんでしたが、Jasminのテストケースも吐き出してくれると言うことで、興味深い内容でした。



Contribution 歓迎ということですので、興味のある方は是非。



紹介したプラグインのライブコーディング・・・



残念ながら、エラー・・・でした。



資料紹介



GitHub: generator-cordova-plugin-devbed



こちらのページに今回の資料が上がっていますので、ご参考まで。



第6回Cordova勉強会: Cordova plugin をもっと簡単に



その他: ライトニングトークと与太話



最後はライトニングトークでした。実際に開発された方の、生の声が聞けました。



その1「Cordovaで作ったSNSアプリ紹介」



実際に開発をしてみた感想などが中心となりました。こちらの所感は非常に参考になると思います。





池尻野 雄介(インフォコム株式会社)さん



ライトニングトーク: 池尻野 雄介さん(インフォコム株式会社)



ハイブリッドアプリを選んだ理由


  • タイムライン機能のネイティブ化の課題。
  • jQuery Movileだとパフォーマンスチューニングが必須。
  • ClickイベントはFastClickを利用したりしてパフォーマンスを上げた。
  • ハイブリッドアプリ向けにチューニングされたOnsenUIが利用できる。
  • OnsenUI+AngularJSでの実装。


OnsenUIをつかってみての感想


  • ネイティブアプリに遜色ない動き。
  • iOSフラットデザインがベースになっていて、デザインに時間がとられない。
  • AngularJSベースなのでjQueryに比べて保守性が上がる。


Cordovaでハマったところ


  • Android
  • OS4.4.4で画像ファイルのアップロードが出来ない。
  • Cameraプラグインが古い事が原因。
  • Cordovaプラグインのバージョンアップは実施した方が良い。
  • iOS
  • ソフトウェアキーボードの挙動が怪しい。
  • ナビゲーションバーのヘッダが追随せず。結局自前で作成。
  • ionic kyebardプラグインを使うと良いらしい。


所感


  • ハイブリッドで作る決断は正しかった。
  • 業務用なら出来ないことは、ほぼ無い。
  • よほど凝ったUI、ゲームアプリじゃなければ問題無い。


その2「CordovaとElectron(Atom Shell)の同じところ・違うところ」





田中 正裕さん



ライトニングトーク:田中 正裕さん



ELECTRONの紹介です。



ELECTRONとは


もともとは「Atom Shell」と呼ばれていた物ということです。GitHub製のエディタ「ATOM」でも有名です。Node.jsを利用した、ハイブリット実行環境で、GitHubにてオープンソースとして公開されています。他に、ELECTRONの構造やELECTRONとCordovaの違いなどが紹介されました。



アプリケーション開発事例




DEMO


Monacaの基板の元になったコードも紹介されました。



GitHub https://github.com/masahirotanaka/calculator



まとめ



今回は入門向けの発表が多かったですが、それだけCordova、Monacaのユーザ層が広がってきたと言うことでしょう。



初めてのツールなどで開発を行うときは、先人のベストプラクティスを聞いてしまうのが一番の近道です。こういった入門向けの勉強会は、ますます広がりを見せてくれる事でしょう。



これからさらに、活躍の場を広げそうなハイブリッド開発ですが、何事も基礎が大事だとおもった勉強会でした。



勉強会の様子



プラグインで簡単に実装できるローカル通知機能!!

こんにちは、渡辺です。

今回は、Manacaで「ローカル通知」プラグインを利用する方法を説明したと思います。
ローカル通知機能のプラグインは、GitHub上で複数ありますが、ここでは下のプラグインを利用します。

katzer/cordova-plugin-local-notifications

ー 目次 ー


 ・ローカル通知とは
 ・サンプルプロジェクトについて
 ・Monacaでのプラグイン組み込み方法
 ・通知許可の確認(アクセス権限の確認)(iOS8のみ)
 ・通知を予約する(スケジュール)
  ー 1分間隔で通知
  ー 1回のみスグに通知
 ・通知スケジュールを取り消す(キャンセル)
 ・サンプルプロジェクトの全体コード
 ・参考情報

ー 確認環境 ー


iPhone6 (iOS 8.1.2)
・GALAXY Note 2 SC-02E (Android4.3 )
デバッグビルドしたアプリで確認済
(※ビルドして確認をお願いします。)

■ローカル通知とは


ローカル通知とは、アプリケーション自身がスケジューリングしてユーザーへ通知する仕組みです。
プッシュ通知(リモート通知)とは違い、インターネット経由での外部通信なしでユーザーへの通知ができます。
カレンダーアプリやToDOアプリなど時間ベースで動くアプリが、ローカル通知に向いているアプリの代表です。

■サンプルプロジェクトについて


サンプルプロジェクトのイメージです。「Onsen UI最小限のテンプレート」をもとに作成しています。

「Granted?」ボタンで、ローカル通知の使用権限を確認します。
「Once」と「Every min」ボタンは、ローカル通知のスケジュール実行ボタンです。
「All」で、スケジュールした通知を解除します。

Monacaでのプラグイン組み込み方法


Monacaでのプラグイン組み込み方法は、2種類あります。
  ・Zip形式のプラグインをアップロードする
  ・名前もしくはURLを指定する





Zip形式のアップロードの場合は、GitHubの「Download ZIP」ボタンをクリックしてZipを取得してください。もう一方の、「名前もしくはURLを指定」を利用する場合は、GitHubのURL「https://github.com/katzer/cordova-plugin-local-notifications」を指定してください。

Monacaが提供しているコアプラグイン以外の外部プラグインをインポートするには、GOLDプラン以上が必要となります。GOLDプラン以上でない方は、まずは無料で試せる14日間のトライアルをご利用してください。

■通知許可の確認(アクセス権限の確認)(iOS8のみ)



iOS8では、アプリがローカル通知を使用する前に、ユーザーから許可をもらう必要があります。「Granted?」ボタンでは、許可を得ているかの確認をしています。許可を得ていない場合は、初回起動にダイアログで許可するかどうかの確認が表示されるはずです。それ以外は、設定画面から通知の許可を与える必要があります。



  //check permission
  hasPermission = function () {
    cordova.plugins.notification.local.hasPermission(function (granted) {
      alert(granted ? 'Yes' : 'No');
    });
  };


■通知を予約する(スケジュール機能)



・1分間隔で通知


ここからローカル通知の処理です。ここでは1分間隔で通知するよう設定しています。プロパティ「every」には、"second", "minute", "hour", "day","week","month","year"と指定できます。また、プロパティ「sound」では、通知した時に流す音源を指定できます。音源は、参考情報に記載したサンプルプロジェクトが提供しているものを使用しています。
※プロパティ「every」に"second"を設定してみましたが、1秒間隔で動かなかったので、もしかしたら、"second"指定でプラグインにバグがあるかもしれません。



scheduleMinutely = function () {
    var sound = device.platform == 'Android' ? 'file://sound.mp3' : 'file://beep.caf';
    cordova.plugins.notification.local.schedule(
      {
        id: 1,
        text: 'Scheduled every min',
        every: 'minute',
        sound: sound
      });
  };


・1回のみスグに通知


一度のみの通知の場合も、schedule( )を使用して通知します。プロパティ「every」がない場合の、デフォルト状態が、1回のみの通知となっています。



//schedule
  var id = 1;
  schedule = function () {
    cordova.plugins.notification.local.schedule(
      {
        id: 1,
        text: 'Test Message 1',
        sound: null,
        data: {
          test: id
        }
      });
  };


■通知スケジュールを取り消す(キャンセル)


さっき設定した1分間隔での通知をキャンセルしましょう。一気に全部キャンセルする場合は、「cancelAll( )」を呼ぶだけです。キャンセルする対象を指定する場合は、「cancel( )」の第一引数にIDを指定します。



  //cancel all notifications
  cancelAll = function () {
    cordova.plugins.notification.local.cancelAll(function () {
      alert("done");
    }, this);
  }

  // cancel single notification
  cordova.plugins.notification.local.cancel(1, function() {
      alert("cancel id 1");
  });


■サンプルプロジェクトの全体コード


・index.html


<!DOCTYPE HTML>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <script src="components/loader.js"></script>
  <link rel="stylesheet" href="components/loader.css">
  <link rel="stylesheet" href="css/style.css">
  <script>
  </script>
</head>

<body>
<div>
  <h2>Local Notification</h2>
  <!-- permission -->
  <h4 class="section">〜 Permission (iOS8) 〜</h4>

  <div class="container">
    <button class="button button--outline" onclick="hasPermission()">Granted?</button>
  </div>
  <!-- schedule -->
  <h4 class="section">〜 Schedule 〜</h4>

  <div class="container">
    <button class="button button--outline" onclick="schedule()">Once</button>
    <button class="button button--outline" onclick="scheduleMinutely()">Every min</button>
  </div>
  <!-- cancel -->
  <h4 class="section">〜 Cancel 〜</h4>

  <div class="container">
    <button class="button button--outline" onclick="cancelAll()">All</button>
  </div>
</div>
<script type="text/javascript">
  var id = 1;
  //permission
  hasPermission = function () {
    cordova.plugins.notification.local.hasPermission(function (granted) {
      alert(granted ? 'Yes' : 'No');
    });
  };
  //schedule
  schedule = function () {
    cordova.plugins.notification.local.schedule(
      {
        id: 1,
        text: 'Test Message 1',
        sound: null,
        data: {
          test: id
        }
      });
  };
  scheduleMinutely = function () {
    var sound = device.platform == 'Android' ? 'file://sound.mp3' : 'file://beep.caf';
    cordova.plugins.notification.local.schedule(
      {
        id: 1,
        text: 'Scheduled every minute',
        every: 'minute',
        sound: sound
      });
  };
  //cancel
  cancelAll = function () {
    cordova.plugins.notification.local.cancelAll(function () {
      alert("done");
    }, this);
  }
</script>
</body>

</html>


・style.css


.button {
    position: relative;
    display: inline-block;
    vertical-align: top;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    -webkit-background-clip: padding-box;
    background-clip: padding-box;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    background: transparent;
    border: none;
    line-height: normal;
    font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-weight: 400;
    font-size: 17px;
    cursor: default;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
    height: auto;
    text-decoration: none;
    padding: 4px 10px;
    font-size: 17px;
    line-height: 32px;
    letter-spacing: 0;
    color: #fff;
    vertical-align: middle;
    background-color: rgba(24, 103, 194, 0.81);
    border: 0px solid currentColor;
    -webkit-border-radius: 3px;
    border-radius: 3px;
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
}

.button:hover {
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
}

.button:active {
    background-color: rgba(24, 103, 194, 0.81);
    -webkit-transition: none;
    -moz-transition: none;
    -o-transition: none;
    transition: none;
    opacity: 0.2;
}

.button:focus {
    outline: 0;
}

.button:disabled,
.button[disabled] {
    opacity: 0.3;
    cursor: default;
    pointer-events: none;
}

.button--outline {
    background-color: transparent;
    border: 1px solid rgba(24, 103, 194, 0.81);
    color: rgba(24, 103, 194, 0.81);
}

.button--outline:active {
    background-color: rgba(24, 103, 194, 0.2);
    border: 1px solid rgba(24, 103, 194, 0.81);
    color: rgba(24, 103, 194, 0.81);
    opacity: 1;
}

.button--outline:hover {
    border: 1px solid rgba(24, 103, 194, 0.81);
    -webkit-transition: 0;
    -moz-transition: 0;
    -o-transition: 0;
    transition: 0;
}

@import url(http://fonts.googleapis.com/css?family=Oswald);
div {
    text-align: center;
    font: bold 21px 'Oswald', sans-serif;
    text-transform: uppercase;
}

body {
    background-image: -webkit-repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%);
    background-image: -moz-repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%);
    background-image: -ms-repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%);
    background-image: repeating-radial-gradient(center center, rgba(0, 0, 0, .2), rgba(0, 0, 0, .2) 1px, transparent 1px, transparent 100%);
    -webkit-background-size: 3px 3px;
    -moz-background-size: 3px 3px;
    background-size: 3px 3px;
}


■参考情報


より詳しい情報は下のサンプルを参考にしてください。
・サンプルプロジェクト
https://github.com/katzer/cordova-plugin-local-notifications/wiki
https://github.com/katzer/cordova-plugin-local-notifications/tree/example