Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
Monaca入門:Onsen UI+AngularJSで作るハイブリッドモバイルアプリ(4)

Monaca入門:Onsen UI+AngularJSで作るハイブリッドモバイルアプリ(4)

AngularJSの方法でMonacaアプリを作ってみよう(前編)
―オープンデータとは?/路線番号データを取得するアプリ―

2014年12月3日 改訂 (初版:2013/11/19)

実践的なMonacaアプリ開発の一例として、オープンデータのWebサービスを使ったアプリの作成方法を説明する。Monacaアプリ開発実践編の第1弾。

ヒム・カンパニー 永井 勝則
  • このエントリーをはてなブックマークに追加

 連載最終回の今回(前編・中編後編の3本)は、インターネット上で公開されている実際のデータを、AngularJSの方法でアプリに取り込み、画面に表示していく。

 といっても特別に難しいわけではない。前回学んだAngularJSのデータ/コントローラー/表示とサービスを定型的な書き方で記述するだけだ。

オープンデータとWebサービス

 皆さんは恐らくWebサービスというものをご存じだろう。その最たるものが「Google Maps API ウェブ サービス」で、Webページやモバイルアプリなどで幅広く活用されている。

 Webサービスには、その時点で最新の情報が入手できるという側面がある。例えばlivedoor天気情報で公開されている「ウェザーハックス」を使うと、図4-1に示すような天気情報アプリが簡単に作成できる。

図4-1 Monacaで作った天気情報アプリ

 また最近は組織が保有するデータを外部に積極的に公開するオープンデータの動きも盛んだ。中には箸にも棒にもかからないものもあるが、今回取り上げる「つつじバスロケーションWEB API」は、福井県鯖江市という地方自治体が運営するコミュニティバスの運行情報をリアルタイムで提供しており、先進的な取り組みとして高い評価を得ている。

 オープンデータは、自治体なり民間企業なりが有用な情報をプログラミングで扱いやすい形で提供してくれると、多くの人々がミニコンピューター(=スマホやタブレット端末のこと)を常時携帯する時代にあって、非常に役立つ資源となる可能性を持っている。スマホやタブレットで動作するアプリの制作を目指そうとする皆さんにも新たな活躍の場が生まれるというものだ。

「つつじバスロケーションWEB API」

 「つつじバスロケーションWEB API」の使い方は図4-1に示す「つつじバスロケーションWEB API」ページで調べることができる。このページの中ほどに[つつじバスロケーションWEB-API説明書.pdf]リンクがあるので、これをクリックすると使い方を書いたPDFファイルがダウンロードできる。

図4-1 「つつじバスロケーションWEB API」ページ

 またページ下部の[WEB-API一覧]項目には、表4-1に示すように、得られる情報と、そのために呼び出すPHPファイル名がリストで掲載されている。

No概要リクエスト名
01 路線毎のバス停の座標データ busstopLookup.php
02 路線毎の時刻表データ timetableLookup.php
03 路線番号データ rosenidLookup.php
04 路線と便を指定したバスの位置データ rosenLookup.php
05 号車を指定したバスの位置データ busLookup.php
06 お知らせデータ messageLookup.php
07 高年大学の開講日データ konendaigakuLookup.php
08 冬季日データ winterLookup.php
09 運行履歴データ rosenrecordLookup.php
10 バスアイコンデータ busiconLookup.php
11 バス停アイコンデータ busstopiconLookup.php
表4-1 「つつじバスロケーションWEB API」のAPI一覧

 概要の各項目をクリックすると、その詳細ページにジャンプする。例えば[路線毎のバス停の座標データ]をクリックすると、「01.路線毎のバス停の座標データ」ページが表示される。ここには「Web APIに対してどのような方法で要求(=リクエスト)を出せばよいのか」と、「それに対してどのような応答(レスポンス)が返ってくるのか」が丁寧に書かれている。

 例えば路線ごとのバス停の座標データの場合には、呼び出すURLは「http://tutujibus.com/busstopLookup.php」だ。これにパラメーターとしてrosenidcallbackを指定する。rosenidは、バス停の緯度経度を知りたい路線の番号(1~12)で、callbackJSONP(詳細後述)のコールバック関数名だ。この要求に対して、応答は、busstopという名前の配列に、{"id":"バス停番号","name":"バス停の名前","latitude":緯度,"longitude":経度}というプロパティと値を持ったオブジェクトがバス停の数分だけ入れられて返される。

 ただし路線ごとのバス停の座標データを要求するには路線を特定する必要があり、路線を特定するには、[路線番号データ](rosenidLookup.php)の方法を使って、前もって路線番号データ(路線番号と路線名)を得ておく必要がある。これは路線ごとの時刻表データなど、他の場合でも同様だ。

 ではまずは、この路線番号データを取得する方法から見ていこう。

路線番号データを取得する

 路線番号データを取得する方法は「03.路線番号データ」ページに書かれている。これを読むと、要求するURLは「http://tutujibus.com/rosenidLookup.php?callback=<JSONPのコールバック関数>」という形式で、これに対し、{"id":"路線番号", "name":"路線名"}というオブジェクトの入ったrosenという名前の配列が返ってくることが分かる。

プロジェクトの作成

 Monacaにログインし、Monaca IDEのダッシュボードから[プロジェクトの作成]ボタンをクリックする。選択するのは[Onsen UI最小限のテンプレート]だ([プロジェクト名]は何でもよい)。なお無料で使用できるBasicプランではダッシュボードの[オンライン]で扱えるプロジェクト数が3つに制限されるので、これを超える場合には、連載2回目の「プロジェクトのエクスポートとインポート」を参考に、プロジェクトをエクスポートして手元で保管するか、または不要なプロジェクトを削除する。

 プロジェクトを作成して開くと、コードエディターにREADME.mdファイルが表示されるので、そこに書かれているindex.htmlのコードを全部コピーし、プロジェクトのindex.htmlファイルの全コードに置き換える。そしてJavaScriptコード冒頭のangular.module()の行の左に、次のようにvar app = を追加する。これによりこのプロジェクトはAngularJS仕様になる(AngularJSへの書き換えに関しては連載2回目の「AngularJS流に書き換える」を参照してほしい)。

JavaScript
var app = angular.module('myApp', ['onsen']);
太字部分を追記する(index.html)

index.htmlのJavaScript その1 ― サービスの作成

 連載3回目の「サービス」で述べたように、AngularJSアプリ(つまりOnsen UIを使ったMonacaアプリ)はデータを内部に持つことも外部から取得することもできる。外部から得る場合にはサービスを使用する。今の場合には路線番号データを提供するオブジェクトがこれに当たる。まずは路線番号データを提供するサービスを作成しよう。

 「03.路線番号データ」ページの情報からは、「http://tutujibus.com/rosenidLookup.php?callback=<JSONPのコールバック関数>」という形式で要求を出せばよいことが分かっている。JSONPというのは「JSON形式の引数を取るコールバック関数」をいう。JSONPでは、このコールバック関数をcallbackパラメーターに指定することが基本的なルールとされている。コールバック関数自体は文字列(String)で指定するが、「03.路線番号データ」ページにはコールバック関数の具体的な例や、取得に成功した場合と失敗した場合をどう書けばよいかは書かれていない。しかしこれはAngularJSが標準的に備えている$httpサービスを使うと定型的な方法で処理できる。

 サービス(RosenIDService)は次のように、myAppモジュール(=変数app)のfactory()関数を使って作成する。そのときには、$httpサービスを使用したいのでこのサービスを注入する。

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
var app = angular.module('myApp', ['onsen']);

// 路線番号データを提供するサービス
app.factory('RosenIDService', ['$http', function($http){
  var rosenIDService = {};

  // 路線番号データを要求して、渡されたコールバック関数を呼び出す
  rosenIDService.getRosenID = function(callback){
    $http.jsonp('http://tutujibus.com/rosenidLookup.php?callback=JSON_CALLBACK')
    .success(function(data){
      callback(data);
    });
  }
  return rosenIDService;
}]);
路線番号データを提供するサービス(index.html)

 ポイントは、サービスのgetRosenID()関数だ。8行目を見ると、この関数にはコールバック関数(=引数callback)を渡すようにしている。

 9行目を見ると、$http.jsonp()関数に渡す、要求のコールバック(=URLcallbackパラメーター)に「JSON_CALLBACK」(常にこの関数名にする)を指定している。

 これにより、11行目のように、要求が成功した場合に呼び出されるコールバック関数(=8行目で引数として渡されたcallback関数の呼び出し)が設定できる(AngularJSの$httpでは、10行目のsuccessメソッドが要求成功時に呼び出され、その引数に指定されている関数が実行される。これにより、11行目のcallback関数が要求成功時に呼び出せるというわけだ)。このcallback関数には応答のデータ(=data)が渡される。

 この使い方と書き方は定型として覚えておくと後々役に立つ。

 getRosenID()関数は次のように、引数にコールバック関数を渡して使用する。

JavaScript
RosenIDService.getRosenID(function(data){
  // コールバック関数の実行内容
});
getRosenID()関数の使い方

page1.html ― コントローラー名の指定と、データの表示

 サービスが作成できたので、次はこれを使用するコントローラー(MainController)を作成しよう。

 コントローラーのHTMLコードは、このアプリのメイン画面となるpage1.htmlファイルに記述する。路線番号データはrosen配列で返されるので、<table>要素の<tr>ng-repeatを使って繰り返し処理することにする。ng-repeatは、連載3回目の「ディレクティブ」で述べているように、強力な機能を持ったAngularJS既定のディレクティブだ。

 次のHTMLコードでは、rosen配列をrosenIDという名前で扱っている。rosenIDはこのコントローラーのスコープのプロパティになる。rosen配列に含まれる各オブジェクト(つまりdata in rosenIDdata)は、idプロパティとnameプロパティを持っている。

HTML
<ons-page ng-controller="MainController">
  <ons-toolbar>
    <div class="center">路線番号データ</div>
  </ons-toolbar>
  <table>
    <tr ng-repeat="data in rosenID">
      <td>{{data.id}}</td>
      <td>{{data.name}}</td>
    </tr>
  </table>
</ons-page>
コントローラー名(MainController)を指定し、そのスコープに割り当てられたデータのrosenIDプロパティを監視してページ上に表示するHTMLソース(page1.html)

index.htmlのJavaScript その2 ― サービスを使用するコントローラーの作成

 MainControllerは次のように、myAppモジュール(=変数app)のcontroller()関数を使って作成する。そのときにはRosenIDServiceを使用したいので、このサービスを注入する。複数行コメント(=/*から*/まで)で囲んだコードは、rosen配列の中身を確認するためのコードで、実際に必要なのはその下の、スコープのrosenIDプロパティにrosen配列を割り当てる1行だけだ。

JavaScript
app.controller('MainController', ['$scope', 'RosenIDService', function($scope, RosenIDService) {
  // RosenIDServiceを使って路線番号データをrosenIDプロパティに割り当てる
  RosenIDService.getRosenID(function(data){
    /*
    var rosenData = data.rosen;
    var len = rosenData.length;
    for(var i=0; i<len; i++){
      console.log(i + ': ' + rosenData[i].id + ': ' + rosenData[i].name);
    }
    */
    $scope.rosenID = data.rosen;
  });
}]);
サービスを使用するコントローラーの作成(index.html)

先ほどの「路線番号データを提供するサービス(index.html)」コードの下に追記する。

路線番号データを表示するアプリの実行

 ここまでのコードを保存し、アプリをMonacaデバッガーから実行すると、図4-3に示す結果が得られる。これで路線番号データが得られた。

図4-3 路線番号データが得られた

 次回は、今回の内容を踏まえて、バス停の座標データを取得するアプリを作成する。

※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

Monaca入門:Onsen UI+AngularJSで作るハイブリッドモバイルアプリ(4)
1. Onsen UI+AngularJSで効率的にモバイルアプリが作れるMonaca

HTML+CSS+JavaScriptを使ってスマホやタブレットで動作するアプリが簡単に作成できる「Monaca」を基礎から解説する入門者向け連載(改訂版)がスタート。今回はMonaca/Onsen UI/AngularJSの概要とMonaca IDE、Monacaデバッガーを紹介。

Monaca入門:Onsen UI+AngularJSで作るハイブリッドモバイルアプリ(4)
2. Monacaで作る、初めてのOnsen UIアプリ

新規作成した“初めてのOnsen UIアプリ”プロジェクトの各ファイルをAngularJS流に書き換える。そのアプリをデバッグビルドし、デバイスに実際にインストールする。

Monaca入門:Onsen UI+AngularJSで作るハイブリッドモバイルアプリ(4)
3. Onsen UIの舞台裏で働くAngularJSの世界

AngularJS流のデータ/コントローラー/表示の実装方法と、AngularJSのディレクティブによるHTML要素の操作方法、データの追加、AngularJS機能のサービスについて解説する。

Monaca入門:Onsen UI+AngularJSで作るハイブリッドモバイルアプリ(4)
4. 【現在、表示中】≫ AngularJSの方法でMonacaアプリを作ってみよう(前編)

実践的なMonacaアプリ開発の一例として、オープンデータのWebサービスを使ったアプリの作成方法を説明する。Monacaアプリ開発実践編の第1弾。

Monaca入門:Onsen UI+AngularJSで作るハイブリッドモバイルアプリ(4)
5. AngularJSの方法でMonacaアプリを作ってみよう(中編)

Monacaアプリ開発実践編の第2弾。Web APIを使ってバス停の座標データを取得するアプリの作成手順を解説する。

サイトからのお知らせ

Twitterでつぶやこう!