モバイル Web 用の Ajax アプリケーションを作成する

クロスブラウザーのスマートフォン Web アプリケーションを作成する

モバイル機器用のアプリケーション開発は、長年の間大いにもてはやされていましたが、コストばかりが高く、利益の少ない作業でした。しかし iPhone OS や Google の Android を使用した最新世代のスマートフォンでは、単に Web アプリケーションを作成すればよいだけの、はるかに単純な作業となりました。そのため、1 つのビルドをすべての機器に使用することができ、それによってコストを下げることができます。さらに良いことに、これらのハイエンド機器はすべて超最先端のブラウザーを搭載しており、高度な HTML、JavaScript、そして CSS がサポートされています。この記事では、最新のスマートフォンの機能と Ajax (Asynchronous JavaScript and XML) とをフルに活用したアプリケーションを作成する方法を学びます。その中で、これらの機器を最大限に活用する方法だけではなく、これらの機器の間の微妙な違いに対処する方法についても学びます。

Michael Galpin, Software architect, eBay

Michael_GalpinMichael Galpin は eBay のアーキテクトであり、developerWorks に頻繁に寄稿しています。彼は JavaOne、EclipseCon、AjaxWorld など、さまざまな技術カンファレンスで講演を行っています。彼が現在取り組んでいることを知るには、Twitter で @michaelg をフォローしてください。



2010年 3月 02日

はじめに

この記事では、Apple iPhone や Android ベースのスマートフォンを対象としたモバイル Web アプリケーションの作成方法について説明します。こうした機器で動作するモバイル Web アプリケーションは、通常のデスクトップ・ブラウザーを使っただけでは作成することはできません。作成できたとしても、少なくとも完全なアプリケーションにすることはできません。完全なアプリケーションを作成するには、エミュレーターまたは実際のモバイル機器が必要です。iPhone の場合には、iPhone SDK に含まれている iPhone エミュレーターが必要になります。この記事では iPhone SDK 3.1 を使用しました。Android の場合には、Android SDK が必要になります。Android SDK には Android Virtual Device マネージャーが含まれており、この Virtual Device マネージャーを使用することで、さまざまなバージョンの Android を実行する Android エミュレーターを作成することができます。この記事では Android SDK 2.1 を使用しました。この記事のコードの大半は JavaScript で作成されており、一部に HTML と CSS が使用されています。その一方で、このアプリケーションには Java™ コードで作成されたサーバー・サイドの部分がありますが、他の Web アプリケーションの場合と同様、この部分には任意のサーバー・サイド技術を使用することができます。この記事のアプリケーションを実行するためには、Java 1.6 が必要です。また、JAX-RS のリファレンス実装である Jersey と、関連するすべての JAR (Java Archive) ファイルも必要です (「参考文献」を参照)。


モバイル・ブラウザーと WebKit

モバイル機器には、かなり以前からさまざまな種類の Web ブラウザーが搭載されていました。しかし各種ブラウザーに対応したアプリケーションを開発するには、クロスブラウザーの問題に対処しなければならず、その作業は常に苦痛を伴うものでした。デスクトップ・ブラウザーの場合、さまざまなバージョンの Internet Explorer、Mozilla Firefox、Safari、等々の上で、HTML、JavaScript、そして CSS をまったく同じように動作させるために、朝から夜遅くまで長時間の作業を長い期間続ける必要がありました。それでもモバイル・ブラウザーの世界に比べれば、デスクトップ・ブラウザーはたいしたことがありません。従来、モバイル・ブラウザーには非常にさまざまなものがありました。各機器メーカーが独自のブラウザーを持ち、さらには同じメーカーであっても機器によってオペレーティング・システムや画面サイズ等々が大きく異なっていました。一部のブラウザーは WAP のみをサポートし、一部のブラウザーは HTML のサブセットをサポートし、また一部のブラウザーは HTML をフルにサポートする一方で JavaScript をサポートしない、といった状態です。

幸いなことに、状況は大きく変わりました。2010年 1月の時点で、米国でのモバイル機器によるインターネット・トラフィックの 80% 以上は iPhone 機器または Android 機器で行われています。この 2 つのオペレーティング・システムはどちらも WebKit を使用して HTML/CSS を描画するだけではなく、どちらも HTML 5 標準を積極的に採用した JavaScript エンジンを備えています。そうなのです。モバイルの世界で支配的な地位を占めるブラウザーが、同時にオープン・スタンダードを推進しているのです。これは皆さんのような Web 開発者にとって、非常に望ましい状況です。

しかしそれでもブラウザーの間には相変わらず違いがあり、iPhone や Android のブラウザーの異なるバージョン間にさえ違いがあります。特に Android の場合にはブラウザーごとに大きな違いがあります。2.0 よりも前のバージョンの Android では、Android ブラウザーは独自の Google Gears 技術を使用していました。現在は HTML 5 標準の一部となっている多くの技術革新を推進したという点で、Gears は評価に値します。ただしそれは、しばらくの間 HTML 5 標準の一部は Android ブラウザーでサポートされておらず、Gears を使うことで同じ機能を実現していた、ということです。この記事のすべてのコードは HTML 5 標準をベースにしており、Android 2.0 またはそれ以降、あるいは iPhone 3.0 またはそれ以降で動作します。今やこうした WebKit ベースの最新のブラウザーを活用する環境は整いました。では、こうした機器での Ajax について調べてみましょう。

モバイル・ブラウザーでの Ajax

デスクトップ Web アプリケーションの場合とまったく同じように、魅力的なユーザー・エクスペリエンスをモバイル Web アプリケーションに実現するための鍵として、通常は Ajax を使用する必要があります。もちろん、Ajax を使う理由はユーザー・エクスペリエンスのためだけではありません。Ajax を使った方が高速で効率的なのです。モバイル Web アプリケーションで Ajax を使う理由として、Ajax によるスピードと効率はデスクトップ Web アプリケーションの場合よりもはるかに重要です。モバイル Web アプリケーションではネットワーク遅延が非常に大きく、またブラウザー自体にもプロセッサー速度、メモリー、キャッシュ・サイズなどの点で大幅な制約があります。幸いなことに、標準ベースのブラウザーのみを考慮すればよくなったことで作業が容易になった、数あるものの中の 1 つが Ajax です。それを説明する前に、この記事で作成するアプリケーションが呼び出す、バックエンド・サーバーについて簡単に調べてみましょう。

作業を始める前に、Jersey、Xerces、Rome、そして Google App Engine SDK に必要な JAR ファイルをダウンロードし (「参考文献」のリンクを参照)、それらのファイルを WebKitBlog > war > WEB-INF > lib フォルダーにインストールする必要があります。それ以外の、このアプリケーションのソース・コードは、「ダウンロード」セクションからダウンロードすることができます。

WebKit ブログ

この記事のモバイル Web アプリケーションは、モバイル Web 開発に関するニュースを読み取る単純なアプリケーションです。現状では、このアプリケーションは WebKit の公式ブログから RSS フィードを単純にプルするだけですが、複数の RSS フィードを集約するように変更することも容易にできます。このアプリケーションは単純な Java Web アプリケーションであり、任意の Java アプリケーション・サーバーにデプロイすることができます。このアプリケーションのすべてのコードを示したものがリスト 1 です。

リスト 1. Feed クラス
@Path("/feed")
public class Feed {
    String surfinSafari = "http://webkit.org/blog/feed/";
    
    @GET @Produces("application/json")
    public News getNews(@DefaultValue("0") @QueryParam("after") long after) 
    throws Exception{
      URL feedUrl = new URL(surfinSafari);
      SyndFeedInput input = new SyndFeedInput();
        SyndFeed feed = input.build(new XmlReader(feedUrl));
        List<Item> entries = new ArrayList<Item>(feed.getEntries().size());
        for (Object obj : feed.getEntries()){
            SyndEntry entry = (SyndEntry) obj;
            if (entry.getPublishedDate().getTime() > after){
                Item item = new Item(entry.getTitle(), entry.getLink(), 
                            entry.getDescription().getValue(), 
                            entry.getPublishedDate().getTime());
                entries.add(item);
            }
        }
        return new News(feed.getTitle(), entries);
    }
}

このコードは Java の JAX-RS を使用して RESTful なサービスを作成しています。@Path アノテーションは、このサービスのエンドポイントを意味します。つまり、このサービスに対する相対 URL は /feed です。@GET は、このサービスが HTTP GET をサポートしていることを意味します。@Produces アノテーションは、このサービスが JSON フォーマットでデータを生成することを宣言しています。こうすることで容易にデータを JSON にシリアライズすることができます。getNews メソッドは after という 1 つのパラメーターを取ります。つまり、ある特定の日付より後のエントリーを取得します。この場合も JAX-RS のアノテーションを使って after パラメーターを after というクエリー・ストリング・パラメーターにバインドしています。値が何も指定されない場合には、デフォルト値の 0 を取得します。

リスト 1 に関するここまでの説明はすべて、サービスに対してルーティングとデータのシリアライズを設定する JAX-RS のアノテーションに関することでした。getNews メソッドの実際の本体は Rome パッケージを積極的に活用することで RSS を処理します。getNews メソッドは単純に最新の RSS フィードをダウンロードし、そのフィードをアプリケーションに必要なデータのみに変換します (データは Item クラスと News クラスによってモデル化されています)。唯一注意が必要な部分は、記事の公開日が long に変換され、ID として使われている部分です。こうすれば ID を使ってソートが行えるため、ID が非常に便利なものになります。これについては後ほど説明します。リスト 2 は News クラスを示したものです。

リスト 2. News クラス
@XmlRootElement
public class News {
    private String title;
    private List<Item> entries;
    // constructors, getters/setters omitted for brevity
}

News クラスが @XmlRootElement という JAXB アノテーションを使っていることに注意してください。このアプリケーションには XML はありませんが、JAX-RS は JAXB を活用することで自動的にシリアライズとデシリアライズを行っています。このクラスの中にあるものは、title プロパティーと、項目のリストのみです。リスト 3 は Item クラスを示したものです。

リスト 3. Item クラス
@XmlType
public class Item {
    private String title;
    private String link;
    private String description;
    private Long id;
    // constructors, getters/setters omitted for brevity
}

このクラスは、この Web アプリケーションで表示するものを示しています。News クラスの場合と同様、このクラスは JAXB アノテーションを使用しているため、このクラスを JAX-RS が JSON にシリアライズしてくれます。サーバー・サイド・コードの最後として、リクエストが JAX-RS にルーティングされるように Web アプリケーションを構成する必要があります。そのためには、このアプリケーションの web.xml ファイルを編集する必要があります (リスト 4)。

リスト 4. web.xml 構成ファイル
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <servlet>
        <servlet-name>WebKit Blog Servlet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.
ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>org.developerworks.mobile</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>WebKit Blog Servlet</servlet-name>
        <url-pattern>/resources/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <!-- Default page to serve -->
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    <mime-mapping>
        <extension>mf</extension>
        <mime-type>text/cache-manifest</mime-type>
    </mime-mapping>
</web-app>

この web.xml の大部分はボイラープレート・コードです。サーブレット宣言を見るとわかるように、このアプリケーションは JAX-RS のリファレンス実装である Jersey を使用しています。サーブレットの初期化パラメーターは Jersey に対し、org.developerworks.mobile パッケージをスキャンするように指示しています。これにより、Jersey はサービス・リクエストを処理するためのアノテーションが付いたクラスを探します。また、/resources/ にマッピングされるすべてのリクエストは Jersey サーブレットにマッピングされます。ここで最後に注意が必要な点は、このファイルの最後にある mime-mapping セクションです。これはマニフェスト・ファイルの MIME タイプであり、後ほど説明するオフラインの Web アプリケーションに対するキーです。これで、この Web アプリケーションが使用するバックエンドのサービスを理解できたので、このバックエンドを使用するフロントエンドを調べてみましょう。


Ajax を活用したユーザー・インターフェース

リスト 4 で、このアプリケーションには標準的な index.html ファイルがあることに気付いたと思います。index.html ファイルは、このアプリケーションのエントリー・ポイントです (リスト 5)。

リスト 5. index.html ファイル
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html manifest="application.mf">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>WebKit News</title>
    <meta name = "viewport" content = "width = device-width"/>
    <script type="text/javascript" src="index.js"></script>
  </head>
  <body onload="loadEntries()">
    <h1 id="title">Recent News About WebKit</h1><img 
id="loader" src="loading.gif"/>
  </body>
</html>

これは非常に単純な Web ページですが、ここにはいくつか非常に重要なものがあります。第 1 に、この文書の先頭でビューポートを設定していることに注目してください。こうすることでブラウザーに対し、コンテンツをズームインして機器上で見やすく表示するように指示しています。UI コードという点では、単にタイトルと画像のロードがあるだけで、他には何もしていません。それ以外のすべては JavaScript によって行われます。index.js ファイルの loadEntries 関数はデータをロードするための Ajax リクエストを行います。この関数を示したものがリスト 6 です。

リスト 6. loadEntries 関数
function loadEntries(){
    if (!window.JSON){
        var head = document.getElementsByTagName("head")[0];
        var jsScript = document.createElement("script");
        jsScript.setAttribute("src", "json2.js");
        jsScript.setAttribute("type","text/javascript");
        head.appendChild(jsScript);
    }    
      var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
        if (this.readyState == 4 &&this.status == 200){
                  var theFeed = JSON.parse(this.responseText);
                  var i = 0;
                  if (theFeed.entries){
                         var len = theFeed.entries.length;
                         for (i=0;i<len;i++){
                                addEntry(theFeed.entries[len - 1 -i], true);
                         }
                  }
                  var body = document.getElementsByTagName("body")[0];
                  body.removeChild($("loader"));
              }
    };
    var urlStr = "/resources/feed";
    xhr.open("GET", urlStr);
    xhr.send();        
}

この関数の最初の部分で、ちょっとした機能検出を行っています。ほとんどのブラウザーは JSON の構文解析とシリアライズのための関数を組み込みでサポートしています。この組み込み関数は json.org から入手できる JSON ライブラリーと同じです。ただしこの関数がない場合であっても、この関数のファイルをページに含めるだけで同じ機能を実現することができます。

その部分を除くと、これは非常に単純な Ajax コードです。Internet Explorer について心配する必要はないので、単純に XMLHttpRequest を直接作成することができます。ある関数に XMLHttpRequestonreadystatechange プロパティーを設定し、この場合はクロージャーを作成します。サーバーからレスポンスが返り (readyState = 4)、処理に問題がなかった場合には (status = 200 OK)、その JSON レスポンスを JSON.parse 関数を使って構文解析します。フィードの各エントリーに対し、addEntry 関数を呼び出します。addEntry は各エントリーの UI 要素を作成するための関数です。この関数を示したものがリスト 7 です。

リスト 7. addEntry 関数
function addEntry(e, prepend){
    var eDiv = document.createElement("div");
    eDiv.setAttribute("class", "item");
    var link = document.createElement("a");
    link.setAttribute("href", e["link"]);
    var title = document.createTextNode(e["title"]);
    link.appendChild(title);
    eDiv.appendChild(link);
    var button = document.createElement("input");
    button.setAttribute("type", "button");
    button.setAttribute("value", "Show");
    button.setAttribute("id", "button" + e["id"]);
    button.setAttribute("onclick", "showDescription('" + e["id"] + "')");
    eDiv.appendChild(button);
    var dDiv = document.createElement("div");
    dDiv.setAttribute("id", e["id"]);
    dDiv.setAttribute("class", "description");
    dDiv.setAttribute("style", "display:none");
    dDiv.innerHTML = e["description"];
    eDiv.appendChild(dDiv);
    var body = document.getElementsByTagName("body")[0];
    if (!prepend && body.childNodes.length > 1){
            body.appendChild(eDiv);
    } else {
            body.insertBefore(eDiv, body.childNodes.item(2));
    }
}

この関数のどの部分も、非常に標準的な DOM 操作です。唯一注意が必要な点は、この関数がエントリーを append または prepend できる、つまりエントリーを先頭に追加することも最後に追加することもできる点です。リスト 6 に戻ると、loadEntries 関数は最後に、グラフィックのロードを削除しています。基本的な Ajax 関数はこれですべてです。使用目的によってはこれで十分かもしれません。ただしこのアプリケーションはサーバーから大量のデータをダウンロードし、そのデータを構文解析する必要があります。より優れたアプリケーションにするためには、そしてモバイル Web アプリケーションの場合には、必ずローカル・キャッシュを使うようにする必要があります。


ローカル・ストレージを使ったキャッシング

ローカル・ストレージは HTML 5 仕様の一部であり、広くサポートされています。ローカル・ストレージには名前と値のペアによる単純なストレージ・メカニズムが用意されており、名前と値はどちらもストリングです。そのため、エントリーをローカル・ストレージに保存するための操作は単純です (リスト 8)。

リスト 8. ローカル・ストレージに保存する
function saveLocal(entry){
    if (!window.localStorage){
        return;
    }
    localStorage.setItem(entry["id"], JSON.stringify(entry));
}

この場合もブラウザーの機能を検出します。まず、ウィンドウ・オブジェクトに localStorage プロパティーがあるかどうかを HTML 5 仕様に従ってチェックします。localStorage プロパティーがある場合には、単純にエントリーの id をストアのキーとして使います。値としてはストリングを使う必要があるので、JSON.stringify 関数を使ってウィンドウ・オブジェクトをストリングにシリアライズします。これで、あとはこれらのデータをローカル・ストレージから読み取る関数があればよいだけです。この関数をリスト 9 に示します。

リスト 9. ローカル・ストレージからロードする
function loadLocal(){
    if (!window.localStorage){
        return [];
    }
    var i = 0;
    var e = {};
    var id = 0;
    var entries = [];
    for (i=0; i< localStorage.length; i++){
        id = localStorage.key(i);
        e = JSON.parse(localStorage.getItem(id));
        entries[entries.length] = e;
    }
    entries.sort(function(a,b) { 
        return b.id - a.id; 
    });
    return entries;
}

この関数も、まずローカル・ストレージが利用できるかどうかのチェックから開始しています。次に、ローカル・ストレージのすべてのデータに対して繰り返し処理を行います。ストレージの各値に対し、再度 JSON.parse 関数を使用してストリングをオブジェクトに戻します。次に、ローカル・ストレージからエントリーを取得する順序は保証されていないため、エントリーをソートします。これは降順のソートであり、最新のエントリーが最初になります。最後に、これでローカル・ストレージに保存する関数とローカル・ストレージからロードする関数が得られたので、あとはこれらの関数を先ほどの loadEntries 関数の中に統合すればよいだけです (リスト 10)。

リスト 10. loadEntries にキャッシングを追加する
function loadEntries(){
    // check for JSON object
    var localEntries = loadLocal();
    var newest = 0;
    if (localEntries.length > 0){
        newest = localEntries[0].id;
    }
    var i = 0;
    for (i=0;i<localEntries.length;i++){
        addEntry(localEntries[i]);
    }
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
        if (this.readyState == 4 && this.status == 200){
                  var theFeed = JSON.parse(this.responseText);
                  var i = 0;
                  if (theFeed.entries){
                         var len = theFeed.entries.length;
                         for (i=0;i<len;i++){
                                addEntry(theFeed.entries[len - 1 -i], true);
                                saveLocal(theFeed.entries[len - 1 -i]);
                         }
                  }
                  var body = document.getElementsByTagName("body")[0];
                  body.removeChild($("loader"));
              }
    };
    var urlStr = "/resources/feed?after=" + newest;
    xhr.open("GET", urlStr);
    xhr.send();    
}

先ほどとの大きな違いは、最初にローカル・データをロードしていることです。最新のエントリーを判断し、サーバーを呼び出す際に、このパラメーターを使用します。こうすることで、サーバーは、まだローカル・ストレージの中にないエントリーのみを送信します。最後に、コールバックを行ってエントリーを取得したら、saveLocal を呼び出し、それらのエントリーをローカル・キャッシュに保存する必要があります。新しいエントリーがローカルに保存されると、オフラインでも Web アプリケーションをフルに利用できるようになります。


オフラインで動作させる

オフラインでも動作可能なアプリケーションを実現することは、モバイル Web アプリケーションの開発にとっての念願です。オフラインで動作させることは簡単ではありませんが、HTML 5 の多くの新機能によって多くの障害が解消されています。最初に必要なことは、オフラインで必要となるアセットを特定し、それらをアプリケーションのマニフェストに記載することです (リスト 11)。

リスト 11. アプリケーションのマニフェスト
CACHE MANIFEST
index.html
index.js
json2.js
loading.gif

このアプリケーションのように単純な場合には、マニフェストも非常に単純です。マニフェストに記載されているのはすべて静的なファイルで、HTML、JavaScript、そして画像 (必要な場合には CSS も) といったファイルです。このマニフェスト・ファイルが text/cache-manifest という MIME タイプで提供されている点は重要です。これはリスト 4 の web.xml ファイルの中で設定したとおりです。最後に、リスト 5 をもう一度見てみると、ルートの html 要素に manifest 属性があり、この属性がリスト 11 のマニフェスト・ファイルを指していることがわかります。あとは、loadEntries 関数に最後の変更を 1 つ加えればよいだけです。

リスト 12. オフラインかどうかをチェックする
function loadEntries(){
    // load local
    // ...
    // check if online
    if (navigator.onLine){
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            if (this.readyState == 4 && this.status == 200){
                      var theFeed = JSON.parse(this.responseText);
                      var i = 0;
                      if (theFeed.entries){
                             var len = theFeed.entries.length;
                             for (i=0;i<len;i++){
                                    addEntry(theFeed.entries[len - 1 -i], true);
                                    saveLocal(theFeed.entries[len - 1 -i]);
                             }
                      }
                      var body = document.getElementsByTagName("body")[0];
                      body.removeChild($("loader"));
                  }
        };
        var urlStr = "/resources/feed?after=" + newest;
        xhr.open("GET", urlStr);
        xhr.send();    
    }
}

オンラインかオフラインかを調べるために、navigator オブジェクト (window.navigator) の onLine プロパティーをチェックします。オンラインでない場合には、サーバーを呼び出して新しいエントリーを要求しても意味がないので、単純にローカルのエントリーをすべて表示します。これで、オフラインでも動作するモバイル Web アプリケーションが完成しました。


まとめ

モバイル Web アプリケーションは現在ホットなトピックですが、それには十分な理由があります。モバイル Web アプリケーションによって、多種多様な機器を使用するユーザーを対象にできるようになります。モバイル Web アプリケーションは、これまで Web 開発者が経験してきた中で最高レベルとも言えるほど、ブラウザー間の標準化を活用しています。この記事では、Ajax を利用するモバイル Web アプリケーションの作成に必要な基本技術のすべてを説明しました。Ajax を利用することによって、モバイル・ブラウザーの最先端機能を活用することができます。この記事のサンプル・コードを調べてみてください。ページが要求された時に、すべての HTML をサーバーで生成することも容易にできます。しかしすべての UI をクライアントに置き、Ajax を使ってサーバーからデータを取得すると、データを容易にクライアントにキャッシュすることができ、さらにはオフラインでアプリケーションを動作させることもできるのです。


ダウンロード

内容ファイル名サイズ
Article source codeWebKitBlog.zip32KB

参考文献

学ぶために

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

議論するために

コメント

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=Web development, Open source
ArticleID=477872
ArticleTitle=モバイル Web 用の Ajax アプリケーションを作成する
publish-date=03022010