Quantcast
Channel: デバイスとITの架け橋
Viewing all 167 articles
Browse latest View live

グリッドアプリケーションのアイテムとして音楽を使ってみる

$
0
0

現在、http://msdn.microsoft.com/ja-jp/jj556277.aspxから公開しているBasic Photo、Entertainment Photoのテンプレートは、Visual Studio 2012のグリッドアプリテンプレート(XAML/C#)をベースに作られています。
このポストではBasic Photoアプリテンプレートをベースに説明を進めます。

Basic Photoテンプレートは名前からすると写真を扱うアプリ用に見えますが、アイテムは音楽の曲でも構いません。Windows PhoneのPCクライアントアプリであるZuneでMusic CDをキャプチャすると、ライブラリのミュージックフォルダーにアルバム情報と曲のファイルが構造化されて格納されます。論理構造的にはアルバムがあってそのアルバムに属する曲が入っているわけです。

アルバム => SampleDataGroup
曲      => SampleDataItem

とすれば、Basic Photo(グリッドアプリ)が想定している、グループ、アイテム構造をそのまま利用できます。ピクチャフォルダーを覗いてみると、アルバムと曲のグループ関係以外の要素が組み込まれています。これを愚直にWindows.Storage名前空間のクラス群を使って辿って、データ構造を作るのもいいのですが、もっと便利にアルバム、曲構造を扱う方法があるので、紹介します。

先ず、Basic Photoテンプレートでアプリケーションプロジェクトを一つ作ってください。

Package.appxmanifestを開き、機能タブで、音楽ライブラリにチェックを入れます。これでミュージックフォルダーにアプリがアクセスできるようになります。

テンプレートで作ったプロジェクトのグループ、アイテムは、DataModel/SampleDataSource.csファイルのSampleDataSourceクラスのコンストラクター内で定義されています。

                var group1 = new SampleDataGroup("Group-1",
                        "Group Title: 1",

から

                        group6));
                this.AllGroups.Add(group6);

までを、

            if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            {
                …
            }

で囲んでしまいます。これで囲まれたコードは、Visual StudioやBlendでXAMLを見ているときだけ有効で、アプリの実行時は有効でなくなります。

ミュージックフォルダーに格納されているアルバム、楽曲情報からSampleDataGroup、SampleDataItemを構築するメソッドをSampleDataSourceクラスに追加します。ファイルアクセス系のAPIで非同期メソッドを使うので、非同期メソッドとして定義します。

        public async void BuildMusicItemsAsync()
        {
            …
        }

このメソッドを、アプリで最初に表示されるページのGroupedItemsPageのLoadStateでコールするため、SampleDataSourceクラスに、

        public static SampleDataSource Current
        {
            get
            {
                if (_sampleDataSource == null)
                {
                    _sampleDataSource = new SampleDataSource();
                }
                return _sampleDataSource;
            }
        }

と、スタティックプロパティを追加します。GroupedItemsPage.xaml.csのLoadStateメソッド内で、

            SampleDataSource.Current.BuildMusicItemsAsync();

を// TODO: の下に書いておきます。これで準備は完了です。

ミュージックフォルダーからアルバム、曲を取り出すには、以下の様にします。

                // ミュージックフォルダーへの参照取得
                var musicFolders = Windows.Storage.KnownFolders.MusicLibrary;

                // ミュージックフォルダーからアルバムフォルダーの取り出し
                var qalbums = musicFolders.CreateFolderQuery(Windows.Storage.Search.CommonFolderQuery.GroupByAlbum);
                var albums = await qalbums.GetFoldersAsync();
                foreach (var album in albums)
                {
                    // アルバム属性の取り出し。albumPropsから、アーティストやアルバム名を取り出せる
                    var albumProps = await album.Properties.GetMusicPropertiesAsync();
                    // アルバムに対応するSampleDataGroupインスタンスを作成
                    var albumGroup = new SampleDataGroup(album.FolderRelativeId, albumProps.Album, albumProps.Artist, ””, "");

                    // 曲ファイルの取り出し
                    var qmusic = album.CreateFileQuery(Windows.Storage.Search.CommonFileQuery.OrderByMusicProperties);
                    var musics = await qmusic.GetFilesAsync();
                    foreach (var music in musics)
                    {
                        // 曲属性の取り出し。musicPropertiesから、曲名、アーティスト、ジャンル、アルバムなどが取り出せる
                        var musicProperties = await music.Properties.GetMusicPropertiesAsync();

                        // 曲に対応するSampleDataItemインスタンスを作成
                        var musicItem = new SampleDataItem(music.Path, musicProperties.Title, musicProperties.Album, musicProperties.AlbumArtist, "", albumGroup);
                        musicItem.MusicFile = music;
                        albumGroup.Items.Add(musicItem);
                    }

                    this.AllGroups.Add(albumGroup);
                }

 説明し忘れていましたが、後々のためSampleDataItemクラスに曲ファイルへの参照を保持するStorageFile型のプロパティ(名前はMusicFile)を追加しておきます。

これで基本的な骨格は出来上がりです。アルバムや曲に関する画像は何もやっていないのでちょっと寂しい出来上がりなので、それは皆さん工夫してください。それから、GroupedItemsPageのLoadStateメソッドは適宜何回もコールされます。このままの実装では何回も何回もこのコードが実行されてしまうので、構築完了を示すフラグを用意して、

        if (!musicPrepared)
        {
            ...
            musicPrepared = true;
        }

とガードを入れてください。あとは例えば、ItemDetaiPageにアプリバーなどでPlayボタンを定義してそのクリックハンドラで

            var selectedItem = (SampleDataItem)this.flipView.SelectedItem;
            await Windows.System.Launcher.LaunchFileAsync(selectedItem.MusicFile);

などと書いてやれば、曲の演奏も可能です。

以上、アルバム、曲をアプリで扱う方法を説明してきました。SampleDataGroup、SampleDataItemは何をグループ、アイテムとして使ってよいので、色々とアイデアを練ってみてください。ページの表示でテキストだけで何となく見栄えを保つ方法は、NewsReaderテンプレートを、アプリ実行時にグループ、アイテムを追加削除したい場合は、Entertainment Photoを参考にしてみてくださいね。

では、また。


Windows 8 ストアアプリ - サンプルコード Tips

$
0
0

今更のポストの気もしますが、皆さん、

http://code.msdn.microsoft.com/windowsapps/Windows-8-Modern-Style-App-Samples

ここから、Windows 8 ストアアプリのサンプルプロジェクトが沢山含まれたZIPアーカイブをダウンロードできるのご存知ですよね。アプリ開発を始める際、一通りざっと目を通しておくことをお勧めします。このZIPに含まれるプロジェクト(それぞれ個別にWebからダウンロード可能ですが)のうち、DirectX系のサンプルプロジェクトをビルド&実行するときには、以下のことに気を付けてください。

例えば、XAML DirectX  3D shooting game sampleやDirectX marble maze game sampleは、slnファイルが格納されているフォルダーをVisual Studio 2012のProjectsフォルダー直下に置かないと、ビルドできません。別の場所に置いて「あれ動かないぞぉ」とお困りの方、試してみてください。(サンプルのQ&Aに書いてありました)

 

DirectXやC++に関する話題を、これから何回かに分けて話をしようかな…などと思っております。はい。

 

 

Welcome Back to C++

$
0
0

今日札幌で話したC++に関する情報です。Visual Studio 2012では、昨年標準化されたC++11への対応や、Windows 8 ストアアプリ開発に対応するためのC++/CXなど、新たな機能が追加されています。

新機能(Modern C++)のC++11対応に関する情報ソースは、

http://msdn.microsoft.com/en-us/library/vstudio/hh279654.aspx

※日本語自動翻訳版は、http://msdn.microsoft.com/ja-jp/library/vstudio/hh279654.aspx

から公開されています。

スマートポインタやラムダ式、新しいテンプレートなどに関する説明はこちらをご覧ください。

C++/CXは、

http://msdn.microsoft.com/en-us/library/windows/apps/br212455.aspx

から公開されています。CXで新たに追加されたキーワード、property、delegate、eventなどに関する説明はこちらをご覧ください。

また、10月末にマイクロソフト本社で開催されたBuildのコンテンツアプリが、Windowsストアから公開されていて、

http://apps.microsoft.com/webpdp/ja-JP/app/build-2012/0c51433d-4d6b-4e51-a274-86611f732fca

で公開されています。

このアプリにはセッション情報、動画、PPTなどダウンロード可能なので、Windows 8ユーザーは是非インストールしてみてください。C++に関するドキュメントも結構あります。

 

 

 

 

 

 

Visual Studio 2012でC++ソースコードの構造を可視化する

$
0
0

Visual Studio 2012ではC++開発に関する機能が強化されています。このポストでは、機能強化の一つである、ソースコードの構造の可視化を紹介します。

プログラムは常に成長するものです。例え、趣味でちょっとしたプログラムを書いているときでも、あれもやってみよう、これもやってみよう…とプログラムの規模はだんだん大きくなってきます。そして気がつけば人間の頭の中だけでは手に負えない状況になったりします。通常の製品レベルのプログラムでは言うまでもないでしょう。C#やVisual Basicでは、Visual Studio 2010の時代からアーキテクチャエクスプローラの機能を使ってソースコードの可視化ができていました。Visual Studio 2012ではC++でもソースコードの可視化ができるようになっています。

※この機能は、有償版のUltimateでご利用いただけます。

先ず試しに、Visual Studio 2012を立ち上げて、VC++のストアアプリ、グリッドアプリケーションテンプレートでプロジェクトを一つ作ります。プロジェクトが出来上がったら、メニューで「アーキテクチャ」→「依存関係グラフの生成」→「ソリューション」を選択します。

これで、以下の様なダイアグラムが生成されます。

おう

ダイアグラムのApp14.exeの濃紺のアイコンにカーソルを持っていくと左にマークが表示されます。それをクリックすると、App14.exeの中身が展開され、

中身の名前空間構造が表示されます。更に濃紺の名前空間のアイコンを展開していくと、

と、クラスの依存関係、クラス内部のメソッドやプロパティが表示されます。この様に簡単な操作で、ソースコードの構造の俯瞰が可能です。

また、アーキテクチャメニューで、「インクルードファイルの場合」を選択すると、

ソースファイルとヘッダーファイルのインクルード関係が図示化されます。C++では、名前空間やクラス/テンプレートライブラリを使うのにヘッダーファイルをインクルードする必要があるので、サンプルコードの実装方法の確認などでも、便利でしょう。

 

Visual Studio 2012でデバイスドライバー開発

$
0
0

Visual Studio 2012は、デバイスドライバーを通常のアプリ開発と同じように開発できるようになっています。デバイスドライバー開発は、以前はほぼ完全にコマンドラインツールを駆使したものでしたが、今は、プロジェクトテンプレートからプロジェクトを作成し、開発できるようになっています。

Visual Studio 2012でデバイスドライバーを開発するためには、先ず、WDK(Windows Driver Kit)をインストールします。

http://msdn.microsoft.com/ja-JP/windows/hardware/gg487428/

から、ダウンロード&インストールを行ってください。PCにVisual Studio 2012(有償版)がインストールされていれば、デバイスドライバー開発に必要な環境一式がVisual Studio 2012に追加されます。WDKのインストールが終わったら早速Visual Studio 2012を起動し、新しいプロジェクト作成メニューを選択してみてください。

VC++の下にWindows Driverというカテゴリが追加され、各種デバイスドライバー、デバイスドライバー向けサンプルアプリ、インストールパッケージ、テスティングフレームワークといったプロジェクトが用意されます。これを取っ掛かりにプロジェクトを作成できるようになったわけです。デバイスドライバーのビルドや、UDMFのドライバーなどは、ソースコードレベルデバッグなども一貫したVisual Studio 2012のUIを使って行うことができます。一つ前のポストで紹介したアーキテクチャの依存関係グラフなども生成が可能で、ドライバーの構造を可視化することができます。また、TFSでのソースコード管理も以前より容易に行えるなど、Visual Studio 2012に関連する機能を使い倒すことができるようになっています。更に、Static Driver VerifierもGUI化されました。

何かIssueがある場合は、Resultのリンクをクリックすると、

レポートページが表示され、該当するソースコードを表示できます。

ドライバーの静的解析はずいぶん昔に話題になったことがあるのを覚えていますが、こちらも試してみてください。

Visual Studio 2012によるドライバー開発は2012年4月に行われたWDD(Windows Developer Days)で、デバイスドライバーズの日高さんが、セッションを担当されています。

http://channel9.msdn.com/Events/Windows-Developer-Days/Windows-Developer-Days-2012/SP-006

CP版の頃の話なので若干古い部分はありますが、こちらもご覧ください。

 

 

Windows 8 Store アプリをリモートからデバッグ

$
0
0

Windows 8 Storeアプリでは、加速度センサー、ジャイロセンサー、コンパス、GPS、オリエンテーションなど色々なセンサーを使ったアプリ開発が可能です。モーション系のセンサーを使ったアプリを開発する場合、デバッグするには、当然端末を傾けたり、振り回してみたり、叩きつけ…(いや、叩き付けるのはやらないでね)しないと、計測したセンサー値を基に正しくアプリが動作するかチェックができません。で、端末を動かしていると「変な人がいる」…とか言われたりするのですが、それはさておき、同じPC上でVisual Studioを使ってデバッグするのは無理です。

そんな時に便利なのがリモートデバッグ機能です。このポストではリモートデバッグの使い方を説明します。

2012/12/3現在、Visual Studio 2012のUpdate 1が既に公開されているので、先ずはVisual StudioをUpdateしましょう。Updateは、

http://www.microsoft.com/visualstudio/jpn/downloads

のVisual Studio 2012 Update 1タイルをタッチして、今すぐインストールをタッチして更新可能です。

更に、このタイルの下の方に、”Remote Tools for Visual Studio 2012”というタイルがあるのでそれもタッチして、リモートデバッグしたいターゲットPCのCPUに対応するソフトをタッチしていインストールします。(この作業はリモートデバッグのターゲットデバイス上で行うことに注意)

Remote Toolsのインストールがすむと、ターゲットPCのスタート画面にRemote Debuggerというタイルが追加されます。

リモートデバッグするには、

  • 開発用PC(VS2012がインストールされていて、プログラミング&デバッグを行うPC)
  • ターゲットPC(Remote Debuggerがインストールされていて、プログラムを実行させるPC)

を2台とも同じネットワークに接続しておきます。

まず、ターゲットPC上でRemote Debuggerのタイルをタッチして、Remote Debuggerを起動します。
認証や、Windows Firewallに関する設定が出てきますが、それはデフォルトでOKです。起動が完了すると

と、Windowが表示されます。

開発用PCでVS2012を立ち上げ、ストアアプリを作ります。C#の場合はプロジェクトのプロパティを表示し、”デバッグ”タブを選択します。

ターゲットデバイスのコンボボックスから、”リモート コンピューター”を選択し、”検索(I)…”ボタンをクリックします。

ターゲットPCできちんとRemote Debuggerが動いていて、ネットワークにきちんと2台ともつながっていれば上のようなダイアログでターゲットPCが表示されます。
接続したいターゲットPCの選択ボタンをクリックします。ユーザー名とパスワードを聞いてくるので、ターゲットPC側でサインインしているマイクロソフトアカウント(メールアドレス:@hotmail.comとか@live.jp、@hotmail.co.jpなど)をユーザー名のボックスに、パスワードにはサインインするときのパスワードを、それぞれ入力し、”OK”をクリックします。

これで準備万端です。

デバッグ対象のコンボボックスから、リモートコンピューターを選択して、デバッグを開始すれば、ターゲットPC上で開発中のアプリをターゲットPC上でデバッグ実行できます。

 

 

.NET Micro Frameworkでネットワークプログラミングする時に便利なクラス達

$
0
0

今、.NET GadgeteerでWindows Azure Storageのテーブルに接続するコードを書いているところですが、よく使うクラスと使用上の注意点をメモっときます。

RESTでWebサービスに接続するには、当然

  • HttpWebRequest
  • HttpWebResponse

の二つのクラスが必要です。そして当然の様に用意されています。若干の細かい違いはあるものの、フルの.NET Frameworkのライブラリとほぼ同じ。デスクトップアプリやWebアプリでのコーディングそのままの勢いで書いちゃってください。名前空間は同じく、System.Netです。使うときには、プロジェクトの参照にSystem.Http アセンブリを加えてください。

XMLデータを受信して解析するには、

  • XmlReader

を使います。このクラスはフルの.NET Frameworkとはかなりメソッド構成が違います。このクラスの使い方はまた別の機会で。名前空間はSystem.Xmlで、使うにはSystem.Xml アセンブリーを参照に追加してください。System.Xml.Legacy アセンブリーは必要ありません。XmlReaderがあるならXmlWriterを使いたい…そんなあなたへ。一応System.Ext.Xml空間にありますが、このクラスは、DPWS(Device Profile For Web Service)ライブラリ用に用意されているクラスで、MFDpwsExtentions というアセンブリーで提供されています。このアセンブリーは比較的サイズが大きく、フルの.NET FrameworkのXmlWriterとは使い勝手も違い、更に、XML文を組み立てるなら、文字列の足し算で十分じゃない?ということで、DPWSを使う場合以外は使わなくてもよいでしょう。小型の組込み機器制御だし。

文字列を組み立てるとなると、

  • StringBuilder

も欲しいところです。このクラス、.NET Micro Frameworkの過去のバージョンでは、名前空間が違うところにあったりしたのですが、4.xではSystem.Textにちゃんと用意されています。

で、URL文を組み立てる段になると、UriクラスのEscapeDataString()メソッドが欲しくなります。これは、.NET Micro FrameworkのUriクラスには用意されていません。困ったな。現在調査中ですが、

  • Regex

クラスのEscape()メソッドがどうやら使えそう。このクラスは、System.Text.RegularExpressions 名前空間にあります。使う場合は、名前空間と同じ名前のアセンブリーを参照に追加してください。

さて。HttpWebRequestクラスを使い、GetRequestStream()メソッドでストリームを取り出して、データをWebサーバーに送る場合、UTF8でエンコードされたバイト列に文字列を変換します。これは、

  • Encoding.UTF8.GetBytes(body)

でエンコード可能です。System.Text名前空間にEncodingクラスがあります。

更に、暗号化など行う場合は、私のブログの前に投稿した記事を見てもらう必要があります。SHA1、HMACなどで暗号化したバイト列を今度はBase64エンコーディングした文字列への変換が必要になります。

  • Convert.ToBase64String(buf)

というようにConvertクラスのToBase64String()メソッドで一発変換。

といったように、一通りWebプログラミングに必要なクラス、メソッドが用意されているので、.NET Gadgeteer/Micro Frameworkで、ネットワーク連携プログラミングをお楽しみください。

 

2012年12月18日時点での公開中テンプレート使用に関する注意

$
0
0

http://msdn.microsoft.com/ja-jp/jj556277

から公開中のEntertainment Photo、Basic Photoテンプレートにちょっとした不具合があるので、ご注意。アプリパッケージを作成する前に、Package.appxmanifestを開いて、下図の

エントリポイントを変更してください。”.App”の前の文字をプロジェクト名に置き換えてください。例えば、プロジェクト名が、”FavoritMusic”なら、

”FavoritMusic.App”

です。お手数をおかけして申し訳ないです。

 

 


Windows 8ストアアプリ開発用 Entertainment PhotoテンプレートのUpdate

$
0
0

皆様

http://msdn.microsoft.com/ja-jp/jj556277

から公開しているEntertainment Photoテンプレートを更新しました。更新前のテンプレートには色々と不具合があって、既に使われている皆様にはご迷惑をおかけして申し訳ありませんでした。年末から年初にかけて、このテンプレートをベースにアプリを一本開発してWindows ストアの審査を通す過程で、いくつか不具合を見つけたので、テンプレートの修正を行い、V2として公開中です。修正したバグは、

  • 固定グループを埋め込んだ状態で、2回目以降起動時にException発生
  • グループに追加されている画像を削除すると直後にException発生

の2う項目。

ちなみに、審査を通して公開されたアプリは、http://apps.microsoft.com/windows/app/827922dc-497c-48ae-aeb4-b826d209fe9cで公開されている”夕焼け倶楽部”というアプリです。このアプリ自体は、夕焼けの写真をコメントを付与しながらアルバム化していくという単純なアプリです。

Entertainment Photoテンプレートでは、Visual Studio 2012が提供するグリッドアプリテンプレートを基に、グループ、及び、グループに所属のアイテムの追加・削除、および、アイテムへの付帯情報付与・編集機能を追加しています。グループ、及び、アイテムは、アプリに埋め込まれて削除や追加ができないグループ・アイテムを用意することもできます。画像や手順などを固定で埋め込んで、関連する情報をユーザーが追加していく様なアプリを開発する際にお使いください。トップ画面のセマンティックズーム、各ページのスナップ表示、検索、共有、プライバシーポリシーなど一通り入っています。

追加したグループやアイテムの情報は、アプリストレージに格納しているので、アプリストレージのサンプルとして見るのも良いでしょう。

 

WinRT APIを使って画像ファイルの位置情報を編集する

$
0
0

WinRT APIには、画像ファイルの位置情報を取り出すAPIが用意されています。

位置情報を取り出すのはとても簡単で、imageFileをStorageFile型のオブジェクトとすると、

        var imageProps = await imageFile.Properties.GetImagePropertiesAsync();

で、imagePropsのLatitude、Longitudeから緯度、経度を取得可能です。この二つのプロパティの型は、double?で、Nulable型になっています。画像ファイルに位置情報が付与されていない場合には、この二つの値はnullです。加えて、この二つのプロパティは、Readonlyで書き換えができません。Windows Phoneデバイスのカメラでは、位置情報を付与してJPEGファイルとして保存することができますが、多分、位置情報付きの画像ファイルはそれほど多くはないのではないかと思われます。位置情報が付与されているのであれば、既にストアから公開(http://apps.microsoft.com/windows/app/f7f0662c-ba9d-4bb3-a6d5-a1559c970aeb )されている、”どこの写真”アプリの様に、

と、写真を地図上に撮った位置にマップして表示する事ができたりするので、色々と便利なんですね。画像ファイルのデータをバイナリレベルで色々と弄れば位置情報を編集するのは可能なのですが、WinRT APIで変更する方法はないかな…と探していたところ、やり方がForum上で公開されているのを見つけました。情報元はこちら。

http://social.msdn.microsoft.com/Forums/nl/winappswithcsharp/thread/aaf0b373-b0e0-4d91-84d8-69e768a374d8

LatitudeとLongitudeを、そのまま保持しているのではなく、別の形式のデータから計算して取得しているので直接はかえられないみたいですね。内部の形式は、上のURLからたどって調べてもらうとして、以下に画像ファイルの位置情報を編集するコードの例を挙げておきますね。

    class LocationHelper
    {
        publicstaticasyncTask<ImageProperties> AddLocation(StorageFile imageFile, double latitude, double longitude)
        {
            int[] denomitor = newint[3] { 1, 1, 1000 };
            string latitudeRef = "N";
            if (latitude < 0)
            {
                latitudeRef = "S";
                latitude *= -1;
            }
            string longitudeRef = "E";
            if (longitude < 0)
            {
                longitudeRef = "W";
                longitude *= -1;
            }

            int[] latitudeNumerator = newint[3] { 0, 0, 0 };
            int[] longitudeNumerator = newint[3] { 0, 0, System.GPS.LatitudeNumerator0 };

            Calcurate(latitude, denomitor, ref latitudeNumerator);
            Calcurate(longitude, denomitor, ref longitudeNumerator);

            var props = newList<KeyValuePair<string, object>>();
            props.Add(newKeyValuePair<string, object>("System.GPS.LongitudeNumerator", longitudeNumerator));
            props.Add(newKeyValuePair<string, object>("System.GPS.LongitudeDenominator", denomitor));
            props.Add(newKeyValuePair<string, object>("System.GPS.LongitudeRef", longitudeRef));
            props.Add(newKeyValuePair<string, object>("System.GPS.LatitudeNumerator", latitudeNumerator));
            props.Add(newKeyValuePair<string, object>("System.GPS.LatitudeDenominator", denomitor));
            props.Add(newKeyValuePair<string, object>("System.GPS.LatitudeRef", latitudeRef));

            await imageFile.Properties.SavePropertiesAsync(props);
            var imageProps = await imageFile.Properties.GetImagePropertiesAsync();
            return imageProps;
        }

        privatestaticvoid Calcurate(double val, int[] denomitor, refint[] numerator)
        {
            numerator[0] = (int)System.Math.Floor(val);
            val -= numerator[0];
            if (val >= 0)
            {
                val *= 60;
                numerator[1] = (int)System.Math.Floor(val);
                val -= numerator[1];
                if (val >= 0)
                {
                    val *= 60;
                    numerator[2] = (int)(System.Math.Round(val * denomitor[2]));
                }
                else
                {
                    numerator[2] = 0;
                }
            }
            else
            {
                numerator[1] = 0;
                numerator[2] = 0;
            }
        }
    }

内部形式は、方位と度、分、秒を基本としたデータ構造ってわけです。更新の際に使われているキーワードは、

http://msdn.microsoft.com/en-us/library/windows/desktop/ff514245(v=vs.85).aspx

に載っているものが使われています。

以上、画像ファイルの位置情報に関するTipsでした。

 

 

WinRT APIでJSONフォーマットをデシリアライズする方法

$
0
0

現在、Twitterのフォロー/フォロワー状況を分析するWindowsストアアプリを作っています。Twitter APIは現在V1.1に移行することを推奨されているので、さぁ使おうとしたら、XML形式でのデータダウンロードはなくなっているんですね。

JSONか…ってことで、このポストではネットなどからダウンロードしたJSONフォーマットのテキストをWinRT APIを使ってC#でデシリアライズする方法を紹介します。

実はとっても簡単、DataContractJsonSerializerクラスを使います。namespaceは、System.Runtime.Serialization.Jsonです。例えばTwitterのFollowerを取得するAPIを使うと、フォローしているユーザーのIDのリストと、2000項目以上のフォロワーがいる場合に、更に情報を取得するためのカーサー情報がJSON形式で受信されます。これを解析するには、

    [DataContract]
    public class TwitterRelationships
    {
        [DataMember]
        publicList<string> ids;
        [DataMember]
        public int next_cursor;
        [DataMember]
        public string next_cursor_str;
        [DataMember]
        public int previous_cursor;
        [DataMember]
        public string previous_cursor_str;
    }

という、受信テキストデータに合わせたクラスを定義して、以下を実行します。streamは、例えば、HttpWebResponseのGetResponseStream()メソッドで取得したJSONデータを取り出すストリームです。

    var ser = newDataContractJsonSerializer(typeof(TwitterRelationships ));
    TwitterRelationships tr = (TwitterRelationships )ser.ReadObject(stream);

これでお仕舞。簡単ですね。ちなみにユーザー情報をIDから取得したJSONをデシリアライズするには、

    [DataContract]
    public class TwitterUserProfile
    {
        [DataMember]
        public string id;
        [DataMember]
        public string screen_name;
        [DataMember]
        public string profile_image_url_https;
        [DataMember]
        public int followers_count;
        [DataMember]
        public bool Protected;
        [DataMember]
        public string description;
        [DataMember]
        public int friends_count;
        [DataMember]
        public string name;
    }

というようなクラスを定義して、

    var ser = newDataContractJsonSerializer(typeof(TwitterUserProfile));
    TwitterUserProfile tr = (TwitterUserProfile)ser.ReadObject(stream);

で、デシリアライズできます。クラスの定義の時は、JSONで記述されている全ての項目をプロパティとして定義する必要はなく、必要な項目だけ定義すればそれでOKです。

 

WinRT APIによるファイル保存時の注意

$
0
0

WinRT APIを使ってテキスト情報などをファイルに保存する場合のちょっとした注意です。

テキストのファイル保存は、Windows.Storage名前空間のStorageFile、TextWriterクラス等を使います。具体的には、

    List<string> statements = …;
    StorageFile file = …;
    using (var fo = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
        TextWriter writer = new StreamWriter(fo.AsStreamForWrite());
        foreach (var s in statements)
        {
            await writer.WriteLineAsync(s);
        }
        writer.Flush();
    }

こんな感じのコードになります。fileは、FilePickerによるファイル選択やアプリストアから作成してください。注意点として、赤字で書いたステートメントを入れてください。TextWriterはある一定のサイズごとに書き込むようで、Writerに対して書き込んだ情報を物理ストレージに吐き出させるFlushメソッドをコールしないと書き込んだつもりのテキスト情報が全て保存されない場合があります。ファイルに書き込んだはずのデータ量と実際に保存されたファイルのサイズが異なる場合は、この点をチェックしてみてください。

.NET Micro Framework 4.3リリースされてます

$
0
0

実はリリースされてからちょっと経ってしまっているのですが、超小型組込み機器向けファームウェア.NET Micro Frameworkが2012年12月にリリースされています。最新バージョンは4.3です。Visual Studio 2012で.NET Micro Frameworkのプログラミングができるようになりました。勿論、Porting Kitも同時にバージョンアップされています。本家の情報は、

http://blogs.msdn.com/b/netmfteam/archive/2012/12/04/netmf-4-3-released.aspx

から。詳しい機能アップデート情報はこちらから。

http://netmf.codeplex.com/wikipage?title=Roadmap%20for%20Next%20Version

後は、早く.NET Gadgeteerが.NET Micro Framework V4.3に対応してくれれば…

 

 

 

NFCをWindows 8 ストアアプリで活用する

$
0
0

さぁWindows 8 ストアアプリでNFCです。

Win RT APIには、近接通信(NFC)するためのProximity APIが用意されています。NFC付のPCであれば、この機能を使ったアプリケーションを動かすことができます。NFCはNear Field Communicationの略で、ベンダー非依存の近距離無線通信規格です。Bluetooth LEやWi-Fi Direct、非接触タグリーダー/ライター等を使って近距離にあるデバイスやタグの間でデータを交換可能です。

Windows 8 ストアアプリでは、Windows.Networking.Proximity名前空間に用意されたクラスライブラリを使って、NFCを活用したアプリを開発できます。

Proximity APIを使って出来ることは、以下の3種類です。

  1. 非接触タグの読込/書込み
  2. タップによるPC間のデータ送受信(Bluetooth LE)
  3. ブラウズによる発見とPC間のデータ送受信(Wi-Fi Direct)

最初の機能は非接触型のプリペイドに対するデータ読み書きです。皆さんよくお使いの非接触型のプリペイドカードが代表選手です。非接触型のタグにデータを書き込んだり、タグからデータを読み込んだりできます。単にデータを読み込むだけでなく、データの形式(テキスト、JPEG、WAVなど)に紐づいたアプリケーションの起動も可能です。URLを指定してブラウザでWebのページを表示させることもできます。他にも、特定のWindowsストアアプリを起動(インストールされていない場合はWindowsストアの該当アプリのページを表示)させることも可能です。タグをリーダー部分に近づけた時、スタート画面にトースト通知が出て、ユーザーに許可を求めるので、勝手に変なデータを送りこまれることはありません。

次の機能は、PCのNFCデバイスがある場所を4㎝以内に近づけ(タップ)てペアリングを行い、データを送受信する機能です。従来のBluetoothの様にパスコードを入力するなどの手間は必要ありません。タップするとスタート画面の右上に、ユーザーの承諾を得るためのトースト通知が表示されます。ユーザーの承認後、2台のPC間でデータのやり取りが可能になります。

最後の機能は、Wi-Fi Directを用いた通信です。通常のWi-Fiがアクセスポイントに接続してネットワークにつながり、ネットワークを介して通信するのに対し、Wi-Fi Directは、ルーターを介さずに、各PCのWi-Fiデバイスが直接Peer To Peerで接続してデータ通信を行える機能です。アクセスポイントが無くても、Wi-Fi Direct対応のデバイス間でなら、ネットワーク通信ができるというとても便利なものです。ただし同時に接続できるのは1対1ですが。

WinRT APIでは、ProximityDeviceとPeerFinderという二つのクラスが用意されています。1.の機能はProximityDeviceクラスを使って、2.と3.の機能はPeerFinderクラスを使って実装可能です。これらの機能の詳しい説明は、

http://msdn.microsoft.com/ja-jp/library/windows/apps/xaml/hh465221.aspx

に書かれているので参考にしてください。今後、各機能について、このブログでも、実際にProximity APIを使うときの注意点などを書いていきますので、こうご期待。
残念ながら、NFCは現在販売されている全てのWindows 8 PCに装備されているものではありません。ARM版のWindows RT PC(タブレット)の場合は、ついている場合が多いです。SONYのVAIOは大概ついています。PCを購入する場合は、カタログに、NFC、Bluetooth LE等の言葉があるか確認してみてください。もしくは、量販店などで実際に触って試せる場合には、コントロールパネル→デバイスマネージャを開き、

  • Bluetoothの下位にBluetooth LEがあるか            2の機能が使える
  • ネットワークアダプターの下位にWi-Fi Directがあるか      3の機能が使える
  • 近接通信デバイスがあるか                     1の機能が使える

の三点を確認してみてください。NFC、はっきり言って面白いです。ストアで公開されているアプリもNFC対応は今のところあまりありません。NFC自体新しい機能なので利用シナリオもアイデア次第で色々出てきそうです。NFCを使った良いアプリが沢山出てくれば、NFC対応のWin8 PCも種類が増えるでしょう。

NFC機能を使うアプリは、Package.appxmanifestで、機能タブの”近接”にチェックを入れてください。

皆さん、NFCを活用したアプリを開発して、Windowsストアで公開しませんか?

次回は、タグの読み書きに関するTipsを投稿の予定

 

Proximity APIでタグへのデータ読み書き

$
0
0

Proximity APIによるNFC関連ネタ第二弾です。

Windows 8 ストアアプリでは、Proximity APIを使って非接触タグに対するデータの読み書きが可能です。

タグに記憶されているデータをNFCリーダーで読込んで、以下のことができます。

  • テキストデータならText Editor、JPEGデータならPhotoアプリというように、読込んだデータフォーマットに合わせてそのデータを扱うアプリを起動
  • 読込んだURLを基にブラウザで表示
  • Windowsストアアプリを引数付きで起動(インストールされていない場合は、Windowsストアのアプリページを表示)

上の3つができるためには、タグにデータが書き込まれていなければなりません。Proximity APIを使えば、タグにデータを書き込むことができます。

さぁ始めよう…でも非接触タグなんてないよ~って方。例えば、https://www.facebook.com/RealTouchShopとかで買えます。東京駅の八重洲中央口を出て少し行ったところで実物見て買えます。あ、それから、NFCリーダー付のWindows 8 PCをご用意ください。

先ずは、書き込みです。テキストデータの書き込みは、

    var device = ProximityDevice.GetDefault();
    if (device == null)
    {
        tbStatus.Text = "This Device doesn't support NFC!";
        return;
    }
    var kindSelect = "Spade";
    var numberSelect = "Ace";
    string messageType = "WindowsMime:WriteTag.text/plain";
    string message = string.Format("mark={0},number={1}", kindSelect, numberSelect);
    var writer = newDataWriter();
    writer.UnicodeEncoding = UnicodeEncoding.Utf16LE;
    writer.WriteString(message);
    publishedId = device.PublishBinaryMessage(messageType , writer.DetachBuffer(), (provider, msg) =>
    {
        provider.StopPublishingMessage(msg);
    });

こんな感じでおしまい。NFCリーダー付きのPCはそんなに多くないので、最初にチェックをします。Windows.Networking.Proximity名前空間のProximityDeviceクラス、このGetDefault()メソッドのコール結果がnullでなければ、非接触タグの読み書きが可能です。

書き込みの基本は、DataWriterクラス(名前空間はWindows.Storage.Streams)で書き込むデータを組み立て、ProximityDeviceのPublishBinaryMessage()でデータのタイプを指定して書き込む、という流れです。Publishメソッドをコールすると、NFCリーダーは書き込み待ちになるので、非接触タグをNFCリーダーに近づけるとタグへの書き込みが行われます。Publishメソッドをコールしっぱなしだと、複数のタグに書き込みできます。ただ、書き込み済みのタグを誤って書き換えてしまうこともあるので、コードの最後に示すように、StopPublishingMessage()メソッドをコールして、書き込みを終了します。

上に示したコードでmessageTypeに代入している文字列は、メッセージのフォーマット指定です。上の例では、平文のテキストです。他のデータフォーマットを送りたい場合は、

http://msdn.microsoft.com/ja-jp/library/windows/apps/hh701129.aspx

を見てください。

次にブラウザで開くURLの書き込みです。上のコードで、messageTypeに"WindowsUri:WriteTag"を、messageに表示したい、URLをセットすれば、OKです。

次にWindowsストアアプリを起動するデータを書き込む方法です。messageTypeは、"LaunchApp:WriteTag"を指定してください。messageの部分は、

    string launchArgs = String.Format("mark={0},number={1}", kindSelect, numberSelect);
    string praid = "App";
    string appName = Windows.ApplicationModel.Package.Current.Id.FamilyName + "!" + praid;

    string message = launchArgs + "\tWindows\t" + appName;

で組み立てます。launchArgsは、起動するWindowsストアアプリに渡す引数です。praidの”App”は、Package.appxmanifestをコードで開いて、<Applications>の下位の<ApplicationId="..." のIdアトリビュートの値を書いてください。Package.appxmanifestのGUI表示のIdではないのでご注意。
messageのフォーマットは、

アプリ引数 + プラットフォーム + 起動するアプリ

という形式です。これで書き込んだタグを近づけると、

こんな感じでトーストノーティフィケーションが表示されます。これをタップすると、

アプリが起動します。ユーザーがOKを出さないとアプリは起動されないので、勝手に変なアプリを密かにすれ違いざまに入れられてしまうということは出来ません。安心ですね。

URLを書き込んだタグをNFCリーダーに近づけると、

こんな表示が出ます。これをタップするとブラウザが起動します。

さて、テキストや画像の場合ですが、読込み方法は、

        var subscribedId = device.SubscribeForMessage("NDEF:MIME.text/plain", (provider, message) =>
        {
            var data = message.Data;
            byte[] buffer = newbyte[data.Length];
            var reader = DataReader.FromBuffer(data);
            reader.ReadBytes(buffer);

というコードで読込みます。ProximityDeviceクラスのSubscribeForMessage()メソッドをコールして、タグがタップされるのを待ちます。この際、第一引数に読込みたいデータのフォーマットを指定します。タグがタップされれば、var data以降のコードが実行され、bufferにタグに書き込まれていたバイナリ―データが読み込まれます。
第一引数は、http://www.nfc-forum.org/が規定しているフォーマットで指定します。書き込むときの指定と違うのでご注意ください。NDEF形式で読込まれたデータを元に戻す方法はまた別のポストで説明しますね。

タグの読み書きは以上です。是非お試しください。

 


 

 


FEZ Spider、FEZ Hydra、FEZ Cerberusがデバッグでつながらない?

$
0
0

昨年..NET Micro Framework4.2に対応した新しいバージョンの.NET Gadgeteerがリリースされました。.NET Gadgeteer SDKがアップデートされると、FEZ Spider、FEZ Hydra、FEZ CerberusのFirmwareをアップデートする必要があります。

アップデートの方法は、http://wiki.tinyclr.com/index.php?title=Firmware_Updateを忠実に実行すればOKです。アップデートしたのにVisual Studioのデバッグ実行でボードが反応しない!!という場合、デバイスドライバーを確認してみてください。

コントロールパネルからデバイスマネージャーを開いてください。

このように、”Debuggable .Net Micro Framework Device”→”GHI .NET Micro Framework USB Debugging Interface"という項目があるか確認してください。これが無い場合、”ユニバーサルシリアルバスコントローラー”の項目に”GHI NETMF Debug Interface”があるか確認してください。FEZボードをUSB接続して、デバイスドライバーがこの項目でインストールされてしまっている場合、Visual Studioでデプロイ&デバッグしようとしてもできません。
この項目を右クリックし、”ドライバーソフトウェアの更新”を選択、”コンピューターを参照してドライバーソフトウェアを更新します”をクリックします。さらに”コンピューター上のデバイスドライバーの一覧から選択します”をクリックして、表示されたリストの中から、”GHI .NET Micro Framework USB Debugging Interface"を選択して正しいデバイスドライバーをインストールしてください。

もし、ユニバーサルシリアルバスコントローラの下に該当するものが無ければ、COMポートの下に”GPS Camera”という項目が無いかチェックしてみてください。この項目がある場合、ボードのファームウェアの更新が中途半端で終わっていない可能性があります。ファームウェアの更新手順を最初からやり直してみてください。

 

 

Proximity APIでWi-Fi Direct通信

$
0
0

WinRT APIは、Proximity APIを通じてWi-Fi Direct通信を行えます。通常のWi-Fiは、アクセスポイントを通じてインターネットにつながったデバイスの間で通信が可能ですが、アクセスポイントが無ければデバイス間で通信はできません。Wi-Fi Directは、アクセスポイントが無くても、サポートしているデバイス間でP2Pで接続し、データ通信を可能にする技術です。ハードウェアは通常のWi-Fiと同じものが使えます。アクセスポイントを介さずにつなげられるので、データ漏えいの危険も減ります。考えてみれば、単にデータを交換したいだけならば、インターネットに接続する必要はないわけです。近場にいる人とのショートメッセージやイメージデータの交換ができるので、ローカルSNSや近場のマルチユーザーゲームなど、アイデア次第で様々な応用が考えられます。

http://www.wi-fi.org/discover-and-learn/wi-fi-directを見ると、Wi-Fi Directはデータ転送が250Mbpsとかなり高速、ハードウェアは従来のWi-Fiそのままが使える、通信に関するセキュリティ、アクセスポイントとの併用など、かなりいい感じです。これを活用しない手はありません。しかし、現時点ではすべてのWindows 8 PCがWi-Fi Directをサポートしているわけではないので、ご注意。ま、持ってる者同士でつながってください。

使い方を以下に説明していきます。Wi-Fi Directは、Windows.Networking.Proximity名前空間のPeerFinderクラスを使います。最初に、アプリが動作しているPCでWi-Fi Directが使えるかをチェックします。PeerFinderクラスのSupportedDiscoveryTypesプロパティをチェックします。

        if ((PeerFinder.SupportedDiscoveryTypes & PeerDiscoveryTypes.Browse) == PeerDiscoveryTypes.Browse)

このプロパティは、ビットフラグなので、上の様なチェックをします。この条件がtrueであれば、Wi-Fi Directを利用可能です。falseの場合には、「Wi-Fi Direct機能付きのPCを購入してね」といったメッセージを出しましょうw。

Wi-Fi Directで接続するためには、別のPCからブラウズできるようにしておく必要があります。

               PeerFinder.ConnectionRequested +=
                   newTypedEventHandler<object, ConnectionRequestedEventArgs>
                       (PeerFinder_ConnectionRequested);
               PeerFinder.Start();

Start()をコールすると、同じストアアプリがフロントで動いているPC上で、探すことができるようになります。ConnectionRequestedイベントは、別のPCからの接続要求を受け付けるためのものです。

同じストアアプリが動いていて、Start()メソッドをコール済みのPCを探すには、

            var peers = awaitPeerFinder.FindAllPeersAsync();
            foreach (var peer in peers)
            {

と、FindAllPeersAsync()を使います。peersは、PeerInformationというクラスのインスタンスのリストです。DisplayNameプロパティで相手のデバイスの名前が判ります。

Wi-Fi Directで接続する場合、

                var streamSocket = await PeerFinder.ConnectAsync(peer);

と、ConnectAsync()をコールします。接続が完了すると、通信するためのストリームソケットを取得できます。
ストリームソケットを取得で来たら、データの受信待ちを開始します。streamSocketからデータ送受信の為のReaderとWriterを作成します。

            peerWriter = newDataWriter(streamSocket.OutputStream);
            peerReader = newDataReader(streamSocket.InputStream);

peerWriterとpeerReaderは、別の目的でも使用するのでクラスのメンバー変数として定義しておきましょう。ストリームソケットを基にDataRearインスタンスを作成したら、あとは、LoadAsyncやReadXXXメソッドを使ってデータを受信し続けます。データの送受信については、別の投稿で詳しく解説する予定ですのでそちらを参照してください。

別のPCがFindAllPeersAsync()メソッドで発見し、ConnectAsync()メソッドをコールして接続要求をすると、先ほど紹介したようにConnectionRequestedイベントに登録したハンドラがコールされます。この要求を受け付ける場合、

            var streamSocket = await PeerFinder.ConnectAsync(e.PeerInformation);

と、ConnectAsync()メソッドをコールします。ConnectionRequestedイベントハンドラの引数のPeerInformationプロパティに接続要求を出したPeerの情報が入っています。ConnectAsync()メソッドをコールして得られたストリームソケットを使ってデータの送受信を行うわけです。AcceptAsync()メソッドをコールしなかった場合はWi-Fi Direct接続要求は無視され、タイムアウト処理されます。Start、FindAllPeersAsync、ConnectAsync、AcceptAsyncのすべてのメソッドコールで、try、catchで例外を捕捉して適切な処理をすることを忘れずに。

以上の流れを図に示しておきますね。

DataReaderインスタンスの作成、LoadAsync、ReadXXXメソッドによるデータ受信で一つ注意をしておきます。この一連の流れの中で通信にかかわる以外のawaitをつけたコール(メッセージダイアログやUIの表示を直接更新するようなDispatcherへ委譲など)は実行しないでください。これをやると、折角接続できたPeerとの通信が切断されてしまうという現象が起こるようです。

次のポストでは、データの送受信について解説します。お楽しみに。

 

Proximity APIを使ってWi-Fi Directでデータ通信

$
0
0

さて、データの送受信です。

ConnectAsync()メソッドの戻り値、または、ConnectionRequestedイベントの引数のPeerInformationから作成したストリームソケット、さらにそのストリームソケットから作成したDataReader、DataWriterを使ってデータの送受信を行うコードを紹介します。送受信するデータの形式は、

とします。”フォーマット”、”テキストやイメージなど”のブロックは、可変長データを送りあうために

とします。

先ずテキストデータですが、

        public async void SendMessage(string message)
        {
            string msgType = "text/plain";
            uint len = peerWriter.MeasureString(msgType);
            peerWriter.WriteUInt32(len);
            peerWriter.WriteString(msgType);

            uint msgLen = peerWriter.MeasureString(message);
            peerWriter.WriteUInt32(msgLen);
            peerWriter.WriteString(message);
            var writeBytes = await peerWriter.StoreAsync();
        }

で送信可能です。peerWriterはストリームソケットから作成したDataWriterです。MeasureString()メソッドでフォーマットの文字列や送信するメッセージ文字列の長さを取得し、WriteUInt32()メソッドで書き込みます。string型のデータは、WriteString()メソッドを使って書き込みます。
データをすべて書き込んだら、StoreAsync()メソッドをコールして、Connect&AcceptしたPeerにデータを送信します。この例では、フォーマット指定は、MIMEタイプを借用しています。独自に定義するよりは、ありものでよく使われているものを使った方が良いでしょう。

次に画像ファイルです。

        public async void SendJpeg(StorageFile jpegFile)
        {
            string msgType = "image/jpeg";
            uint len = peerWriter.MeasureString(msgType);
            peerWriter.WriteUInt32(len);
            peerWriter.WriteString(msgType);
           
            len = peerWriter.MeasureString(jpegFile.Name);
            peerWriter.WriteUInt32(len);
            peerWriter.WriteString(jpegFile.Name);

            var content = awaitFileIO.ReadBufferAsync(jpegFile);
            peerWriter.WriteUInt32(content.Length);
            peerWriter.WriteBuffer(content);
            var writeBytes = await peerWriter.StoreAsync();
        }

フォーマット名を画像用に変えています。フォーマットの部分はテキストの時と同じです。上の例では、”フォーマット”+”ファイル名”+”画像データ”の順で送信データを組み立てています。どのブロックも、データ長+データ本体で構成しています。画像ファイル(JPEG)の中身は、FileIOクラスのReadBufferAsync()メソッドで取り出しています。取り出したデータ列は、DataWriterのWriteBuffer()メソッドで書き込めます。

他のデータ形式を送りたい場合には上のコードを参考にして色々と工夫してみてください。Wi-Fi Directによる通信の場合、基本的にはアドホックディスカバリーのP2Pなので複雑な手順を含むようなプロトコルよりも送りたいときに送る形式の方が良いでしょう。

以上説明した方法でデータが送信されることを前提に、受信方法を説明します。このポストを読んでトライした読者が色々嵌ってしまわないように、筆者が実際に動作することを確認した主要コードを以下に示しますね。ちょっと長いですがじっくりと読んでください。

        private async void StartReader( CoreDispatcher dispatcher)
        {
            Exception currentEx = null;
            bool hasClosed = false;
            try
            {
                uint bytesRead = await peerReader.LoadAsync(sizeof(uint));
                if (bytesRead > 0)
                {
                    var typeLen = peerReader.ReadUInt32();
                    bytesRead = await peerReader.LoadAsync(typeLen);
                    if (bytesRead > 0)
                    {
                        var msgType = peerReader.ReadString(typeLen);
                        switch (msgType)
                        {
                            case"text/plain":
                                bytesRead = await peerReader.LoadAsync(sizeof(uint));
                                if (bytesRead > 0)
                                {
                                    var msgLen = peerReader.ReadUInt32();
                                    bytesRead = await peerReader.LoadAsync(msgLen);
                                    if (bytesRead > 0)
                                    {
                                        var msg = peerReader.ReadString(msgLen);
                                        WriteStatusAsync(dispatcher, msg);
                                    }
                                    else
                                    {
                                        hasClosed = true;
                                    }
                                }
                                else
                                {
                                    hasClosed = true;
                                }
                                break;
                            case"image/jpeg":
                                bytesRead = await peerReader.LoadAsync(sizeof(uint));
                                if (bytesRead > 0)
                                {
                                    var nameLen = peerReader.ReadUInt32();
                                    bytesRead = await peerReader.LoadAsync(nameLen);
                                    if (bytesRead > 0)
                                    {
                                        var fileName = peerReader.ReadString(nameLen);

                                        bytesRead = await peerReader.LoadAsync(sizeof(uint));
                                        if (bytesRead > 0)
                                        {
                                            var imgLen = peerReader.ReadUInt32();
                                            bytesRead = await peerReader.LoadAsync(imgLen);
                                            if (bytesRead > 0)
                                            {
                                                var content = peerReader.ReadBuffer(bytesRead);
                                                StoreJpegFile(fileName, content);
                                                WriteStatusAsync(dispatcher, "Received JPEG File : " + fileName + " at " + DateTime.Now);
                                            }
                                            else
                                            {
                                                hasClosed = true;
                                            }
                                        }
                                        else
                                        {
                                            hasClosed = true;
                                        }
                                    }
                                    else
                                    {
                                        hasClosed = true;
                                    }
                                }
                                else
                                {
                                    hasClosed = true;
                                }
                                break;
                        }
                    }
                    else
                    {
                        hasClosed = true;
                    }
                }
                else
                {
                    hasClosed = true;
                }
            }
            catch (Exception ex)
            {
                currentEx = ex;
                hasClosed = true;
            }
            if (hasClosed)
            {
                Disconnect();
                if (currentEx != null)
                {
                    var dialog = new MessageDialog("Read Error - " + currentEx.Message);
                    await dialog.ShowAsync();
                    WriteStatusAsync(dispatcher, "Disconnected at " + DateTime.Now);
                }
            }
            else
            {
                StartReader(dispatcher);
            }
        }

 データ受信の基本は、DataReaderのLoadAsync()メソッドコールでデータ長を指定してロード、ReadXXX()※XXXは型名メソッドコールで実際に読み込みの順に行います。データ長、文字列、バイト列はぞれぞれ

  • ReadUInt32
  • ReadString
  • ReadBuffer

メソッドが対応します。受信中に相手とのコネクションが切れた場合、LoadAsyncの戻り値は0になります。また、DataReader、DataWriterのメソッドコールでは、通信の状況でExceptionが発生する場合があり、この状況が発生すると通信は継続できないので、受信状態をやめます。問題が発生していない場合には、最後の方でStartReader()をコールして更に相手からのデータの待ちに入ります。WinRT APIは非同期プログラミングに対応しているので、この一連の流れで、相手からのデータを順次受信していくことが可能です。

他PCとの接続から、StartReader()メソッドをコールする流れは、

            peerWriter = new DataWriter(streamSocket.OutputStream);
            peerReader = new DataReader(streamSocket.InputStream);
            StartReader(Window.Current.CoreWindow.Dispatcher);

です。※peerWriter、peerReaderは、それぞれクラスのメンバー変数として定義されているものとする
StartReader()メソッドコールにawaitをつけていない点に注意してください。awaitをつけないことにより、StartReader()メソッドの実行は、非同期に行われることになり、データ受信によるブロックを避けることができます。

Disconnectメソッドでは、peerWriterとpeerReaderに対し、Dispose()メソッドをコールして後始末してください。

WriteStatusAsync()は、UIの表示��報の更新などを行うことを想定しています。以下のようにUIを管理するディスパッチャーに処理を委譲します。

        private asyncvoid WriteStatusAsync(CoreDispatcher dispatcher, string msg)
        {
            await dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                () =>
                {
                    // XAML上のTextBoxなどへのアクセス
                });
        }

StartReader()メソッドの中で、WriteStatusAsync()メソッドをコールする際にもawaitをつけずに非同期実行しているところも実は重要なので、ご注意ください。


 

PlayToを使って、リモートでメディアを再生

$
0
0

Windows 8のWinRT APIが提供するUI部品には、MediaElementという部品があります。音ファイルや動画ファイル、写真ファイルを表示する部品です。

XAMLでメディアを再生するには、

    <MediaElementx:Name="mediaElem" Souce="ファイルのURI"/>

と書けば、簡単に再生可能です。この部品は、単にメディアファイルを再生するだけではなく、http://msdn.microsoft.com/ja-jp/library/windows/apps/windows.media.playto.aspxに書いてあるように、

「リモート再生を使用すると、ユーザーは自分のコンピューターのオーディオ、ビデオ、またはイメージを、簡単にホーム ネットワークのデバイスにストリーム転送できます。たとえば、アプリケーションでビデオを再生しているユーザーは、そのビデオを自分のテレビにストリームできるため、室内のすべてのユーザーがそのビデオを見ることができます。」

なんていう素敵な機能がついているんです。これを使わない手はありません。XAMLのページに<MediaElement../>タグを書いて、そのコードビハインドのC#コードのページのクラスに、

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            var prayToManager = PlayToManager.GetForCurrentView();
            prayToManager.SourceRequested += new TypedEventHandler<PlayToManager, PlayToSourceRequestedEventArgs>(prayToManager_SourceRequested);
            base.OnNavigatedTo(e);
        }

を追加します。OnNavigatedToメソッドは、このページにナビゲートされて表示されるときにコールされるメソッドです。PlayToManagerというクラスは、Windows.Media.PlayTo名前空間に属する、リモート再生にかかわるライブラリです。上のコードでは、カレントのビューに付随しているPlayToManagerインスタンスを取得して、リモート再生要求があった時にコールされるハンドラ、playToManager_SourceRequestedメソッドを登録しています。

このページが表示されている状態で、デバイスチャームからリモートディスプレイを指定すると、prayToManager_SourceRequestedメソッドがコールされます。このメソッドでやることの基本は、以下の通り。

        async void prayToManager_SourceRequested(PlayToManager sender, PlayToSourceRequestedEventArgs args)
        {
            awaitDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                var deferal = args.SourceRequest.GetDeferral();
                args.SourceRequest.SetSource(mediaElem.PlayToSource);
                deferal.Complete();
            });
        }

これで、要求があった時にMediaElementで表示されているメディアがリモート再生されるっていうすんぽうです。…あ、Playと書くべきところがPrayになっている…ま、Windows 8 ストアアプリの普及を願っている心が思わず出てしまったということでご勘弁。

この機能を使ったとてもシンプルなアプリを一個ストアに申請してみました。http://apps.microsoft.com/windows/app/00bc3a21-cd8b-427f-be1d-b7f792551327額縁プレーヤーというアプリです。

MediaElement自体は、動画再生時のPauseとか再生位置指定とかのUIが無いので、http://playerframework.codeplex.com/ から公開されている、Microsoft Player Frameworkを使っています。このフレームワークでは、MediaElementを拡張した、MediaPlayerっつうクラスが提供されているので、MediaElementの代わりにこのクラスを使います。XAML上で置き換えれば、この投稿で紹介したコードはそのまま使えるので、試してみてください。

Visual Studio 2012でOffice 2013の拡張アプリを作れるようになりました!!

$
0
0

私が書くのもなんなのですが、…ま、組込み系でもExcelをCASE Toolとして使う開発者も多いからいいですね。ということで、Visual Studio 2012向けに最近リリースされたMicrosoft Office DeveloperToolsを紹介します。

Visual Studio(有償版)では、ずいぶん昔から、ExcelやWord、PowerPoint、Visioに拡張機能を追加するToolsetが存在していました。2013年3月19日現在のVisual Studio 2012をインストールした状態では、Office 2010向けのOffice Toolsetしか入っていません。あれ、既に出ているOffice 2013向けはないの?と思った方も多いでしょう。大丈夫です。以下の手順に従って拡張機能をインストールしてください。

C:\Program Files\Microsoft\Web Platform InstallerのWebPlatformInstaller.exeを実行

 

"Microsoft Office Developer Tools"を検索

"Microsoft Office Developer Tools for Visual Studio 2012"を選択して”インストール”

関連するライブラリーやツールのインストール状態によって、途中で失敗する場合もありますが、その場合は再度インストールをトライしてください。Visual Studioのダイアログが開いているとインストールが進まなくなるので、Visual Studio 2012は終了しておいた方が良いでしょう。

インストールが完了したら、プロジェクトテンプレートには、

の様に、Office 2013向けのToolsetを使うプロジェクトテンプレートが追加されます。インストールしたPCにOffice 2010がインストールされていれば、Office 2010用のプロジェクトテンプレートもインストールされます。

 

Viewing all 167 articles
Browse latest View live


Latest Images