PhoneGapで外部アプリと通信するための設定

PhoneGapを使ったプログラムで外部のプログラムとの通信を行うためには、まずPhoneGap側の設定ファイルを変更する必要があります。PhoneGapでは、外部プログラムとの通信にホワイトリスト方式を採用しており、許可された接続先のみ通信できるようになっているからです。ホワイトリストは次のように設定します。

iOSの場合

「Supporting Files」というディレクトリの中に「phonegap.plist」または「cordova.plist」というファイルが格納されています(バージョンによって異なります)。このファイルを開いて「ExternalHosts」という項目を探し、通信先のホストを記載してください。

全てのホストとの通信を許可する場合には「*」を指定してください。

Androidの場合

「res/xml」というディレクトリの中に「cordova.xml」というファイルが格納されています。このファイルを開いて、<access origin=...>というタグを探してください。このoriginプロパティに、次のように通信を許可するホストを記載します。

サンプルコード:cordova.xmlのoriginプロパティの設定例

<access origin="http://127.0.0.1*"/>

全てのホストとの通信を許可する場合には次のような指定になります。

サンプルコード:全てのホストとの通信を許可する場合

<access origin=".*"/>

Ajaxによるサーバとの通信

サーバとの通信はAjaxを使用して行います。今回は、Ajax通信の実装部分にjQueryを利用します。jQueryを使えば、HTMLコードの<script>タグの中に、以下のようなJavaScriptコードを埋め込むだけでAjax通信を実行することができます。$.ajax()関数がAjax通信を行うための関数で、通信先のサーバのURLはurlオプションの値として指定します。この例では「http://example.com/html5」を指定しています。

サンプルコード[JavaScript]:Ajaxによるサーバとの通信

$.ajax({ url:"http://example.com/html5", success:funciton(d){ alert(d); }, error:function(d){ alert("error"+d); } });

Ajaxでは、通信の状態に応じて、通信毎に次の4種類のイベントが発生します。

  • success - 通信が成功した際に発生する
  • error - 通信に失敗した際に発生する
  • beforeSend - 通信を行う前に発生する
  • complete - 通信処理が完了した際(successやerrorの処理の後)に発生する

イベントは$.ajax()の実行時に指定した同名のオプションの関数によって処理されます。例えば指定したURLとの通信が成功した場合には、successイベントが発生して、successオプションに指定した関数が実行されます。この関数の引数には、サーバから返される情報(通常のWebページであればHTMLコード)が渡されます。この例では、渡された情報をalert()を使って表示しています。

端末が圏外にあるなど、何らかの理由で通信に失敗した場合には、errorオプションに指定した関数が実行されます。このときの引数にはエラー情報が渡されます。

サーバとの通信に用いるデータのタイプを明示的に指定することもできます。データタイプの指定は、dataTypeオプションを使用して次のように行います。指定できるデータタイプとしては「JSON」や「JSONP」、「HTML」などがあります。以下の例では、「HTML」を指定しています。

サンプルコード[JavaScript]:データタイプとしてHTMLを指定

$.ajax({ url:"http://example.com/html5", dataType:"html" success:funciton(d){ alert(d); }, error:function(d){ alert("error"+d); } });

以上が、Ajaxによる基本的な通信方法になります。

PhoneGapアプリからAjax通信を実行する

続いて、PhoneGapアプリ内からAjax通信を行うケースについて考えてみましょう。PhoneGapで通信を行う場合にも基本的な手順は変わりませんが、以下のような要件を満たしたい場合にはコードを工夫する必要が出てきます。

  1. アプリ内の入力フォームから取得したデータをサーバに送信したい。
  2. 通信先のURLはアプリからの参照のみを受け付けるようにして、一般には公開したくない。

まずはこの2つの機能を実現する方法を、それぞれ個別に考えてみます。

データをPOSTメソッドで送信する

会員登録を行ったり、アプリ内で使用したデータ(例えばゲームのスコアなど)をサーバに保存した場合などには、HTTPのPOSTメソッドを用いてデータを送信する必要があります。jQueryの$.ajax()メソッドでは、typeオプションとdataオプションを使うことで、POSTによるデータの送信を行うことができます。

まず、typeオプションの値には"POST"を指定します。指定しない場合にはGETでの送信となります。
そして、dataオプションの値の指定方法は2つあります。

一つ目は、送りたいデータを「キー=値」の形式で指定する形です。例えば「Arai」という値を「name」というキーに関連付けて送るコードは次のようになります。

サンプルコード[JavaScript]:POSTメソッドによるデータ送信

$.ajax({ url:"http://example.com/html5", type:"POST", data:"name=Arai", success:function(d){ alert(d); }, error:function(d){ alert(d); } });

このデータを受け取るサーバ側のコードは、例えばPHPであれば次のようになります。

サンプルコード[php]:サーバ側のPHPコードの例

<?php $name = $_POST['name']; // $nameには"Arai"が入る ?>

このような形でデータを受け取り、データベースに保存するなどの処理を行えばいいわけです。

また、データを複数送信する場合にはdataオプションの値を「キー=値&キー=値」という風に、「&」により送信データをつなげる形で指定します。
下記の例では、「Arai」という値を「name」というキーに関連付け、さらに「28」という値と「age」というキーに関連付けています。

サンプルコード[JavaScript]:複数のデータをPOSTメソッドで送信

$.ajax({ url:"http://example.com/html5", type:"POST", data:"name=Arai&age=28", success:function(d){ alert(d); }, error:function(d){ alert(d); } });

dataオプションの値の指定方法の2つ目は、{キー:値,キー:値}という風に、JSON風に指定する形です。
上記と同様に、「Arai」という値を「name」というキーに関連付け、さらに「28」という値と「age」というキーに関連付ける場合は以下のようになります。

サンプルコード[JavaScript]:JSON風のフォーマットで送信データを指定

$.ajax({ url:"http://example.com/html5", type:"POST", data: {'name': 'Arai', 'age': '28'}, success:function(d){ alert(d); }, error:function(d){ alert(d); } });

Basic認証を使用する

サーバ側で展開しているサービスを一般に公開することなく、特定のアプリやユーザからのアクセスのみ受け付けるようにするもっとも基本的な方法は、Basic認証を利用することです。Ajax通信でBasic認証をパスするためには、以下のようにusernameオプションおよびpasswordオプションでユーザ名とパスワードを指定する必要があります。

サンプルコード[JavaScript]:AjaxによるBasic認証

$.ajax({ url:"http://example.com/html5", username:"BASIC_USERNAME", // BASIC_USERNAMEはBasic認証に使用するユーザ名に置き換えてください password:"BASIC_PASSWORD", // BASIC_PASSWORDはBasic認証に使用するパスワードに置き換えてください success:function(d){ alert(d); }, error:function(d){ alert(d); } });

あるいは、前述したbeforeSendというイベントを利用して、サーバに対するリクエストヘッダを指定する形でも実装することができます。その場合は、beforeSendイベントに対するコールバック関数の引数としてXMLHttpRequestオブジェクトが渡されるので、setRequestHeader()メソッドを利用することでリクエストヘッダを設定することができます。

setRequestHeader()メソッドとは、XMLHttpRequestオブジェクトに含まれるメソッドの一つで、「setRequestHeader(キー、値)」の形で、各種リクエストヘッダを設定することができます。Basic認証の場合は、キーを「Authorization」、値を「Basic ユーザー名:パスワード」という形で指定します。

サンプルコード[JavaScript]:beforeSendイベントを利用したリクエストヘッダの指定

beforesend:function(xhr){ xhr.setRequestHeader("Authorization", "Basic " + "BASE64_USERNAME_AND_PASSWORD"); }

注意が必要なのは、ユーザ名とパスワードをBase64エンコードして渡さなければいけないという点です。まず、ユーザ名とパスワードを「:」でつないだ形の文字列として用意します。ユーザ名が「adc」、パスワードが「phonegap」であれば、「adc:phonegap」という具合です。この「adc:phonegap」をBase64エンコードしたものを、上記コードのBASE64_USERNAME_AND_PASSWORDの部分に記述してください。

ただし、JavaScriptには標準でBase64エンコードを行える関数がないので、自作して動的に変換するか、Webサービスなどを利用して事前に変換してから記述するといった作業が必要になります。ユーザー名とパスワードを動的に変換しなければならないという場面は多くないので、PhoneGapアプリであれば事前に変換したものを記述しておく形で問題ないでしょう。また、通常のウェブサイトはJavaScriptファイルは閲覧可能な状態にあるので、ファイル内に直接記述することはセキュリティ上も望ましくありません。

Base64エンコードする簡単なスクリプトはPHPの場合以下のようになります。

サンプルコード[php]:Base64エンコードを行うPHPコードの例

<?php $user_pass = $_GET['user_pass']; echo base64_encode($user_pass);

上記スクリプトにより得られた文字列を使い、Ajaxを実施する場合のコードは以下のようになります。

サンプルコード[JavaScript]:beforeSendイベントを利用したBasic認証

$.ajax({ url:"http://example.com/html5", beforesend:function(xhr){ // BASE64_USERNAME_AND_PASSWORDにはBase64エンコードしたユーザ名:パスワードを記述してください。 xhr.setRequestHeader("Authorization", "Basic " + "BASE64_USERNAME_AND_PASSWORD"); }, success:function(d){ alert(d); }, error:function(d){ alert(d); } });

Basic認証とPOSTによるデータ送信を組み合わせる

続いて、Basic認証とPOSTメソッドによるデータ送信を組み合わせる方法を考えてみましょう。それぞれの方法が分かっているので、これらを組み合わせて次のようにオプションを指定すれば実現できます。

サンプルコード[JavaScript]:Basic認証とPOSTメソッドによるデータ送信

$.ajax({ url:"http://example.com/html5", type:"POST", data:"name=Arai", username:"BASIC_USER", password:"BASIC_PASSWORD", success:function(d){ alert(d); }, error:function(d){ alert(d); } });

以下は、ユーザー名とパスワードをフォームに入力し、送信ボタンを押した際にサーバに入力内容がPOSTされるPhoneGapアプリケーションの例です。通信先の「http://html5dev.jp/phonegap-sample/html5.php」はPOSTで送られてきた、userとpasswdの値をただJSON形式に変えてレスポンスするだけのプログラムです。

サンプルコード[JavaScript]:サーバ通信を行うPhoneGapアプリの例

<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ADC Sample</title> <script type="text/javascript" charset="utf-8" src="cordova.js"></script> <script type="text/javascript" charset="utf-8" src="http://code.jquery.com/jquery-1.8.1.min.js"></script> <script> function ajaxSendMethod() { $.ajax({ url: 'http://html5dev.jp/phonegap-sample/html5.php', type: 'POST', username: 'phonegap', password: 'testapp', data: {'user': $('#username').val(), 'passwd': $('#password').val()}, dataType: 'json', success: function(d) { console.log(d); alert('ユーザー名:' + d.user + '\nパスワード:' + d.passwd + '\nがサーバに送信されました。'); }, error: function(d) { alert(d); } }); } </script> </head> <body> <h1>Ajax Sample</h1> <label for="username">ユーザー名</label><input type="text" id="username"><br/> <label for="password">パスワード</label><input type="password" id="password"><br/> <button onclick="ajaxSendMethod()">送信</button> </body> </html>

PhoneGapを使ったアプリにおけるサーバとの通信は、PhoneGapの設定ファイルを変更する以外は通常のAjaxによる非同期通信となんら変わるところがありません。

WebサービスなどでAjaxを実装された経験をお持ちの方であれば全く苦労することなく実装できますし、経験をお持ちのない方であっても、本記事で紹介したように非常に簡単に実装することが可能です。

是非、サーバと連携したPhoneGapアプリケーションを実装し、その手軽さを実感してください。