接続された Windows ストア アプリの作成

私たちの周囲には、ネットワークに接続されたデバイスがあふれています。冷蔵庫や洗濯機でさえ、最近ではインターネットやホーム ネットワークに接続できるのです。ですから、アプリも同じようにネットワークに接続したいとエンド ユーザーが考えても不思議はありません。これらの "接続アプリ" は、Web 上の最新コンテンツ (ソーシャル メディア、デジタル メディア、ブログなど、さまざまな種類のコンテンツ) を利用します。接続アプリの開発は標準になりつつありますが、ネットワークの切断、従量制課金接続のコスト、パフォーマンスなどの一般的な問題への対応が課題として残っています。Windows 8 では、接続アプリを今までにないほど簡単に開発できます。

この記事では、Windows ストア アプリのユーザーに、高速かつ滑らかで手間のかからない接続エクスペリエンスを提供するための有効なヒントについてご説明します。

  • シナリオに合った API を選ぶ
  • 適切なネットワーク機能を選ぶ
  • アプリの動作を従量制課金接続に対応させる
  • ネットワークの状態の変化に対応する
  • コンテンツをキャッシュして滑らかな動作を実現する

では、それぞれのヒントについて詳しく説明していきましょう。

適切な API を選ぶ

家を建てようとする場合、適切な道具が必要ですね。釘を打つなら金づち、板を切るならのこぎり、ネジを締めるならドライバーがそれぞれ必要です。同様に、ネットワークに接続される Windows ストア アプリを開発する場合にも、適切な Networking API を使用する必要があります。Windows 8 には、アプリがインターネットとプライベート ネットワークのどちらを介して他のコンピューターやデバイスと通信する場合にも使用できる、さまざまな Networking API が用意されています。したがって、最初のステップは、開発するアプリに必要なネットワーク機能を把握することです。

ネットワークにおける最も一般的なシナリオは、Web サイトにアクセスして情報を取得または保存することです。簡単な例として、Web サイトを使用してユーザー情報やスコアを保存するゲームがあります。もう少し複雑な例としては、REST ベースの Web サービスに接続し、その Web サービスが提供するライブラリを使用して情報へのアクセスや保存を行うアプリがあります。Windows 8 には、Web サービスや Web サイトに接続する API がいくつかあります。アプリでこれらの API を使用すると、REST をサポートする Web サービスにアクセスしたり、Web サーバーに基本的な HTTP プロトコルのコマンド (GET や POST など) を送信することができます。Web アクセスの場合、必要な API はアプリの開発に使用する言語によって変わります。

  • XMLHTTPRequest (英語) および WinJS.xhr (英語) - JavaScript および HTML で作成したアプリ。
  • HttpClient (機械翻訳) - C# または Visual Basic .NET と XAML で作成したアプリ。
  • XML HTTP Request 2 (IXHR2) (英語) - C++ および XAML で作成したアプリ。

以下のコードは、REST ベースの Web サービスを使用して基本的な要求と応答を実行する方法を示しています。この場合、Web サービスは Web サーバー上で ASP.NET スクリプトを実行する可能性があります。

JavaScript

 function makeXHRCall() {
    WinJS.xhr({ uri: "https://www.microsoft.com/en-us/default.aspx” }).done(
 function onComplete(result) {
 print(result.responseText);
 },
 function onError(err) {
 print("Error: " + err.responseText);
        });
}

C#

 private async void MakeHttpCall()
{
    HttpClient httpClient = new HttpClient();
    try {
        string response = await httpClient.GetStringAsync("https://www.microsoft.com/en-us/default.aspx");
    }
    catch (Exception) {
        // Handle exception.
    }
}

WinJS.xhr の詳細については、「Web サービスへの接続 (JavaScript と HTML を使った Windows ストア アプリ)」を参照してください。HttpClient の詳細については、「クイックスタート: HttpClient を使用した接続 (C#/VB/C++ と XAML を使った Windows ストア アプリ)」および「HttpClient のサンプル」(英語) を参照してください。

ネットワークにおけるもう 1 つの一般的なシナリオは、ファイル転送に時間がかかる場合のファイルのダウンロードやアップロードです。例として、写真やフォト アルバムの Web サービスへのアップロードや、Web サービスからのダウンロードを行うカメラやフォト ギャラリーのアプリがあります。これらの転送には時間がかかりますが、転送が終わるまでユーザーを待たせることはありません。Windows.Networking.BackgroundTransfer API は、アプリが実行されていなくてもファイルのダウンロードやアップロードを行う機能を備えています。アプリがフォアグラウンドで実行されていてフォーカスがある状態のときに転送を開始すると、その後アプリが終了しても、Windows 8 がバックグラウンドで転送を続けます。

もっと特殊なシナリオとして、シンジケート コンテンツへのアクセスがあります。Windows.Web.Syndication API は、RSS 形式または Atom 形式でフィードを取得できます。さらに、Windows.Web.AtomPub API により、アプリはさまざまな AtomPub 形式でデータを公開できます。

API を介して特定のより高度なネットワーク プロトコルを利用することができないシナリオでは、Windows ランタイムが TCP ソケットと UDP ソケットも (マルチキャストと共に) サポートします。Windows.Networking.Sockets API は、StreamSocket (TCP) および DatagramSocket (UDP) を提供して、より上位のレイヤーにある他のプロトコルを実装できるようにします。

注: Windows 8 には、WebSocket という新しい種類のソケットが用意されています。WebSocket および WebSocket を使用するタイミングの詳細については、「WebSocket を使った接続」を参照してください。

次の表に、サポートされるネットワーク機能の詳細と、追加情報へのリンクを示します。

 

API

機能

 

 

 

 

複数のバージョンの RSS 形式または Atom 形式でフィードを取得します。これらの API により、OData などの新しい形式のサポートを簡単に実装できます。Windows ランタイムは Atom 公開プロトコルもサポートしているので、Atom コレクションを公開することができます。 詳細については、「概要コンテンツへのアクセスと管理」を参照してください。

 

 

 

 

 

    • RSS リーダー

 

 

 

Windows.Networking.BackgroundTransfer

 

 

呼び出し元のアプリがフォアグラウンドにない場合でも、持続的、コスト認識可能、再開可能な方法で、コンテンツのダウンロードとアップロードを実行します。この API は、HTTP、HTTPS、FTP の各プロトコルを使用したコンテンツ転送をサポートします。 詳細については、「バックグラウンドでのデータの転送」を参照してください。

 

 

 

 

    • SkyDrive

 

    • Xbox ビデオ

 

 

 

 

 

 

 

 

 

 

REST ベースの Web サービスと他の HTTP ベースのプロトコルを操作します。 詳細については、「Web サービスへの接続」を参照してください。

 

 

 

 

 

    • Bing マップ

 

 

 

Windows.Networking.Proximity

 

 

アプリがソケット API を使用して 2 つのデバイス間のネットワーク通信をトリガーした後、そのデバイス間の近接通信を検出します。 詳細については、「近接通信とタップのサポート」を参照してください。

 

 

 

 

    • ゲーム

 

    • 共用アプリ

 

 

 

Windows.Storage.Pickers

 

 

リモート ファイル共有と通信します。 詳細については、「データとファイルへのアクセス」を参照してください。

 

 

 

 

    • Xbox Music

 

    • フォト

 

 

 

Windows.Networking.Sockets

 

 

これまでに説明した API でサポートされていないプロトコル (SMTP、MAPI、telnet など) を使用するサービス、または同じローカル ネットワーク上にある別のデバイスに接続します。また、Web (HTTP プロキシを含む) を介して新しいサービスに接続するためにソケットのようなセマンティクス (非同期、双方向) を必要とするアプリにも使用されます。 詳細については、「ソケットを使った接続」を参照してください。

 

 

 

 

 

 

 

    • Lync、共有型ホワイトボード、またはストック ピッカー

 

 

 

Windows.Storage.ApplicationData

 

 

Windows 8 では、一部のアプリケーション データがユーザー デバイス間で自動的に移行されます。アプリケーション データのローミングは、アプリのユーザーが複数のデバイスを活用している場合 (職場では PC、自宅ではタブレットを使用して、複数のデバイスに同じアプリをインストールしている場合など) に役立ちます。 詳細については、「アプリケーション データのローミングのガイドライン」を参照してください。

 

 

 

適切なネットワーク機能を選ぶ

ネットワークの分離は、Windows 8 で使用されるアプリ セキュリティ モデルの一部です。Windows は、積極的にネットワーク境界を発見し、ネットワーク アクセスを制限してネットワークの分離を適用します。これらの機能を適切に展開すると、ユーザーやアプリを悪意のある攻撃から守ることができます。

アプリでネットワークの分離の機能を宣言して、ネットワーク アクセスの範囲を定義する必要があります。これらの機能を宣言しないと、アプリはネットワーク リソースにアクセスできません。Windows でネットワークの分離をアプリに適用する方法の詳細については、「ネットワーク機能を設定する方法」を参照してください。

同一デバイス上の Windows ストア アプリとデスクトップ アプリ間のプロセス間通信メカニズムとしてネットワークを使用することはできません。したがって、Windows ストア アプリで IP ループバック アドレスは使用できません。開発目的の限定的な例外として、Visual Studio デバッガーで操作するときは IP ループバック アドレスの使用が許可されます。詳細については、「ループバックを有効にする方法とネットワーク分離のトラブルシューティングを行う方法」を参照してください。

ネットワークへのアクセス要求は、2 つのカテゴリに分けられます。

  1. クライアントによる発信要求: アプリはクライアントとして機能し、最初のネットワーク要求をリモート コンピューター (通常はサーバー) に送信することでネットワーク アクセスを開始します。アプリは 1 つ以上の要求をサーバーに送信し、サーバーは 1 つ以上の応答を返します。たとえば、Web クライアント アプリから Web サーバーへのすべてのトラフィックは、このカテゴリに入ります。
  2. 未承諾の着信要求: アプリはネットワーク サーバーとして機能し、リモート コンピューターからの着信ネットワーク要求をリッスンします。リモート コンピューターは、サーバーとして機能しているアプリに最初の要求を送信することで、ネットワーク アクセスを開始します。リモート コンピューターは 1 つ以上の要求をアプリに送信し、アプリは 1 つ以上の応答をリモート コンピューターに返します。たとえば、メディア サーバーとして機能するアプリがこのカテゴリに入ります。

最小権限の原則に従い、アプリが必要とする機能のみを追加します。クライアントによる発信要求のみが必要なアプリもあれば、未承諾の着信要求も受け取る必要があるアプリもあります。アプリによっては、ネットワークを介して認証を行う際に、ユーザーの資格情報や証明書へのアクセスが必要になるものもあります。

次の表に、接続アプリで必要とされることが多いネットワークの分離機能とその他の関連機能を詳しく示します。最初の 3 つは、接続アプリが使用する主要なネットワークの分離機能です。実際、接続アプリでは、これらの 3 つの機能のうち少なくとも 1 つを有効にする必要があります。表内の他のエントリは、一部の接続アプリでよく必要とされる追加機能です。

 

ネットワーク機能

説明

アプリの例

インターネット (クライアント)

 

 

インターネットや公共の場所 (空港や喫茶店など) のネットワークへの発信アクセスを提供します。インターネット アクセスを必要とするほとんどのアプリは、この機能を宣言する必要があります。

 

       

    • RSS リーダー

 

    • ソーシャル ネットワーク

 

    • ゲーム

 

 

 

インターネット (クライアントおよびサーバー)

 

 

インターネットや公共の場所 (空港や喫茶店など) のネットワークへの着信アクセスと発信アクセスの両方を提供します。クリティカル ポートへの着信アクセスは常にブロックされます。この機能は、インターネット (クライアント) 機能のスーパーセットであるため、両方を宣言する必要はありません。

 

 

 

    • P2P アプリ

 

    • マルチキャストを使ってプレイヤーを見つけるマルチプレイヤー ゲーム

 

 

 

プライベート ネットワーク (クライアントおよびサーバー)

 

 

ユーザーによって信頼済みのプライベートな場所で、着信および発信のネットワーク アクセスを提供します。これらは通常、自宅や職場のネットワークです。クリティカル ポートへの着信アクセスは常にブロックされます。

 

 

 

    • ネットワーク接続ストレージ (NAS) のコンテンツにアクセスするアプリ

 

    • 基幹業務アプリ

 

    • プライベートな (自宅または職場の) ネットワーク上で、マルチキャストを使ってプレイヤーを見つけるマルチプレイヤー ゲーム

 

 

 

近接通信

 

 

デバイスとの近接通信に必要です。招待の送信または承認に対するユーザーの承諾を得て、アプリが近接通信でデバイスに接続してネットワークにアクセスすることを許可します。

 

 

 

    • 近接通信のユーザーとのマルチプレイヤー ゲーム

 

 

 

エンタープライズ認証

 

 

ドメイン資格情報が必要な企業イントラネット リソースに接続する機能を提供します。

 

 

 

    • 基幹業務アプリ

 

 

 

共有ユーザー証明書

 

 

ユーザーの ID を検証するために、スマート カード証明書などのソフトウェアとハードウェアの証明書にアクセスする機能を提供します。関連 API が実行時に呼び出されたときは、ユーザーはアクション (カードの挿入や証明書の選択など) を行う必要があります。

 

 

 

    • 仮想プライベート ネットワーク アプリ

 

  • 基幹業務アプリ

このチェック リストを使用して、アプリ内でネットワークの分離が構成されていることを確認します。

  • アプリが必要とするネットワーク アクセスの方向 (クライアントによる発信要求、未承諾の着信要求、その両方) を確認します。
  • アプリが通信するネットワーク リソースの種類 (自宅または職場のネットワーク上の信頼済みのリソース、インターネット上のリソース、その両方) を確認します。
  • 最低限必要なネットワークの分離機能をアプリ マニフェストで構成します。そのためには、Microsoft Visual Studio 2012 のアプリ マニフェスト デザイナーを使用するか、手動で追加 (英語) します。
  • アプリを展開して実行し、トラブルシューティング用に提供されているネットワークの分離ツールを使用してテストします。詳細については、「ループバックを有効にする方法とネットワーク分離のトラブルシューティングを行う方法」を参照してください。

次のスクリーン ショットは、Microsoft Visual Studio 2012 のアプリ マニフェスト デザイナーを使用してネットワーク機能を有効にする方法を示しています。

Visual Studio 2012 でアプリの package.appxmanifest を使ってネットワーク機能を選択する

Visual Studio 2012 でアプリの package.appxmanifest を使ってネットワーク機能を選択する

アプリの動作を従量制課金接続に対応させる

データ通信量が毎月の上限値に近づいた場合や、海外旅行に出かける場合を考えてみてください。このような場合、通常は大事をとってデバイスとアプリの使用を中止し、不要なネットワーク使用料が発生しないようにします。

Windows 8 では、アプリが利用可能なネットワーク リソースを監視し、従量制課金接続の場合はそれに応じた動作をさせることで、この問題を解決します。ユーザーのアプリへの信頼度を高めるため、接続によって費用が発生する場合にはそのことを通知し、費用を抑えるようにアプリを動作させることができます。

Windows.Networking.Connectivity API は、ネットワーク接続の種類と費用に関する情報を提供します。これにより、ネットワーク リソースを普通に使ってよい場合、控えめに使ったほうがよい場合、ユーザーに問い合わせる場合をアプリが判断できます。

ConnectionProfile は、ネットワーク接続を表します。ConnectionProfileConnectionCost を使用して、アプリの動作を対応させるかどうかを判断することができます。NetworkCostType プロパティは、ネットワーク接続の種類を示します。有効な値は次の 4 つです。

  • Unrestricted - このネットワーク接続の使用は無制限です。使用料や容量の制約はありません。
  • Fixed - このネットワーク接続の使用は、一定の限度までは無制限です。
  • Variable - このネットワーク接続の使用は、バイト ベースの従量制です。
  • Unknown - このネットワーク接続に関するコスト情報を使用できません。

他にも ConnectionCost のブール型プロパティがいくつかあり、より詳細な情報を提供します。

  • Roaming - ホーム プロバイダーの外側のネットワークに接続されているかどうかを示します。
  • ApproachingDataLimit - 接続がデータ プランで指定されたデータ使用量の上限に近づいているかどうかを示します。
  • OverDataLimit - 接続がデータ プランで指定されたデータ使用量の上限を超えているかどうかを示します。

これらのプロパティで示された状況にアプリを対応させます。接続が Roaming であれば、ネットワーク使用に関連するデータ コストは高くなる可能性があります。NetworkCostTypeVariable の場合、ネットワークは従量制課金接続で、ユーザーはネットワーク上で送受信したデータ量に基づいて料金を支払います。NetworkCostTypeFixed の場合、ユーザーが既にデータ量の上限に近づいているか、または上限を超えているかどうかが心配の種になります。

この情報を使用することにより、アプリはこれらのガイドラインに従って最適なネットワーク リソースの使用方法を決定できます。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

動作

接続コスト

アプリのガイドライン

標準

 

 

NetworkCostTypeUnrestricted または Unknown で、ConnectionCostRoaming 以外

 

 

アプリは制限を実装しません。アプリは接続のコストを無制限として扱い、使用料や容量の制約はありません。

 

 

 

    • メディア プレーヤー アプリは、HD ムービー全体を再生できます。

 

    • アプリが大きなファイルをダウンロードする際に制限はなく、メッセージも表示されません。

 

 

 

控えめ

 

 

NetworkCostTypeFixed または Variable で、ConnectionCostRoaming でも OverDataLimit でもない

 

 

アプリは、従量制課金接続での操作を処理するために制限を実装して、ネットワーク使用量を最適化します。

 

 

 

    • メディア プレーヤー アプリは、ムービーを低解像度で再生できます。

 

    • アプリは、クリティカルでないダウンロードを遅延させることができます。

 

 

 

承認

 

 

ConnectionCostRoaming または OverDataLimit

 

 

ネットワーク アクセス コストが計画したコストより大幅に高くなる場合、アプリは例外処理を行います。

 

 

 

    • アプリは、ネットワークにアクセスするかどうかをユーザーに確認します。

 

  • アプリは、バックグラウンドのすべてのデータ ネットワーク アクティビティを中断します。

以下のサンプル コードは、接続コストをチェックして、適切なアプリの動作を提案します。

JavaScript

 var CostGuidance = { Normal: 0, Conservative: 1, OptIn: 2 };
// GetCostGuidance returns an object with a Cost (with value of CostGuidance), 
// CostName (a string) and Reason, which says why the cost is what it is.
function GetCostGuidance() 
{
    var connectionCost = Windows.Networking.Connectivity.NetworkInformation.getInternetConnectionProfile().getConnectionCost();
    var networkCostConstants = Windows.Networking.Connectivity.NetworkCostType;
    var Retval = new Object();
    if (connectionCost.roaming || connectionCost.overDataLimit)
    {
        Retval.Cost = CostGuidance.OptIn;
        Retval.CostName = "OptIn";
        Retval.Reason = connectionCost.roaming
            ? "Connection is roaming; using the connection may result in additional charge."
            : "Connection has exceeded the usage cap limit.";
    }
    else if (connectionCost.networkCostType == networkCostConstants.fixed
        || connectionCost.networkCostType == networkCostConstants.variable)
    {
        Retval.Cost = CostGuidance.conservative;
        Retval.CostName = "Conservative";
        Retval.Reason = connectionCost.networkCostType == NetworkCostType.fixed
            ? "Connection has limited allowed usage."
            : "Connection is charged based on usage. ";
    }
    else
    {
        Retval.Cost = CostGuidance.Normal;
        Retval.CostName = "Normal";
        Retval.Reason = connectionCost.networkCostType == networkCostConstants.unknown
            ? "Connection is unknown."
            : "Connection cost is unrestricted.";
    }

    return Retval;
}

C#

 public enum NetworkCost { Normal, Conservative, OptIn };
public class CostGuidance
{
    public CostGuidance()
    {
        var connectionCost = NetworkInformation.GetInternetConnectionProfile().GetConnectionCost();
        Init(connectionCost);
    }
    public NetworkCost Cost { get; private set; }
    public String Reason { get; private set; }


    public void Init(ConnectionCost connectionCost)
    {
        if (connectionCost == null) return;
        if (connectionCost.Roaming || connectionCost.OverDataLimit)
        {
            Cost = NetworkCost.OptIn;
            Reason = connectionCost.Roaming
                ? "Connection is roaming; using the connection may result in additional charge."
                : "Connection has exceeded the usage cap limit.";
        }
        else if (connectionCost.NetworkCostType == NetworkCostType.Fixed
            || connectionCost.NetworkCostType == NetworkCostType.Variable)
        {
            Cost = NetworkCost.Conservative;
            Reason = connectionCost.NetworkCostType == NetworkCostType.Fixed
                ? "Connection has limited allowed usage."
                : "Connection is charged based on usage. ";
        }
        else
        {
            Cost = NetworkCost.Normal;
            Reason = connectionCost.NetworkCostType == NetworkCostType.Unknown
                ? "Connection is unknown."
                : "Connection cost is unrestricted.";
        }
    }
}

アプリ動作の従量制課金接続への対応の詳細については、ネットワーク情報のサンプル (英語) を参照してください。

タスク マネージャーを実行して、各アプリが使用しているネットワーク データの量を確認することもできます。次のスクリーン ショットにその例を示します。

タスク マネージャーの [アプリの履歴] タブでアプリごとの CPU とネットワークの使用量を確認

タスク マネージャーの [アプリの履歴] タブでアプリごとの CPU とネットワークの使用量を確認

ネットワークの状態の変化に対応する

モバイル デバイスの使用中に、ネットワークの状態が変化することがあります。ユーザーの自宅やガレージなどで、3G または 4G のモバイル ブロードバンド ネットワークが、Wi-Fi が利用可能であるにもかかわらず圏外になることがあります。同様に、ユーザーが自宅を離れると Wi-Fi が圏外になることもあります。こうした場合、ネットワークが使用できなくなる可能性があります。Wi-Fi やモバイル ブロードバンド ネットワークの普及に伴い、このようなネットワークの状態の変化が頻繁に発生します。

NetworkStatusChanged イベントは、利用可能コストや接続オプションが変化したことを示します。ネットワークの状態の変化に対応し、変化が起こった場合でもシームレスなエクスペリエンスを提供するために、接続アプリは以下のシナリオのガイドラインに従います。

エラーによる切断

ほとんどの場合、ネットワーク操作を再試行するだけで、改めて接続を確立できます。うまくいかない場合は、NetworkStatusChanged イベントを待機します。接続が続けてエラーになる場合は、アプリが再試行に使用するバックオフの間隔を増加させる (50 ミリ秒から始めて、指数関数的にこの間隔を増加させる) ことをお勧めします。

ネットワークの損失

接続が切れたことをユーザーに通知し、NetworkStatusChanged イベントを登録して待機します。

新しいネットワークの利用範囲

デバイスが複数のネットワークに接続している場合もあります。たとえば、ユーザーが家に着く前にモバイル ブロードバンドに接続して Windows 8 のメッセージング アプリで友人とチャットしながら、自宅でも無制限のネットワークに接続する場合があります。Windows 8 の既定のポリシーでは、従量制課金接続よりも無制限のネットワークを優先し、低速のネットワークよりも高速のネットワークを優先します。しかし、アプリによって確立された既存の接続は、新しいネットワークに自動的には切り替わりません。新しいネットワークに切り替えるかどうかの判断ができるのはアプリだけであるため、アプリ自身が関与する必要があります。

たとえば、ビデオ ストリームが終わりかけている場合、新しいネットワークに切り替える意味はあまりありません。しかし、現在のネットワークがパケットを損失していたり、あまりに遅かったり、ストリームの終了までにまだ時間がかかりそうな場合には、新しいネットワークへの切り替えが最良の選択です。

アプリのシナリオにおいてネットワークの切り替えが妥当であると判断した場合は、新しいネットワークの検出時に次のガイドラインに従ってください。

  1. 既存のネットワークと新しいネットワークのコストを確認します。新しいネットワークへの切り替えに意味がある場合は、新しいネットワーク接続の確立を試行し、前述したガイドラインに基づくネットワーク操作を再試行します。Windows は、(利用可能であれば) 従量制課金接続よりも無制限のネットワーク、低速のネットワークよりも高速のネットワークを自動的に選択します。
  2. 新しいネットワーク接続が確立できたら、この新しい接続をアプリで使用し、以前のネットワーク接続がまだ存在している場合は元のネットワーク操作をキャンセルします。

ネットワーク コストの変化

ネットワーク コストの変化は、NetworkCostTypeFixed で、使用量がデータ量の上限に近づいた、または超えた場合に起こる可能性があります。ネットワーク コストの変化は、NetworkCostTypeVariable になるか、Roaming が true に変わった場合にも起こる可能性があります。こうした場合には、前のヒントのガイドラインに基づいて、アプリの動作を変化に対応させます。

以下のコード例は、NetworkStatusChanged イベントを使用して、さまざまなネットワーク状態の変化に対してアプリのシームレスなエクスペリエンスを提供します。どちらの例でも、registeredNetworkStatusNotification というグローバルなブール型変数を使用します。この変数の初期設定値は false です。

JavaScript

 // Register for NetworkStatusChanged notifications, and display new 
// Internet ConnectionProfile info upon network status change.
function registerForNetworkStatusChange() {
    try {

        // Register for network status change notifications.
        if (!registeredNetworkStatusNotification) {
            var networkInfo.addEventListener("networkstatuschanged", onNetworkStatusChange);
            registeredNetworkStatusNotification = true;
        }
    }
    catch (e) {
        print("An unexpected exception occurred: " + e.name + ": " + e.message);
    }
}

// Event handler for NetworkStatusChanged event
function onNetworkStatusChange(sender) {
    try {
        // Get the ConnectionProfile that is currently used to connect 
        // to the Internet.
        var internetProfile = networkInfo.getInternetConnectionProfile();
        if (internetProfile === null) {
            print("Not connected to Internet\n\r");
        }
        else {
            internetProfileInfo += getConnectionProfileInfo(internetProfile) + "\n\r";
            print(internetProfileInfo);
        }
        internetProfileInfo = "";
    }
    catch (e) {
        print("An unexpected exception occurred: " + e.name + ": " + e.message);
    }
}

C#

 // Register for NetworkStatusChanged notifications, and display new 
// Internet ConnectionProfile info upon network status change.
void NetworkStatusChange()
{
    // Register for network status change notifications.
    try
    {
        var networkStatusCallback = new NetworkStatusChangedEventHandler(OnNetworkStatusChange);
        if (!registeredNetworkStatusNotification)
        {
            NetworkInformation.NetworkStatusChanged += networkStatusCallback;
            registeredNetworkStatusNotification = true;
        }
    }
    catch (Exception ex)
    {
        rootPage.NotifyUser("Unexpected exception occurred: " + ex.ToString(), NotifyType.ErrorMessage);
    }
}

// Event handler for NetworkStatusChanged event
async void OnNetworkStatusChange(object sender)
{
    try
    {
        // Get the ConnectionProfile that is currently used to connect 
        // to the Internet 
        ConnectionProfile InternetConnectionProfile = NetworkInformation.GetInternetConnectionProfile();

        if (InternetConnectionProfile == null)
        {
            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                rootPage.NotifyUser("Not connected to Internet\n", NotifyType.StatusMessage);
            });
        }
        else
        {
            connectionProfileInfo = GetConnectionProfile(InternetConnectionProfile);
            await _cd.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                rootPage.NotifyUser(connectionProfileInfo, NotifyType.StatusMessage);
            });
        }
        internetProfileInfo = "";
    }
    catch (Exception ex)
    {
        rootPage.NotifyUser("Unexpected exception occurred: " + ex.ToString(), NotifyType.ErrorMessage);
    }
}

NetworkStatusChanged イベントの詳細については、「クイック スタート: 接続イベントと可用性の変更の管理」および「ネットワーク情報のサンプル」(英語) を参照してください。

コンテンツをキャッシュして滑らかな動作を実現する

コンテンツをディスクにキャッシュすると、アプリが高速かつ滑らかに動作します。たとえば、RSS フィード リーダー アプリは、前回のセッションでディスクにキャッシュされたフィードをすぐに表示できます。最新のフィードが利用可能になると、アプリはコンテンツを更新します。キャッシュすることにより、ユーザーはアプリ起動時にすぐにコンテンツを確認でき、その間にアプリは新しいコンテンツを取得できます。

Windows 8 には、Windows.Storage 名前空間の ApplicationData クラスが用意されています。このクラスは、アプリ データ ストアへのアクセスを提供します。このデータ ストアは、デバイスのローカルなファイルと設定、複数デバイス間のローミング、または一時的なデータで構成されます。

ファイルは、大規模なデータ セット、データベース、または一般的なファイル形式のデータの格納に最適です。ファイルは、Roaming フォルダー、Local フォルダー、Temporary フォルダーのいずれかに格納されます。これらはそれぞれ次のように扱われます。

  • Roaming のファイルは、ユーザーが接続されたアカウントでサインインした複数のコンピューターやデバイスの間で同期されます。ファイルのローミングはすぐには実行されません。複数の要素が評価されて、データ送信のタイミングが決定されます。ローミング データの使用量はクォータ (RoamingStorageQuota プロパティによって利用可能) を超えないようにします。クォータを超えると、データのローミングは中断されます。アプリが書き込み中のファイルをローミングすることはできません。したがって、アプリのファイル オブジェクトは、必要なくなったら閉じるようにしてください。
  • Local のファイルは、コンピューター間で同期されません。これらのファイルは、最初に作成されたコンピューター上にそのまま存在します。
  • Temporary のファイルは、使用されなくなると削除されます。一時ファイルの削除は、使用可能なディスク容量やファイル作成からの経過日数などの要素を考慮して決定されます。

以下のコード例は、コンテンツをディスクにキャッシュします。サーバーの応答をキャッシュすると、強制終了/再起動の後、アプリがすぐにコンテンツを表示することができます。簡潔にするため、これらの例ではアプリ データ ストアへの設定の書き込み方法やローミング イベントへの応答方法は示していません。これらの詳細については、「アプリケーション データのサンプル」(英語) を参照してください。

JavaScript

 var roamingFolder = Windows.Storage.ApplicationData.current.roamingFolder;
var filename = "serverResponse.txt";

function cacheResponse(strResponse) {
    roamingFolder.createFileAsync(filename, Windows.Storage.CreationCollisionOption.replaceExisting)
        .done(function (file) {
            return Windows.Storage.FileIO.writeTextAsync(file, strResponse);
        });
}

function getCachedResponse() {
    roamingFolder.getFileAsync(filename)
        .then(function (file) {
            return Windows.Storage.FileIO.readTextAsync(file);
        }).done(function (response) {
            print(response);
        }, function () {
            // getFileAsync or readTextAsync failed. 
            // No cached response.
        });
}

C#

 MainPage rootPage = MainPage.Current;
StorageFolder roamingFolder = null;
const string filename = "serverResponse.txt";

async void cacheResponse(string strResponse)
{
    StorageFile file = await roamingFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file, strResponse);
}

async void getCachedResponse()
{
    try
    {
        StorageFile file = await roamingFolder.GetFileAsync(filename);
        string response = await FileIO.ReadTextAsync(file);
    }
    catch (Exception)
    {
        // getFileAsync or readTextAsync failed.
        // No cached response.
    }
}

アプリ データ ストアの詳細については、「アプリ データのローミング」と「アプリケーション データのサンプル」(英語) を参照してください。

まとめ

Windows ストア アプリを開発する際には、この記事のガイドラインを使用して、手間のかからない優れた接続エクスペリエンスを提供してください。これらのヒントを使用すると、開発プロセスが簡単になるだけではなく、アプリの滑らかさを維持しながらユーザーの信頼度も上げることができます。

- Windows プログラム マネージャー II、Suhail Khalid

協力: Steven Baker、Peter Smith