Android と iPhone のブラウザー戦争: 第 2 回 iPhone と Android に対応したブラウザー・ベースのアプリケーションを構築する

HTML 5、CSS、JavaScript、Ajax、そして jQuery を利用する

この記事は、iPhone と Android に対応したブラウザー・ベースのアプリケーションを開発する方法を説明する 2 回シリーズ「Android と iPhone のブラウザー戦争」の第 2 回です。第 1 回では、iPhone および Android ブラウザーの中核にあるブラウザー・エンジンである WebKit を紹介しました。今回の記事ではさらに詳細を掘り下げ、iPhone ブラウザーと Android ブラウザーの両方で実行されるネットワーク管理アプリケーションを構築します。このアプリケーションを例に、モバイル・ブラウザーでのリッチなアプリケーション・エクスペリエンスを実現する上で重要な 2 つの技術、すなわち、ブラウザーのローカル SQL ストレージと Ajax について説明します。さらに、このアプリケーションではよく使用されている人気の JavaScript ライブラリーである jQuery も利用します。

Frank Ableson, Software designer

Frank Ableson はニュージャージー州北部の起業家であると同時に、モバイルおよび組み込みアプリケーション・ソフトウェアを専門とするソフトウェア開発者でもあります。彼は Android によるアプリケーション開発に関する本の著者であり、組み込みシステムとワイヤレス通信、そしてカー・エレクトロニクスにプロとしての関心を持っています。彼の最大のファンは、彼の妻の Nikki と彼らの子供達です。



2010年 1月 05日

はじめに

これまで、充実した機能を備えたモバイル Web アプリケーションの開発には数々の障害が伴っていました。しかし、事態は急速に変わりつつあります。ネットワーク速度が十分でないという問題は解消されたわけではないものの、3G 技術が携帯電話で広く利用できるようになったことにより、この問題は大幅に改善されました。それと同じく、ユーザー・インターフェースは iPhone を筆頭に、飛躍的に改善され、Android が革新的な設計で勢いに乗っているなか、強力な WebKit エンジンが最高の HTML および CSS レンダリングを実現するようになっています。ユーザーに時代遅れのモバイル UI を提供するのでは、もはや職務を全うしたとは言えません。

デスクトップ・ブラウザーのエクスペリエンスと同様、ローカル・データベース・ストレージがブラウザーで利用できるようになったことをきっかけに、モバイル Web アプリケーションもある種のルネサンス期を迎えました。次世代のモバイル Web アプリケーションに力を与えているもう 1 つの技術は、Ajax です。Ajax は JavaScript を使用してサーバー・サイドのページを呼び出し、特定のデータ要素を HTTP によって取得することによって、Web ページ全体を取得して再レンダリングする必要をなくすという手法です。Ajax の動作は非同期であるため、モバイル Web アプリケーションの機能は飛躍的に向上する結果となっています。

この記事でターゲットとするのは iPhone と Android です。開発に役立つよう、サンプル・アプリケーションはデスクトップ上の Safari でもテストします。Safari は、同じく WebKit をベースとしていることから、WebKit Inspector アプリケーションを有効に活用できるため、開発を迅速化し、優れたデバッグ支援を提供する理想的な開発プラットフォームとなります。


サンプル・アプリケーション

コードの詳細を説明する前に、サンプル・アプリケーションの目標について考えてみましょう。このネットワーク監視/管理アプリケーションで達成したい目標は何でしょうか。

顧客用の Web サイトを (内部または外部に関わらず) 管理した経験があるなら、Web サイトが落ちているという知らせを受け取ったことがあると思います。サイトが落ちているという事態は、自動化された事前対策用監視ツールから通知されることもあれば、これは望ましくないことですが、「サイトが落ちているので、すぐに調べて連絡してほしい」という顧客からの E メールや電話で知らされることもあります。

サイトが落ちていると聞いて、通常まず初めに行うことは何ですか?それは、ブラウザーを立ち上げて、ホーム・ページをロードしてみることです。おそらく停電が、ある特定の場所からの接続性に関係していたのかもしれません。これはときどきあることなので、詳細を調べた結果、実はサイト自体の問題ではないと判明する前に、停電の関与を調べる価値はあります。

基本的なクライアント接続性の問題ではないことがわかったら、サイトのトリアージで次に踏むべきステップは、ファイルシステムのリソースや使用可能なメモリー、各種の接続、最後のエラー・メッセージなどといった重要な情報を集めることです。情報を収集するためには、一般にリモート・デスクトップや SSH セッションでサーバー自体にアクセスしなければなりません。しかし、あなたが席から離れているとしたらどうなるでしょうか。

「サイトが落ちている」という知らせは受け取って嬉しいものではありませんが、決まってこの知らせを受け取るのは、オフィスから外出していて通常のインターネット接続を使えない一番都合の悪いときであったりします。これにはかなりの無力感を覚えるはずです。そのうち、あるサイトに障害が発生するのは、よくある問題のいずれかが原因となっていることがわかってきます。例えば外部リソース (データベースやサード・パーティーの支払処理装置など) が使用できなかったり、ファイル転送に失敗したために、Web サイトの一部に適切な情報が表示されなかったり、古い情報が表示されたりするといった問題です。対処しなければならない問題が何であろうと、問題を最初に診断する際にはいくつかの基本統計情報が役立ちます。これらの統計情報、つまりパフォーマンス指標はサイトごとに異なっているからです。そこで、問題に対処するための支援ツールを作成するというのが、この記事で取り上げるアプリケーションの目的です。

ここで説明するアプリケーションは、外出中でも Web サイトの問題を診断できるように支援することを目的に設計します。iPhone または Android 搭載機器を持っていれば、武器を手にしたのと同じことです。これらの強力なプラットフォームの機能は、Web サイトの管理を支援するために活用することができます。


設計についての検討

このサンプル・アプリケーションは、できる限りサーバーのデータベースに依存しないように設計します。つまり、サード・パーティーのサービスにアカウントを作成しなくても、アプリケーションを実行できるようにします。このアプリケーションは、ユーザーが Web ページを 1 度ダウンロードすれば、ユーザーのブラウザーからローカルに実行できるように作成するつもりです。当然、ユーザーがページにブックマークを付けて適宜最新の状態に更新すれば、その後アプリケーションに追加された新しい機能を取得できるようにします。ただし、すべてのデータはモバイル機器の SQL データベースにローカルに保存されます。

このようなデータをサーバーのどこかに保存すれば確かにメリットはありますが、複数のユーザーのデータを管理および保存できるようにする機能は、この記事の範囲には含まれません。ここでの第一の関心事は、ローカル・ストレージと Ajax を活用して実用的で便利なアプリケーションを作成することだからです。アプリケーションを拡張するために考えられる次のステップについては、記事の締めくくりとして説明します。

このアプリケーションのコードは 2 つの異なるグループに分けられます。一方のグループは、モバイル機器上で実行されるコードです。このコードには以下のファイルを組み込みます。

  • アプリケーションの骨組みとなる index.html ファイル。
  • アプリケーションの機能の大部分が含まれる netmon.js という名前の JavaScript ファイル。
  • JSON 関連のルーチンが含まれる json2.js という名前のもう 1 つの JavaScript ファイル。
  • スタイル情報が含まれる複数の CSS ファイル。第 1 回では、スタイル情報のほとんどは 1 つの主要な CSS ファイルに含まれていましたが、今回は特定のプラットフォームでのアプリケーションのルック・アンド・フィールを改善できるように、それぞれの機器に固有の CSS ファイルを用意します。
  • DOM 操作および Ajax クエリーを支援するための jquery.js ライブラリー・ファイル。

もう一方のグループはサーバー上で実行されるコードで、管理対象のサイトごとに固有のコードです。このコードの詳細はそれぞれの実装によって異なりますが、最終的な内容は必ず、プロパティー名の項目 (名前と値のペアの配列) をはじめとする少数の特定プロパティーが含まれる JSON (JavaScript Object Notation) オブジェクトとなります。この JSON オブジェクト内のデータが、アプリケーションのブラウザー内でのレンダリング方法を指示します。さらに、名前と値のペアが各サイトに固有の重要な運用データを指定し、(願わくは) 状況を素早く診断するために必要な情報を提供して、スタッフが迅速に問題を見つけて解決できるようにします。


アプリケーションの作成

まずはこのアプリケーションのデータ・モデルを検討するところから取り掛かります。データ・モデルの大体の感じをつかんだ上で、データを操作してこのアプリケーションに生命を吹き込むコードを検討します。

データ・モデル

ブラウザーを介してモバイル機器に保存されるデータは、HTML 5 データベース、つまりブラウザーによるアクセスが可能な SQL データベース・ストアに保存されます。ブラウザー・ベースの SQL データに関する仕様はまだ流動的で、その詳細は現在も調整中です。けれども実際面から言うと、iPhone、Android、そしてその他の WebKit 対応の環境では現在すでに使用できるようになっています。このデータベースの機能は根本的に、ベースとなる SQLite 実装との JavaScript インターフェースです。サンプル・データベースには、tbl_resources という 1 つのテーブルしか含まれていません。

このテーブルは、サンプル・アプリケーションが実行時に使用するデータを真似ています。このデータは基本的に JSON オブジェクトの配列で、各オブジェクトには以下の情報が含まれます。

  • サイトの名前。
  • サイトのホーム・ページの URL。
  • サイトの基本統計情報の URL。ここでは ping URL と呼びます。
  • サイトの現在のステータス。OK または BAD のいずれかです。
  • サイトの現在の要約情報。これは、サイトの現在の状態を記述する短いテキストで、例えば「データベースが落ちています」のようになります。
  • 名前と値のペアの配列。名前と値のペアには、サイトの現行の運用状態を説明するのに役立つサイト固有の詳細が含まれます。これらの値は、サイトが落ちていないとしても役立つ場合があることに注意してください。特定の要素に、近い将来発生しそうな問題を示すデータが含まれることもあります。

リスト 1 は、ある特定のサイトを表す JSON オブジェクトの例です。

リスト 1. サイトを表す JSON オブジェクト
    [
      {
         name : 'msi-wireless.com',
         homeurl : 'http://msiservices.com',
         pingurl : 'http://ibm.msi-wireless.com/mobile2/netmon.php',
         status : 'OK',
         summary : 'Everything is fine...',
         items :
         [
          {name : 'DiskSpace', value : '22.13 GB'},
          {name : 'Database Up?', value : 'Yes'}
         ]
      }
   ]

データベースの役割はデータを永続化することですが、操作は JSON オブジェクトが含まれる配列を使用して行われ、データベースが絶えず参照されることはありません。このストラテジーは、JavaScript でコードを単純化するため、そしてデータベースでのデータ入出力回数を最小限にするために実装されています。ただし多数のデータ要素を使用するアプリケーションの場合は、データベースを直接操作するか、あるいはある種の「ページ化」したやり方をした方がよいかもしれません。この「ページ化」したやり方では、データベースから多数の要素を一度に取得し、その取得した全要素のうちの一部を JavaScript の配列で表すように要素の「ウィンドウ」を設けます。

図 1 に、データベースの構造といくつかのレコードのスナップショットを示します。Safari/WebKit ブラウザー・プラットフォームの一部となっている Web Inspector を使用すれば、このようにデータベースを表示することができます。これが、WebKit が強力な開発手段となっている理由の 1 つです。以下の図で示しているのはデスクトップ上の Web Inspector ですが、すべてのコードは iPhone と Android でも同様に、正常な動作をします。

注: このコードのターゲットは Android V2.0 でした。その後、Android の WebKit 機能セットはリリースごとに完成度を高めています。

図 1. データベースの構造といくつかのレコードのスナップショット
データベースの構造といくつかのレコードのスナップショットを示すスクリーンショット

データ要素の概要がわかったところで、次はこれらのデータ要素をサンプル・アプリケーションで管理する方法について見て行きます。


クライアント・サイド — デフォルト・ビュー

アプリケーションのデフォルト UI は、管理対象のサイトの一覧をステータスの値でソートしたものです。ステータスが OK でないサイトは、一覧の先頭に表示されます (図 2 を参照)

図 2. ステータスが OK でないサイト
ステータスが OK でないサイトを表示する画面

この画面からわかることは、管理対象のサイトは 3 つあり、現在、そのうちの 2 つのサイトに問題があることです。サイトの状態が良好であれば、その status プロパティーは OK となるので、要約情報フィールドを表示せずに、サイトの名前を黒のテキストで表示します。status プロパティーが BAD の場合はサイトの名前の隣に要約情報を表示します。要約情報のレンダリング属性は、CSS ファイル内の BAD という名前のスタイルによって指定されます (この例の場合、赤いテキスト)。詳細については、netmon.css ファイルを参照してください。このアプリケーションの完全なソース・コードは「ダウンロード」セクションに用意されています。

エントリーをクリックすると、そのエントリーの詳細情報の表示と非表示が切り替わります。図 2 に示されているように、各エントリーには有効な 3 つのリンクがあり、その下にホームの URL と Ping URL のロケーションが続きます。さらにその下にあるのがサイトの詳細を記述する部分です。つまり、そのサイトに必要な条件を表す名前と値のペアが表示されます。

上記の例では、ibm demo 2 というサイトの要約情報として「No more coffee? (もうコーヒーはいりませんか?)」という内容が表示されています。これはもちろん技術的な緊急事態というわけではありませんが、愉快な例としてこの例を検討してみましょう。このエントリーの下にある「Details (詳細)」セクションに目を移すと、このサーバーの状態の背後にある基本統計情報、すなわちコーヒー・ポットが空になっているということ、が示されています。

この画面では、ホーム・ページへのリンクが有効になっているので、このリンクをクリックすると、新しいブラウザー・ウィンドウが立ち上がります。2 番目の「Refresh (更新)」リンクをクリックすると、最新の状態のデータに更新することができます。データ更新のステップについては、この後すぐに説明します。

このエントリーを削除するには、3 番目の「Remove (削除)」リンクを選択します。すると、簡単な確認用のダイアログを表示する window.confirm() が実行されて、この操作は元に戻せないけれども、操作を続行してもよいかという確認メッセージが表示されます。


クライアント・サイド — HTML

このリストを作成するには、2 つのファイルを詳しく調べる必要があります。1 つは index.html ファイル (リスト 2 に記載)、そしてもう 1 つは netmon.js (リスト 3 に記載) です。この記事では、説明に伴っていくつかのコード・スニペットを記載しますが、完全なソース・コードが必要な場合は「ダウンロード」セクションを参照してください。

前回に引き続き、モバイル向けの WebKit のメタタグである viewport を指定して、ブラウザーにページのレンダリング方法を指示できるようにします。また、特定の機器をターゲットとするために、一部の JavaScript を選択的に使用して特定の CSS ファイルを指定します。

今回の index.html ファイルで新しくなっている点は、いくつかの JS ファイルと併せて「ローカル」の JavaScript ファイルをいくつか組み込んでいることです。この index.html ファイルの最後には、ID が entryform に設定された新しい HTML div 要素があります。この要素に、新しいエントリーをアプリケーションの中から直接追加するために必要な要素が含まれています。従来の手法では、新規エントリーを追加するには別の HTML ページをロードしなければなりませんでしたが、今ではその必要はありません。前に述べたように、このアプリケーションの設計目標の 1 つは、他のサーバー・ベースのツールを使用して監視対象サイトの外部でデータを操作および保存しなくても済むようにすることです。リスト 2 に、JavaScript ファイルを組み込んでいるコードの部分を index.html から抜粋して示します。

リスト 2. index.html
<link rel="stylesheet" href="netmon.css" type="text/css" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="netmon.js"></script>
<script type="text/javascript" src="json2.js"></script>

<script type="text/javascript">
   if (navigator.userAgent.indexOf('iPhone') != -1) {
      document.write('<link rel="stylesheet" href="iphone.css" type="text/css" />');
   } else if (navigator.userAgent.indexOf('Android') != -1) {
      document.write('<link rel="stylesheet" href="android.css" type="text/css" />');
   } else {
      document.write('<link rel="stylesheet" href="desktop.css" type="text/css" />');
   }

クライアント・サイド — 一覧へのデータの取り込み

データはローカル・データベースから抽出されて、サーバー・エントリーの一覧に表示されます。この一覧を作成するには、データベースをオープンし、SQL クエリーを実行してデータベース・テーブルのなかにあるすべての項目を取得します。

この種のアプリケーションで一般的に使われる手法は、テーブルをオンザフライで作成するというものです。けれども思い出してください。外出している最中には、傍で手を貸してくれる DBA がいません。そのためこのアプリケーションではすべての作業をアプリケーション自体で行う必要があります。リスト 3 に、netmon.js のソースを記載します。このファイルには、以下のさまざまな項目が実装されています。

  • netmonResource オブジェクトのデータ型コンストラクターの定義。
  • アプリケーションがデータベースおよび監視対象の Web サイトとやりとりする際に必要となる一連の関数。netmon 名前空間に実装されるこれらの関数には、以下のものがあります。
    • dbHandle — データベースとの接続を管理するために使用する関数。
    • initialize — データベースを作成/オープンし、管理対象のサーバーの一覧を取得するために使用する関数。リスト 3 に記載されているこの関数は、指定のデータベースがまだオープンされていない場合はオープンを試行し、オープンされたデータベースに対してクエリーを実行します。また、データベースに指定のテーブルが存在しない場合は、該当するテーブルの作成プロセスを開始します。
    • createResourcesTable — 必要なデータベース・テーブルを作成し、デモ用に 1 つのデフォルト・エントリーを作成する関数。
    • addEntry — 新規エントリーをデータベース・テーブルに挿入する関数。
    • deleteEntry — データベース・テーブルからエントリーを削除する関数。
    • refreshEntry — Ajax 呼び出しによってエンントリーの Ping URL を取得し、エントリーを最新の状態に更新する関数。
    • Resources — データベース・エントリーの「キャッシュ」が含まれる配列。他のいくつかの関数は、データベースに直接作用するのではなく、この配列に作用します。
    • Render — HTML ストリングを返す関数。各サーバー・エントリーをどのように表示するかについての規則を考案し、その規則に従ってこのストリングのフォーマットが設定されます。新しいフォーマットを思い付いた場合には、必要な CSS スタイルとともにそのフォーマットを、この関数に実装します。

リスト 3. netmon.js

netmon 名前空間にはサイトを実装するために必要なロジックの大部分が含まれており、それを index.html ファイル内のいくつかのヘルパー関数によって補っています。次のセクションでは、データベースに新規エントリーを追加するタスクについて見て行きます。


クライアント・サイド — サイトの追加

このアプリケーションは、ユーザーにとって関心のある 1 つまたは複数のサイトの一覧を管理します。それぞれのサイトごとに、最初に以下の情報を収集して保存します。

  • サイトの名前
  • ホームの URL
  • Ping URL

上記の情報を収集および保存するために、単純なフォームを作成します。このフォームには 3 つのフィールドとそれぞれのラベル、そしていくつかのボタンがあります (図 3 を参照)。

図 3. 単純なフォーム
単純なフォームを表示する画面

このフォームのコンテンツは、実際にはサイトの一覧と同じ index.html ページのなかにあります (リスト 2 を参照)。サイトの一覧を表示するデフォルトのビューとこの新規サーバーの追加フォームとの間で表示を切り替えるには、jQuery のマジックを使います。サイト・エントリーの一覧は、ID が mainContent の HTML div 要素に含まれる一方、フォームは ID が entryform の HTML div (最初は非表示) に含まれます。この 2 つの div 要素の可視性は常に相互排他的です。この 2 つの要素の可視性を逆にするには、リスト 4 の addNewEntry 関数に示されているように、それぞれの要素で toggle という名前の jQuery メソッドを呼び出します。

リスト 4. addNewEntry 関数
function addNewEntry() {
   $("#entry_name").val("");
   $("#entry_homeurl").val("");
   $("#entry_pingurl").val("");

   $("#mainContent").toggle();
   $("#entryform").toggle();
}

新しいサーバー・エントリーが作成されたら、そのエントリーをデータベースに保存し、サーバーの一覧を最新の状態に更新して新規エントリーの追加を反映しなければなりません。それにはまず、ユーザーが「Save」ボタンを選択します。すると index.html に実装された JavaScript 関数 saveEntryが呼び出され、この関数によって netmonResource という名前の新規 JavaScript オブジェクトが作成されます。すべてのフィールドが正しく入力されていることを確認した後、データベースへの保存操作を開始します。新規エントリーを保存するために呼び出すのは、netmon.addEntry です。その後、2 つの div 要素でもう一度 toggle を呼び出してエントリーのリストを再表示します。注: ここでは URL を確認する完全な正規表現を実装しませんでしたが、この正規表現を実装しておくのが得策です。

以下の説明については、リスト 3 の netmon.js を参照してください。

JavaScript で SQL データベース・インターフェースを使用するには、2 つの基本ステップが必要です。まず、データベースがまだオープンされていない場合には、これをオープンする必要があります。このアプリケーションでは、initialize 関数のなかでデータベースをオープンします。データベース内に新規レコードを作成する方法については、リスト 5 に記載する addEntry 関数のコードを調べてください。SQL トランザクションを開始するには <databasehandle>.transaction(function (tx) {tx.executeSql()}); を呼び出します。この例でのデータベース・ハンドルは netmon.dbHandle です。

executeSql 関数は以下の 4 つの引数を取ります。

  1. SQL 文。この文のすべてのパラメーター (フィールド値など) はプレースホルダー ? で表現されます。各 ? は、この関数に渡される 2 番目の引数に含まれている値の順序位置に基づいて置き換えられます。
  2. パラメーターとして使用される値の配列。これらの値が、最初の引数に含まれる SQL 文に示された ? プレースホルダーに置き換わります。
  3. SQL 文が正常に実行された場合に呼び出されるコールバック関数。このコールバック関数への引数には、トランザクション・ハンドルと結果セットが含まれます。
  4. SQL 文でエラーが発生した場合に呼び出されるコールバック関数。このコールバック関数への引数には、トランザクション・ハンドルとエラー・オブジェクトが含まれます。

リスト 5 に、netmon.addentry 関数を記載します。

リスト 5. netmon.addentry 関数

これで、エントリーを追加できるようになりました。一覧からエントリーを削除する場合も、追加操作とほとんど同じです。netmon.deleteEntry 関数を参照して、エントリーをデータベースから削除する方法を確認してください。

次に調べるのは、Ajax を使用してエントリーを最新の状態に更新する方法です。


クライアント・サイド — Ajax による更新

前述のとおり、Ajax は Web ページ全体を更新することなくサーバー・サイドのコンテンツを取得するための手法です。Ajax の実装に使用する基礎となる技術はブラウザーによって異なりますが、このアプリケーションでは JavaScript ライブラリーである jQuery を使用して基礎となる技術を覆い隠す手法をとっています。もちろんこの記事は iPhone と Android のブラウザー開発に関するものですが、現在、JavaScript ライブラリーを使用することは一般的に認められていて、奨励されてもいるほどです。jQuery では Ajax を簡単にプログラミングできることを知れば、皆さんもきっとこのライブラリーを使用することに賛成するはずです。

リスト 6 に記載する netmon.refreshEntry 関数には Ajax コードと、最終的なデータでデータベースを更新するコードが含まれています。

リスト 6. netmon.refreshEntry 関数

サーバーからデータを取得する方法としては、単純に $.get() を呼び出します。最初の引数は URL、2 番目の引数は呼び出しの完了時に呼び出す関数です。この例では、新しく取得したデータでデータベースを更新するために (リスト 3 の netmon.refreshEntry を参照)、前に説明したデータベースのスキルをいくつか使用しています。

jQuery には、パラメーターを Web ページに渡すとともに、返されてくるはずのデータの種類に関するヒントを与えるための「フォームに埋め込まれたデータ」を提供する機能もあります。jQuery の Ajax 関数について調べるには、「参考文献」を参照してください。アプリケーションのニーズによっては、さらに粒度を高めることもできます。

jQuery は JSON オブジェクトを直接取得する手段にもなりますが、皆さんが構築する他のアプリケーションにも一般的に適用できるように、ここでは「汎用」の Ajax 関数を使用することにします。

サーバーからデータを受け取った時点で、データを JavaScript オブジェクトに変換し、そのプロパティーにアクセスできるようにしなければなりません。それには、eval という JavaScript 関数で、var object = eval(<json text>); を実行するだけで変換することができます。

ここまでのところで、クライアント・サイドの機能については順調に作業が進みました。後はサーバー・サイドのページに対処するだけです。サーバー・サイドのページでは、このサンプル・アプリケーションで処理することになる JSON を生成します。


サーバー・サイド — 独自の監視ページの作成

サンプル・アプリケーションに返さなければならない JSON 構造についてはすでに説明したとおりですが、JSON 構造は一体どのようにして生成されるのでしょうか。短く答えると、それはあなた次第です。.NET 技術で作業したいというのであれば、.aspx ページを生成してデータを動的に生成することができます。あるいは、定期的に実行されるようにスケジューリングしたシェル・スクリプトにテキスト・ファイルを生成させて、単にそのファイルを取得するだけで更新後の最新ステータスを調べられるようにするという方法もあります。要するに、アプリケーションは 1 つの URL を指定すれば JSON オブジェクトを取得できるようでなければなりませんが、JSON を生成するというタスクを実現する方法については任意に選べるということです。

リスト 7 に記載するサンプル PHP ファイルは、ファイルの一覧を生成し、その一覧から error.txt という名前のファイルを探して、このファイルについて調べます。このファイルの中身が空でなければ、何らかの問題があると見なし、ステータスの値が BAD である JSON オブジェクトを組み立て、error.txt ファイルの内容を使って要約情報のプロパティーを更新します。

リスト 7. サンプル PHP ファイル
<?
$filecount = 0;
$statusValue = "OK";
$summaryValue = "No Error";
?>
[
{
items : [
{ "name" : "Date", "value" : "<? echo date("m/d/y H:m:s"); ?>"  },
<?
foreach (new DirectoryIterator("./data") as $fileInfo) {
   if ($fileInfo->isDot() || $fileInfo->isDir()) continue;
   $filecount++;
   echo "{\"name\" : \"".$fileInfo->getFilename()."\",\"value\" : 
\"".$fileInfo->getSize()."\"},";
   if ($fileInfo->getFilename() == "error.txt") {
     if ($fileInfo->getSize() > 0) {
        $statusValue = "BAD";
        $fsize = $fileInfo->getSize();
        $fh = fopen("./data/".$fileInfo->getFilename(),"r");
        $summaryValue = fread($fh,$fsize);
        fclose($fh);
     }
   }
}
?>
 {"name" : "FileCount","value" : "<? echo $filecount ?>"}
],
"status" : "<? echo $statusValue ?>",
"summary" : "<? print str_replace("\n","",$summaryValue) ?>"
}
]

このコードは、エラー条件があると見なして以下のリスト 8 に記載する JSON データを生成します。

リスト 8. リスト 7 によって生成された JSON データ
[
    {
        "items" : [
            {
                "name" : "Date",
                "value" : "11/22/09 15:11:51" 
            },
            {
                "name" : "error.txt",
                "value" : "20" 
            },
            {
                "name" : "bad.html",
                "value" : "91" 
            },
            {
                "name" : "testfile.txt",
                "value" : "44" 
            },
            {
                "name" : "good.html",
                "value" : "87" 
            },
            {
                "name" : "FileCount",
                "value" : "4" 
            } 
        ],
        "status" : "BAD",
        "summary" : "the sky is falling." 
    } 
]

この例では、データが生成された日付、現在のファイル数、そしてファイルの一覧とそれぞれのファイルのサイズを提供しています。サーバーのタイムゾーンは、現在地のタイムゾーンとは異なる場合があることに注意してください。

error.txt の長さは 0 バイトではないため、このファイルの内容を読み込んで要約情報のプロパティーに割り当てます。これですべてです。このように、非常に基本的な監視スクリプトとなっています。

JSON の生成に取り組んでいるときに、ブラウザー・ベースのアプリケーションからコードを構文解析するのに苦労することがありますが、そのような場合には JSON 検証ツール (「参考文献」を参照) を使ってみてください。図 4 に、このエントリーがデスクトップ・ブラウザーにレンダリングされた様子を示します。

図 4. JSON 検証ツール
図 4 には、JSON 検証ツールが示されています。

図 5 に、iPhone で実行中のアプリケーションを示します。

図 5. iPhone で実行中のアプリケーション
iPhone で実行中のアプリケーションを示す図です。

図 6 に Android で実行中のアプリケーションを示します。この場合、サーバーの一覧の表示は少し異なります。

図 6. Android で実行中のアプリケーション
図 6 には、Android で実行中のアプリケーションが示されています。

これでアプリケーションは完成しました。とは言っても、新しく追加できそうな内容は常に思い付くものです。そこで最後となる次のセクションでは、読者の演習として残してある内容を紹介します。


次のステップ

このアプリケーションを改善するために考えられる新しい案は尽きることがありません。そこで、追加すると面白いと思われる内容を以下にいくつか記載します。

  • エントリーの編集機能を追加する (今のところ、「Add New (新規追加)」または「Delete (削除)」しか使えません)。
  • フォームのフィールド・エントリーを適切に検証するための正規表現を実装する。
  • アプリケーションから直接 E メールで情報を送信できるようにする。
  • サーバーにプロファイルを保存して、さまざまな機器で使用できるようにする。
  • PhoneGap や Appcelerator のようなツールを使ってこのアプリケーションをネイティブ・アプリケーションに組み込み、AppStore でアプリケーションを販売できるようにする。

まとめ

この記事では第 1 回で説明した基礎知識をベースに、SQL ローカル・ストレージと Ajax クエリーを使用して非常に機能的なモバイル Web アプリケーションを構築しました。このアプリケーションはサーバー・サイドにほんの少し手を加えるだけで、現在のネットワークを監視するための支援ツールとして使うことができます。

この記事を読んで、皆さんが iPhone と Android に対応した独自のモバイル・アプリケーションを構築する気になったことを願います。


ダウンロード

内容ファイル名サイズ
Part 2 source codeos-androidiphone2-browserwars2.zip31KB

参考文献

学ぶために

製品や技術を入手するために

議論するために

  • Eclipse に関する質問を投じる最初の場所として、Eclipse Platform newsgroups があります (このリンクをクリックすると、デフォルト Usenet ニュース・リーダー・アプリケーションが起動され、eclipse.platform が開きます)。
  • Eclipse newsgroups には Eclipse を利用し、拡張することに関心を持つ人達のために、さまざまなリソースが用意されています。
  • developerWorks blogs から developerWorks コミュニティーに加わってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=465678
ArticleTitle=Android と iPhone のブラウザー戦争: 第 2 回 iPhone と Android に対応したブラウザー・ベースのアプリケーションを構築する
publish-date=01052010