世界時計アプリ Wheel World Clock の Universal Windows Platform (以下UWP)版を公開しました。
Wheel World Clock
https://www.microsoft.com/store/apps/wheel-world-clock/9nblggh10zzn
今回の作業、UWP化の恩恵をフルに活用しよう!という訳では無く、この元々簡単な時計アプリをダシにして
アプリのUWP化・ビルド・ストアへの提出等の作業を一度全部通して試してみるのが目的です。
このため、UWPの売りであるところのAdaptiveなLayout変更やx:Bind等は全く使っていません。
Appとして破綻しない程度に動けばOK!くらいの簡単な実装です。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9Jy6Dym9mS0r3Lr_FSs1QgKHvtR2PbAxlcGoVfFa2NPtcCZfnBDJm7awPO4JLNKMtH3ifUSFF9Z_xQIC6ZugarIf0OjkHB82o4blL8svmMhn42bFRrIP8B7nI8w8fkUDQP0_gF2bJ_Vw/s400/WWC_UWP_Desktop.jpg) |
Win10 Desktop でWheel World Clock UWP が動いている様子 |
UWP対応でやったこと
Wheel World Clock(以下WWC)は元々「Win/WP8.1の」Universal アプリで、
- Windows 8.1用Project
- Windows Phone 8.1用Project、
- 共用のShared Project
から成るソリューションになっています。
今回、これに「Universal Windows」…UWP のProjectを追加し、3Project+Sharedのソリューションとする変更を行いました。
※今回は練習のため8.1 UniversalにUWPを追加する形にしていますが…
今後特にWin/WP8.1用をメンテする予定がないのなら、素直にUWPだけのソリューションにしたほうが話は早いと思います。
UWP Project の追加
追加時にはフォルダ作成先に気を付け、三つ仲良く並ぶように作成。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2IW7g9h48l_euJvqO79U5xMl58KouBTZ9tlD9ImV5pSLJomL3hkrZAH5FVCYjgCtSWG-GGO1eMo_8cFCbYgqnbAK8UeTUVTXYkA50zCudeLkAt44DsorKUid5N1iHsFt5LLHwM0coYVE/s320/WWC_UWP_Solution.PNG) |
Project三つ+Shared一つ |
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzyM1tDXCJpAOYs7qnYwgcSiKIw_9fnIdBDVfs9-G6ty1dZ-u04ICdhWm0qlvtiJ-8PpQsRWTSDz9YOI0GX0heMB0Kp2BEHtb1pcBGwHYkO-63UpeZva6v-fcf1QpyEihlLReRKO2MTEI/s320/WWC_UWP_Folder.PNG) |
フォルダはこんな感じに並びます
ソリューション .sln ファイルは一つ上のフォルダ |
8.1 Sharedは、各々のProjectの名前空間を共通にすることでSharedのソースを共通に参照する、という仕掛けになっています。
このため、UWP Projectをその名前空間に変更します。
- Main.xaml / cs
- PackageManifestのスタートアップを指定してるとこ
そして、参照にShared Projectを追加します。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1JI1dNWLTdwJOwjluZNFWmshVWOhMuHWTz5RU0uVJdrSiGkE64SPu1yGeCcP7V7RaZ6U0JWszdljVFtyBHo3FwCzDhVC7bZwU0D94sYzS2wPryQSs39yU6TjKyW4hP0L2fk54ltR1zuM/s320/WWC_UWP_Shared.PNG) |
Shared.projitem を参照に追加 |
最後に、App.xaml / cs を削除 (App.xaml / cs を共用している場合)。
ここで一発Appをビルドし、実行されAppのWindowが出てきたらソリューション・プロジェクトの枠組み作成はとりあえず成功です。
Project Unique な部分の変更
ここから先はApp Specificな部分が多いのですが、その中でもある程度アプリ共通な部分を挙げてみます。
備考…WWCの構成
WWCの構成を簡単に説明します(以降のUWP化作業理解の助けのため)
アプリが持っているページは二つ
- Main.xaml メイン。時計を表示するページ。
- Cities.xaml 表示するタイムゾーンをカスタマイズするページ。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipdq0fjulFLs7jwByKnUtqHrmwTR5PSahkK2eZOkOoJtcAS9Iw21HoVlzJfIqGpaCjplNgJHFaouJS5_keNYdCJL15dNvzgiWiAmrSSBenBT4aUguW0FIVWF5da7zTn9odTcUMr6IMbTo/s320/WWC_PSTFIX+%25282%2529.png) |
Win8.1用のCities ページ |
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-skPek_vxs7vSreiylFGaM7fuqIePTnMhGWbEqQ3-nN35f_F7d9zsJH_DRFh0VVLilgOD9oEorgI7r3r4xCX0F7qmJwdSvCkYFWBeaejlAYv9d-j4yb8x5L-fdv_GZQbJcZIvu82q6x0/s320/wp_ss_20150118_0004.png) |
WP8.1 用のCities ページ |
そして、ぐるぐる回る時計はユーザーコントロールとして作ってあります。
Win8.1/WP8.1 Universal では、Main・CitiesをそれぞれのProject用、ユーザーコントロールは共通として作っていました。
今回のUWPも、MainとCitiesのみ別持ち、時計は共通のユーザーコントロールをそのまま使うという方針です(このためコード変更があんまり無い…)
SuspensionManager, NavigationHelper等のテンプレート部分
このあたり、今回UWPはBlankで作ったため初期状態では何もありません。
そこで、Microsoft が Githubに上げているSample集から当該ファイルをパチっ(持ってきて)使います。
今回、名前空間だけ変更しました(そのままでも別にいいですが…使う人のUsingが変わるだけ)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhse0_gxTC8KMYCIjjOagwSRbpYlhRWMoCvBm67palZKDJteEir6PGxzrVWWhz02K0NvX8_gOVT2UxuJYVeVVyZBug4KHPt-uo1rngqksTeGnjIIdBdZ9bd1sz47Ef0SsM3xSiTeJoxHU0/s320/WWC_UWP_Common.PNG) |
Commonに置くファイル 最低限これだけあればなんとか |
一つ注意なのは、これらのSourceは8.1と異なりUWP用であるため、中でMobile DeviceFamilyのExtensionを参照しています。このため、参照にMobile Extensionを追加する必要があります。
App.xaml.cs の変更
WWCでは Application Insights を使っています。今回、UWP用を別集計としたいので…#ifdefで分け、UWP用のInstrumentation Keyを指定します。
Windowの最小サイズ変更・タイトルバーの色変更
UWPではAppの最小サイズを縦・横で指定できます。
指定はManifestでは無くコードで行います。
また、タイトルバーの色もここで変更します。OS標準の白は正直見づらいので。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEk940Nwo3aD0HZ0W7Ci2gPgKLZsvXVqKy3VEYomCV6vrBx9ckNnjVCbQYu-lenrOsU5kB3woKqJjeovIDoX_dWDs6r6G1MqXa2ugQMLM-VMB2MIBypqiwD8Cb4epN2uetfWlnHcQGRpc/s400/WWC_UWP_TitleBar.PNG) |
App.xaml.cs で指定している様子
App.xaml.cs はShared コードであるため、UWP用の部分はIFDEFで分けます。 |
Main.xaml の変更
WWCでは、Windows用に三点リーダのAppBar引きずり出しボタンを自作して使っていました。UWPでは同じ物がCommandBarに組み込まれているため、そちらを利用しました。
広告
困ったことに、UWP 用のMicrosoft Advertising SDK はまだリリースされていません。無いものは仕方ないので、今回UWP版には広告を出さないことに決め、関連コードをコメントアウトしました。
Cities.xamlの変更
WWCでは、
で、UIを作り分けていました。
今回のUWP版ではPC・電話両方で動くわけですが…Hubは電話では使いづらいため、電話用に作ったPivot版をそのまま持ってくることにしました。 PCで動かすと見た目は少し悪いです。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZnKRSfAyyjLM3wTd7Yb23afT1Org7OdCx6kvb_sTRgWr5wjtLT4uT9Ju-07GTWoxpDObPVAsnJ9QDYeCEWhR1ZpTYqvfLW53DJHe87yb9wAfBEcXDJuhCuukPRx9RVSgIjhR5_Qti2FI/s320/WWC_UWP_settings.PNG) |
UWP用のCities ページ
PC・電話ともにこれが表示されます
上のWP8.1用と構成が同じなのが見て分かります |
また、元の電話UIにはバックボタンをつけていませんでした。これは電話では常にバックボタンがOS(またはハードウェア)で用意されているため、アプリ側では(特に処理が無いのなら)何もしなくてもよかったためです。
今回はそうもいかないので…タイトルバーに表示するバックボタンを使うことにします。
これはよくできていて、
Window表示…タイトルバーにバックボタン表示
フルスクリーン表示…タスクバーにバックボタン表示
という切り替えをOSが勝手にやってくれます。ありがたい。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDEWaYwYdeqeM7wZZkw7V3h2JnotafW4-VBFNoz6Z3tc1aXBr5BQe-MFEI5HuJ30j9qTbasWEQ9CiI3HeTPbfbTEMFxvCTVRgKDcRasjJuM521V_aP9GGwxQ9nROdJHXOG5YfGOIOuP_c/s400/WWC_UWP_Backbutton2.PNG) |
バックボタンの追加
Cities.xaml.csのコンストラクタで行っています
|
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxMLYBWw7ikIdEa2XFVEnNxGbyoyKjgZLGa96xbd3gL_oQ5NPyQEpYXa6bqooGUzEBrIzV0jEwALeqTVUl5lechkoYeR6oCXAVgIGSl6MwrlODwFrQkZkabbZ2S78o1TyZ9s2pJhBZt6Q/s320/WWC_UWP_BackButtonUI.png) |
タイトルバーのバックボタン |
Win2D
WWCでは文字盤に貼り付ける画像の切り出しにWin2Dを使っているのですが、このライブラリがVS2015RTMのタイミングでWin8.1用とUWP用に分かれました。
このため、UWP版を使用するよう変更しました。
画像リソースの追加
これが一番面倒なんですが… UWP用にアイコン・タイル・スプラッシュ画面等の画像リソースを作成します。
UWPではベースのスケールが200になっているので、そのままではWin/WP8.1用の画像は使えないです。諦めて一個一個リサイズしましょう…
(.csprojでスケールを指定する方法も一応あるのですが、今回はUWP標準に揃えました)
また、UWPは電話・PC共通ですが…特に電話ではタイルを透明にすると見栄えが大変良いので、タイルはなるべく背景を透明で作ると良いです。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhd4Z01stSSO6s41j9CRIU5EPbxYrA8ybkrEwlHrua_KhGYHVxM1ALb03hQ-nPNZhyphenhyphenPuhacbFqVArrZIDL034XGoygGykUJsNJOy9Yj0I-Bl-WOtCE2xCnSKawOu6tY36PsNznmboLC38c/s320/WWC_UWP_Assets.PNG) |
UWP用画像リソース |
ストアへのアップロード用パッケージのビルド
本来なら引っかかる所では無いのですが…8月3日現在のWin10 SDKには問題があり、私のPackageはこれに引っかかってしまいました。
詳しくはMSDN Forumの当該スレッドを見て頂ければと(私も書いてます)。このスレの通り、更新版の.targets fileを使う事でBuildに成功しました。
RTM Known Issue: Release configuration fails to build on using Desktop and Mobile Extension SDKs in a Universal Windows app
https://social.msdn.microsoft.com/Forums/en-US/2887e169-348d-4d97-a359-aee413b5fa26/
この問題、鍵になっているのは.NET Native 用のFileです。
既定の設定では、UWP Projectは
- Debug Build .NET Native Off
- Release Build .NET Native On
になっています。
このためリリースビルドのアップロードパッケージ作成で問題が発覚した感じです。
私のようにリリース直前にエラー出て慌てるのもなんなので、開発中も「たまには」リリースビルドを行い様子を見るのをお勧めします。
私の経験では….NET Nativeに対応するためにコード変更が必要になった事は無いのですが、有るときは有るので(凝ったSerializerを自作してるとか)…その意味でもたまにリリースビルドを行い動作を確認するといいよ!とBuildでMSのエンジニアが言っていました。
なお….NET Native をOnにするとコンパイル・ビルドに偉く時間がかかります。私のポンコツマシン(Core2Duo 2GHz, Memory 4GB, SSD)だと、ARM/x86/x64 全部ビルドするのに17,8分。
ストアへのアップロード
ここはWebの言うとおりに進めることができ、特に引っかかる所は無かったです。
WWCは既にWin8.1とWP8.1用のパッケージがアップロード済みで、それに今回ビルドしたWin10 UWP パッケージが追加される形になります。
Win8.1/WP8.1用アプリが独立していた頃とは異なり、ストア上のエントリ…登録の扱いは一つ、その中に各OS用のパッケージが格納される感じです。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIDFDJHDJz7kObclWTRtGpoguXtWk4kFcOPaif8b_1qGIHmgE7yXkYvn2eXyCztyZh_U86zOc5RXg3NesmlzhK-AP1RCVqnpEoK4l8K4HZtbxpAKaTynHoKCFj6z6-0WtP2v6PCiIy5po/s400/WWC_UWP_Packages.PNG) |
Win10 / Win8.1 / WP8.1 それぞれのパッケージが並んでいる様子 |
ユーザーがストアにアクセスし「インストール」ボタンを押すと、システムに応じたパッケージのみがDLされます(Win10に無理くりWin8.1用を入れる、とかは無し)。
最後に…
VS2015RTM+Win10SDK、出たばかりという事もあり中々スリリングでして…私のポンコツマシンだと、Win10 をクリーンインストールした上にVSをインストールした環境でも頻繁にフリーズが発生し、若干使い物にならない感じ(マイルドな表現)です。特にスタートアッププロジェクトを変更すると100発100中で死ぬんですが。困った。
そんな中でも今回の作業や画像掲示板ブラウザ F10の開発を続けられているのは、Azure VM上に安定したWin10+VS2015の仮想環境を確保できているのが大変大きいです。
本来なら使用料が発生する所ですが、昨年 Microsoft Taiwan が主催したアプリコンテスト「MSCC」の参加賞として3年分の「AzureとVisualStudio Enterpriseをタダで使える権」を頂いたので無償で使えています。本当に、Microsoft Taiwan には感謝しか無いです。有難うございます。