酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

WindowsストアアプリとWindows Phoneアプリをひとつに統合できる「ユニバーサルWindowsアプリ」について

2014年4月、「BUILD 2014」で「Visual Studio 2013 Update 2」のRC公開と共に「ユニバーサルWindowsアプリ(universal Windows apps)」とWindows Phone 8.1が発表されました。 ユニバーサルWindowsアプリ(以下、ユニバーサルアプリ)とWindows Phone 8.1の登場によって、WindowsストアアプリとWindows Phone 8.1アプリのコードの共有について、もう一歩踏み込むこととなりました。

従来のWindows Phone 8.0では、Windowsと同様のWindows NTベースのカーネルを採用しており、一部のWinRT APIは使用することができました。共通のAPIがあることによって、WindowsストアアプリとWindows Phoneアプリ間で部分的にですがコードの共有化が可能でした。

ユニバーサルアプリでは、WindowsストアアプリとWindows Phoneアプリとを統合して、Windowsストア上で「ひとつのアプリ」として扱うことができるようになりました。

例えば、Windows用のアプリを購入すると、同一タイトルのWindows Phone用アプリを別途購入せずに使えたり、アプリ内で使用するデータやファイル、設定などのユーザーデータをローミングで共有したりと、ユーザーの視点では同じアプリがマルチプラットフォームで動いているように見えるようになりました。

ただ、実際には画面サイズが狭くデザインやデバイス的な表現が限定されるスマートフォンアプリと、それに比べると比較的表現が自由なWindows用アプリとでは、最適なUIはどうしても異なってしまうため、UIやロジックまで含めて同じアプリ(バイナリ)というわけにはいきません。同じデータソースを表示するにしても、下図のようにそれぞれのプラットフォームでの最適な表現は異なります。

f:id:ch3cooh393:20150302164534p:plain

ユニバーサルアプリでは、基本的にページなどのWindowsとWindows Phoneのプラットフォーム固有の部分は別々のプロジェクトを作成し、それぞれのアプリプロジェクトからはプラットフォームに依存しないコントロールやロジックを共有したプロジェクトを使う形になります。

ユニバーサルアプリにおけるコードの共有

ポータブルクラスライブラリ(Portable Class Library)」にて、マルチプラットフォーム対応のアプリでのソースコードの共有の方法として、「[リンクとして追加]によるコードの共有」や「ポータルクラスライブラリのプロジェクト共有」について紹介をしました。

ここでは、ユニバーサルアプリでのソースコードの共有について、プロジェクトの生成からソリューションの構成、そしてシミュレータでの実行結果を紹介します。

まずは、Visual Studio 2013 Update2以降で、[新しいプロジェクトウィザード]を使ってユニバーサルWindowsアプリのプロジェクトを作成してみましょう。

テンプレートツリーから[テンプレート]、[Visual C#]、[ストアアプリ]の順に選択します。テンプレートの一覧が表示されますので、「ハブ アプリケーション (ユニバーサル アプリ)」を選択します。

f:id:ch3cooh393:20150302164611p:plain

[OKボタン]をクリックすると、下図のソリューションの構成でプロジェクトが生成されます。全部で3つのプロジェクトが確認できます。

f:id:ch3cooh393:20150302164636p:plain

「UniversalApp」という名前のアプリのプロジェクトが、それぞれWindows 8.1用とWindows Phone 8.1用のプロジェクトが生成されています。それぞれのプロジェクトにはページを定義したxamlである「HubPage.xaml」「ItemPage.xaml」「SectionPage.xaml」があり、UIがプラットフォームによって異なっていることが理解できます。

それらのプロジェクトの下にある「UniversalApp.Sharedプロジェクト」がユニバーサルアプリのキモと言える「共有プロジェクト(Shared Project)」です。DataModelフォルダには「SampleDataSource.cs」があり、これがアプリで表示させるデータソースです。Windows 8.1用アプリとWindows Phone 8.1用アプリは、共有プロジェクトにある同じデータソースクラスにアクセスして、データをUIへ表示させています。

下図のようにWindowsストアアプリとWindows Phoneアプリのソースコードのうち、それぞれのプラットフォーム固有の処理(例えばWindows.Phone.UI.Input名前空間のハードウェアキー押下イベントなど)やスマートフォンとタブレットPCとの用途の違いで見せ方が異なるXAMLなどを除いて共有プロジェクトでコードを共有化することができるようになりました。

f:id:ch3cooh393:20140422170645j:plain

ポータルクラスライブラリでは扱えなかったWindowsランタイムAPIやUIなどの共有化が可能となっているのが分かります。

どうしてこのようなことが可能になったかというと、前述した通りWindows Phone 8からWindows Phone OSのカーネルをWindows CEベースのものからWindows NTベースのものに置き換わり、それに伴って.NETエンジンも「.NET Compact Framework」から「CoreCLR」に置き換わったからです。

CoreCLRは、Windows 8/Windows 8.1で使われている.NETエンジンと同じものです。そのため、Windows Phoneアプリからも(Windowsストアアプリで使うことができる)Windowsランタイムのサブセットを使用することができるようになりました。Windows Phone 8.1でさらに使用できるAPIが増え、WindowsランタイムAPIのほとんどが網羅されています。

さて、これらのアプリをデバッグ実行してみましょう。まずはユニバーサルWindowsアプリをWindowsストアアプリとして実行します。デフォルトのスタートアッププロジェクト設定がWindowsストアアプリになっているので、Visual Studioのツールバーから[デバッグ]、[デバッグ開始]の順に選択してアプリを実行します。

f:id:ch3cooh393:20150302164738p:plain

次にWindows PhoneアプリとしてユニバーサルWindowsアプリを実行してみましょう。ツールバーにあるターゲット設定の下矢印になっている部分をクリックして、「スタートアップ プロジェクト」、「UniversalApp.WindowsPhone (Windows Phone 8.1)」を選択します。

f:id:ch3cooh393:20150302164802p:plain

スタートアッププロジェクトがWindows Phoneアプリ側に切り替わりますので、先ほどと同じ要領でVisual Studioのツールバーから[デバッグ]、[デバッグ開始]の順に選択するかまたはF5キーを押下してアプリを実行すると、Windows Phone 8.1エミュレータが起動します。

f:id:ch3cooh393:20150302164826p:plain

このようにユニバーサルアプリでは共有プロジェクトを使うことで、WindowsランタイムAPIを使って記述されたロジックを再利用して、WindowsストアアプリとWindows Phoneアプリの開発を効率化することができるようになりました。