[WinRT] Surface RT で閲覧しているURLをデスクトップに送る

[WinRT] デスクトップで閲覧しているURLをSurface RTに送る – Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/4718

の逆向きパターンで、タブレットPCからデスクトップのほうにURLを送ります。

こっちのほうは、比較的簡単?で、タブレットPCで動作しているブラウザ(IE10)から共有を使って、ストアアプリに送信、そのストアアプリからデスクトップアプリに通信させます。簡易HTTPサーバーを立てるところは、前回と同じなので流用してます。というか同じアプリに乗せています。

■簡易HTTPサーバー

///
/// フォームロード時
///
///
///
private void Form1_Load(object sender, EventArgs e)
{
    listener = new HttpListener();
    listener.Prefixes.Add("http://*:8090/");
    listener.Start();

    // 受信待ちタスク
    Task tsk = new Task(
        () =>
        {
            while (true)
            {
                var cont = listener.GetContext();
                var req = cont.Request;
                var res = cont.Response;
                if (req.RawUrl.StartsWith("/GetUrl"))
                {
                    Debug.WriteLine(string.Format("req {0}", req.RawUrl));
                    var tw = new StreamWriter(res.OutputStream);
                    tw.Write(_text);
                    tw.Close();
                    res.Close();
                }
                else if (req.RawUrl.StartsWith("/PutUrl") == true)
                {
                    Debug.WriteLine(string.Format("req {0}", req.RawUrl));
                    var text = req.RawUrl.Replace("/PutUrl/", "");
                    text = System.Uri.UnescapeDataString(text);
                    textBox1.Text = text;
                    var tw = new StreamWriter(res.OutputStream);
                    tw.Write("OK");
                    tw.Close();
                    res.Close();
                }
                else
                {
                    var tw = new StreamWriter(res.OutputStream);
                    tw.Write("ERROR");
                    tw.Close();
                    res.Close();
                }
            }
        });
    tsk.Start();
}

同じ8090ポートを使って、/GetUrl の場合はデスクトップからタブレットPCへ、/PutUrl の場合はタブレットPCからデスクトップへ通信をします。
まあ、先行きは XML シリアライズを使って実装しますが、ひとまずこれで使い勝手を確認。

■共有ターゲットの実装

ブラウザから「共有」の対象になるために、連携するストアアプリを共有ターゲットにします。
追加で「共有コントラクト ターゲット」を追加してから、以下の部分を修正。

□共有コントラクトを開いたとき

public async void Activate(ShareTargetActivatedEventArgs args)
{
    this._shareOperation = args.ShareOperation;
    // ビュー モデルを使用して、共有されるコンテンツのメタデータを通信します
    var shareProperties = this._shareOperation.Data.Properties;
    var thumbnailImage = new BitmapImage();
    this.DefaultViewModel["Title"] = shareProperties.Title;
    this.DefaultViewModel["Description"] = shareProperties.Description;
    this.DefaultViewModel["Image"] = thumbnailImage;
    this.DefaultViewModel["Sharing"] = false;
    this.DefaultViewModel["ShowImage"] = false;
    this.DefaultViewModel["Comment"] = String.Empty;
    this.DefaultViewModel["SupportsComment"] = true;
    Window.Current.Content = this;
    Window.Current.Activate();
    // ブラウザからURLを共有する
    if (this._shareOperation.Data.Contains(StandardDataFormats.Uri))
    {
        var uri = await this._shareOperation.Data.GetUriAsync();
        this.DefaultViewModel["Comment"] = uri.ToString();
    }
    // 共有されるコンテンツの縮小版イメージをバックグラウンドで更新します
    if (shareProperties.Thumbnail != null)
    {
        var stream = await shareProperties.Thumbnail.OpenReadAsync();
        thumbnailImage.SetSource(stream);
        this.DefaultViewModel["ShowImage"] = true;
    }
}

□共有コントラクトで Share をタップしたとき

private async void ShareButton_Click(object sender, RoutedEventArgs e)
{
    this.DefaultViewModel["Sharing"] = true;
    this._shareOperation.ReportStarted();
    // TODO: this._shareOperation.Data を使用して共有シナリオに適した
    //       作業を実行します。通常は、カスタム ユーザー インターフェイス要素を介して
    //       このページに追加されたカスタム ユーザー インターフェイス要素を介して
    //       this.DefaultViewModel["Comment"]
    if (this._shareOperation.Data.Contains(StandardDataFormats.Uri))
    {
        // テキストデータを保存
        var text = this.DefaultViewModel["Comment"] as string;
        string url = "http://mars:8090/PutUrl/" + System.Uri.EscapeUriString(text);
        HttpClient cl = new HttpClient();
        var res = await cl.GetAsync(new Uri(url));
    }
    this._shareOperation.ReportCompleted();
}

実は、Active がなくていきなり share してもいいんですが、まあ、テンプレートのままで使ってみます。
こうすることで、

  1. ブラウザで閲覧する。
  2. チャームで「共有」を開いて GoRTApp を選択する。
  3. URL を確認してデスクトップに URL を通知する。
  4. デスクトップアプリのほうで、URL をブラウザで開く。

という流れができます。

■サンプルソース

サンプルソースはこちらで。

仕組みはこんな感じ。

20130422_02

カテゴリー: C#, WinRT パーマリンク