2014年1月3日金曜日

Microsoft Application Insights を ストアアプリで使う (その1)

※2016年4月追記 StoreApp / UWP App用のApplication Insights 新規受け付けは2016年4月15日で終了しています。既存ユーザーはHockeyAppへ移行するようにというアナウンスが出ています。

Transitioning Mobile Apps from Application Insights to HockeyApp
https://azure.microsoft.com/ja-jp/blog/transitioning-mobile-apps-from-application-insights-to-hockeyapp/

※2015年2月追記 Application Insights は現在Azure ベースのサービスに移行しており、本記事でお話しているVisual Studio Online 版は提供が終了するようです。このため本記事は現在のApplication Insights にはあまり当てはまるところがありません。
Azure版については以下の記事も御参照下さい。

うまく行かない人用の Application Insights ガイド(2015/02)
http://ddlgjp.blogspot.jp/2015/02/application-insights.html


------


今回、ストアアプリ WiFiSD8 に Microsoft Application Insights を組み込む機会がありました。未だ試用版ではありますが、アプリの使用状況を把握するにはかなり有用なサービスであるなぁ、という印象です。簡単ですが紹介・使い方記事を書いてみました。



概要

Application Insights とは

Application Insights (以下「AI」と略」) は、Webサイト・Azure・Windows ストアアプリ・Windows Phone アプリ・.NET アプリ の使用状況を収集・分析するためのMicrosoft のサービスです。Visual Studio Online の中で提供されています。

昨年10月、Visual Studio Online と同時にアナウンスされましたが、その時はAzure等のWebサービス向けでした。昨年12月に ストアアプリ版のPreliminary SDKがリリースされました(このため、全体にどちらかというとサーバー向けのデザインというか・・・アプリから見ると??な所、サーバーのみで使える機能、が多いです)。

AI Dashboard の例 (MSDNより借用)


AI SDK をストアアプリに組み込むだけで、基本的な情報…

  • 一日あたりのユニークユーザー数・新規ユーザー数
  • ユーザー辺りのセッション(アプリケーションの起動・終了)数
  • アプリのバージョン割合
  • ユーザーの使用環境(モニタサイズ、OSバージョン等)

は Coding 無しで取得されます。特にユニークユーザー数は Windows Store のDashboard では判らない情報で、PubCenter等の広告の運用や、アプリ販売・アプリ内販売の値段決定等を考える際には大変に有用な情報だろうと思われます(AdDuplexでも取得できますが)。

それ以上の細かい情報… Appの各ページが何回表示されたか、ある処理に掛かった時間、数値・文字列等…を取得するには、簡単なCode をアプリ内に「イベント」として埋め込みます。

例を挙げると、実際のアプリ内のページ遷移を集計することで、ユーザーが実際にどうやってアプリを使っているかを追跡する事ができます。あるアクションについて二つのパス…アプリ上に常に表示するボタンと、アプリ バー内に置いたボタン…がある場合、

  • 実際どれくらいの割合で二つのパスが使われているのか?
  • 片方のパスがほぼ0だったらそれは要らないのでは?
  • 意図せざる使われ方をしていたら、何かデザイン変更・チュートリアル追加等が必要なのでは?

等、UI改善に役立てる事が出来るでしょう。

他にも、以下のような様々な使い方があるのではと思います。
  • GridView上に表示するアイテムの平均・最大最少を見て、データの見せ方を考える(少なければリッチな見せ方に重点を置く、多ければVirtualization が効くようにする、グルーピング機能を検討する等)
  • あるアクションに掛かる時間の平均・最大最少を取得する

一方、使用者が特定できない形とはいえ、ユーザー情報を収集するサービスですので、使用には一定の注意が必要です。興味本位でデータを集める、無断で公開する等でユーザーからの信用を失っては元も子もありません。Baidu での一連のFrameUp は記憶に新しい所ですし。


Availability

現在(2014年1月)の所、AIは Preview Release であり、無料で使用することができます。Visual Studio Online 内でTesterを募集しており、そこのフォームにMail Addressを入力してしばらくするとActivation Code が送られてきます。

Visual Studio Online のトップページに案内が表示されている(はず)
Activation Code を入力してログインすると、AI で使う アプリケーションのGUID を取得することができます。この ID を アプリケーション起動時にパラメータとして AI SDKに渡すことで、一意なデータ集計が行われます。
初期化コードは以下のような感じです(App.xaml.cs)。

        protected override async void OnLaunched(LaunchActivatedEventArgs args)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            Microsoft.ApplicationInsights.Telemetry.WindowsStore.ClientAnalyticsSession.Default.Start("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");            

            if (rootFrame == null)
            {
            ... 



アプリへの埋め込み


実際の作業は、MSDNのチュートリアル(とても判り易いです)を参照しながら進めていく事になりますが、自分が引っ掛かった2,3点について少し説明します。

Analyze Windows Store App Usage
http://msdn.microsoft.com/en-us/library/dn509554.aspx


AI SDK の インストール

Tutorial に従って NuGet からInstallするのですが、「リリース前のパッケージを含める」を選択する必要があります(しないと検索しても見つかりません)。

ソリューション エクスプローラ→右クリック→NuGet パッケージの管理

C# - Any CPU でビルドしているアプリに AI を導入する場合


AI SDKは x86 / x64 / ARM, CPU 別のComponentとして提供されています。このため、ストアアプリをC# - Any CPU でビルド・パッケージングしている場合、Native CPU別のパッケージに変更する必要があります。

ビルドについては、Visual Studio の構成マネージャーで x86, x64, ARM をそれぞれ設定します。

VSのメニュー ビルド → 構成マネージャ
実際の開発中は x64 / ARM だとXAML デザイナが動かない(x64マシン上でも)ため、多くは x86で回すことになります。Debug Targetに合わせて適宜変更します。

なお、Any CPU から CPU Native に変更した場合、既にAny CPU のPackageがインストールされているシステムに対して Visual Studio から配置を行うと、配置がエラーになる・配置エラー出ないけれども実際動かすとSplash Screenで止まる、等が起こる場合があります。

この場合、Any CPU でBuild したパッケージを一度ターゲット マシンからアンインストールし、その後でVisual Studio から配置を行うことで正常にDebugできます。

なお、Visual Studio からではなく、ストアからアプリをインストール・更新する場合(エンドユーザーの場合)は特に問題ありません。例えばRelease 1 がAny CPU Package、Release 2 がCPU Native の Package だった場合、アプリの更新はRelease 1 → Release 2 で問題無く行われ、アンインストールが必要、アプリ情報が消える、等という事はありません。

パッケージングについては、パッケージ作成の際にNeutral を外し、各CPU のチェックを入れます。
作成が完了すると.appxupload ファイルがCPU毎に3つ作成されるので、それら3つをDashboardにUploadします。
※ Package 3つになったとしても、共通のAppIdを持つのでストア上では一個のアプリになります。

また、言語別のリソースを持つ場合、VS2013の既定のバンドル設定『必要に応じて』では複数のCPUパッケージ+言語リソースは一個のバンドル パッケージにまとめられます。この辺りはお好みでどうぞ。上で述べたように、ユーザーから見ると特に変わるところはありません。


VSのメニュー ストア→アプリ パッケージの作成 



...長くなってしまったので、アプリ内へのイベントの埋め込み、プライバシー等については章を分けてまた書きたいと思います。




2014年1月2日木曜日

WiFiSD8 Release 3

ストアアプリ版 FlashAir Client WiFiSD8 Release 3 を公開しました。Windows ストア からダウンロードできます。
既にインストール済みの場合、順次自動的に更新されます。

Click で ダウンロード
インストール・更新が成功した場合、設定→アクセス許可 に表示されるバージョン が「1.1.0.20」になります。
バージョン表示 設定チャーム→アクセス許可 で表示されます


変更点

2014年に撮影した写真が「2015年」にグループ分けされてしまう問題の修正

年が明けて初詣の写真を転送していて気が付きました。大変お恥ずかしい…
なおRelease 2 でも、写真そのもののExif、日付等には影響ありません。

一括転送で.jpgと同じ名前のファイルも転送するオプションの追加


一括転送において、画像ファイル名と同じ名前・別の拡張子のファイルがある場合そのファイルも同時に転送するオプションを追加しました。設定チャーム→WiFiSD8 設定から設定できます。
実質、RAW ファイル転送用です。RAW ファイルの拡張子はカメラ・メーカーにより異なるため、このような実装になっています。

その他細かい修正

・グループ表示画面から「更新」(FlashAirからのファイルリスト再読み込み)が出来るようになりました。

2014年1月1日水曜日

あけましておめでとうございます


あけましておめでとうございます。

昨年は futa8 と WiFiSD8、アプリ二つを公開する事ができました。
お使い頂いている方、ありがとうございます。

これまで Windows Desktop App 開発の仕事は長かったのですが、自前で一からデザインしたアプリをストアに載せるというのは初めての経験でした。足りない部分多くはありますが、自分が良いと思うものを両手で実装していくのは大変に楽しいものでした。
今年も、なんとか良い物を形にしていきたいと考えています。
宜しくお願い致します。

なお WiFiSD8、不具合等を修正したRelease 2 を既にストアに提出済みなのですが…未だ審査が始まっていないという困った状況です。
ご迷惑をお掛けしています。
1/1朝 審査通過しました!Windows ストアからDLできます!

写真は昨年10月、東京拘置所一般公開での一枚です。

2013年12月30日月曜日

スタート画面の上品なタイル グラデーションを真似する試み

以前から気になっていた事なのですが... Windows 8 のスタート画面上のタイル、微妙なグラデーションと細い枠線が使われていて、例えば単にSolidColorBrushでGridViewのタイルをベタ描くよりもずっと上品でオサレな感じだなぁと感心していました。

このタイル一つ一つのグラデーションが上品で綺麗ですよね!ね?という話なんですが
同意してもらえるか一抹の不安を抱えつつ記事を書いています


年末年始で時間もあることですし、どういうロジックでこの上品な描画を行っているか確認してみようぜ!そして出来れば真似してみよう!という企画です。

アプリの場合、ソリューションの Package.appxmanifest でアプリケーション タイルの背景色を指定します。
しかし、この色がそのままFlatに描画されている訳ではないです。

下の画像がタイルサイズ「小」での実際の描画を拡大した様子なのですが、判ります?

・1px のボーダーが設定されている
・ボーダー・タイル内部 共、色は左辺から右辺へのGradient Brushになっている



例えば WiFiSD8 を例にとると、Appxmanifestで設定しているタイル色は#759AC4 なのですが、実際の描画はこの色で塗りつぶされている訳では無く、以下の様なGradient 付きで描画されています。


場所左辺右辺
サイズ大(310x310) タイル内部 759AC491B2D1
サイズ大(310x310) ボーダー 83A4CA9CBAD6
サイズワイド(310x150) タイル内部 759AC491B2D1
サイズワイド(310x150) ボーダー 83A4CA9CBAD6
サイズ中(150x150) タイル内部 759AC491B2D1
サイズ中(150x150) ボーダー 83A4CA9CBAD6
サイズ小(70x70) タイル内部 759AC490B2D1
サイズ小(70x70) ボーダー 83A4CA9CBAD6

つまり元の#759AC4 からタイル内右辺の#91B2D1(サイズ小の場合は#90B2D1), ボーダー(枠線)左辺の#83A4CA と右辺#9CBAD6, を何らかの方法で計算しているという事になります。

他アプリのタイルのデータも取ってみます。

場所左辺右辺
ストア タイル内部 1A961A1AAF1A
ストア ボーダー 83A4CA9CBAD6
IE タイル内部 2672EC2E8DEF
IE ボーダー 3C80EE4399F1
ミュージック タイル内部 D24726DC572E
ミュージック ボーダー D75A3CE06843
カメラ タイル内部 95008CAE00A7
カメラ ボーダー A01A98B61AB0

GreenとRed・Blueの増分差を見ると単にRGB値に定数掛け算している訳では無さそうなので、Windows的にお馴染みのHSL(HSVでは無く)に変換してみると

Excelとか持ち出して完全に見失っている様子


………うううーn……HSL に変換することでRGB 値から独立した変換係数的なのが出てくるかと思ったんですが、何か別の要素があるみたいです。又はHSL ではなくHSV でやっているのかもしれない。
とは言っても大体の傾向は判ります。左辺の値に「Saturation 1.01 / Lightness 1.10」 程度を掛けてあげると右辺の値になると。また、タイルのベースカラーからBorderへの変換は「 Saturation 0.9 / Lightness 1.10」あたりで。若干無理がありますが。

という事で、こういう掛け算をしてタイル・ボーダーのGradient Brushを作るとスタート画面っぽい上品なグラデーションが得られる、はず、です。やってみましょう。

(余談ですが、この記事30分くらいでちゃちゃっと書くつもりだったんですが、この時点でもう数時間経っている…RGB2HSL変換コードとか書いちゃうし何かもう見失っている 僕がマネージャーなら止めさせるレベル)

伝わらないかなぁ…


おおおお!!!!スタート画面のタイルっぽい!!かなり良い感じなのではないかと!僕は興奮しているのですが!
…でもなー…やっぱり、そもそものスタート画面のグラデーションの美しさが共有できていないとこの興奮も伝わらないのでは無いかという不安が消えません。

最後に

ストアアプリ、というかMetro Design Initiative では「Chrome排除!!」(※1)が鉄の掟、マントラな訳ですが…その割にはスタート画面で微妙にChromeってるのがずっと気になっていたのでした。人はマントラだけでは生きていけないのか。でもこれくらいなら上品で良いなと思います。

※1)Google Chrome の事では無いです。ウィンドウにドロップシャドウ落とす、XPのLunaみたいにつやつやさせる、左上からライトが当たっている前提でUI部品に変化つけたり、的な描画上の装飾(クロム)を排除しようぜ!という。Authentically Digital, 俺のカラダの筋肉はどれをとっても機械だぜ!(意訳)と並ぶ、Metro Designの柱です。



2013年12月29日日曜日

Segoe UI Symbol を手入力するには


Windows 8 でのUI 用フォントである所のSegoe UI Symbol、ストアアプリを作るには超便利で、futa8・WiFiSD8 共アイコンはほぼ全部これで間に合っています(futa8の塩辛アイコンは別)。

が、たまに…Segoe UI Symbol に何か書き足したい、少し弄りたい時があります。そういうときは Paint.netのようなペイントソフトに文字を入力し、編集して.PNGにしてアプリ内に持つのですが…その文字入力方法を毎回忘れては探しまた忘れ、を繰り返しているので…忘れた時用に記録しておきます。

2013年12月28日土曜日

WiFiSD8 Release 2

ストアアプリ版 FlashAir Client WiFiSD8 Release 2 を公開しました。Windows ストア からダウンロードできます。
既にインストール済みの場合、順次自動的に更新されます。

Click で ダウンロード
インストール・更新が成功した場合、設定→アクセス許可 に表示されるバージョン が「1.1.0.15」になります。

バージョン表示 設定チャーム→アクセス許可 で表示されます


変更点

一括ダウンロードの動作変更

動作がどう変わるのか

Release 1 では、WiFiSD8 が中断している間もダウンロードが継続していました。
Release 2 では、WiFiSD8 が中断している間、ダウンロードも中断します。

「WiFiSD8 の中断」とは?

Windows8 ではアプリが他のアプリの後ろに隠れると、数秒でアプリはOSに「中断」されます。
中断している間、アプリは一時停止している状態になります。ダウンロードも停止します。
アプリを前面に出して表示すると、アプリは再開し、ダウンロードも再開します。

「ダウンロードの中断」を避けるには?

一括ダウンロードの間、アプリを表示し続けることで中断を避けることができます。
一括ダウンロード中に他のアプリを使用したい場合、画面分割でWiFiSD8 を画面脇に表示する事で中断を避けることができます。

WiFiSD8 を画面左に寄せて表示している様子

Release 1 のほうが便利なのでは?何故変更を?

FlashAir Class 10 タイプ(W-02)用に「インターネット同時接続機能」対応ファームウェアが2013年11月にリリースされました。モバイルルータ等をお持ちの場合、外出中でも FlashAirに接続したままインターネット接続が可能となる画期的な機能です。

ところが、この新ファームウェアで追加された機能の一つ「リダイレクト」をOnにしていると、OSが「このシステムはインターネットから切断されている」と判断する場合が有ることが判りました(しない場合もあります)。
OSがこう判断した場合、Release 1 で使っていた「アプリ中断中もダウンロードを行う」機能 「Background Transfer」 は使えず、ダウンロードができなくなってしまうのです。
このため、WiFiSD8 Release 2 では 「Background Transfer」を使わず、一般的なAPI 「HttpClient」 で一括ダウンロードを行うよう変更しました。

WiFiSD8 側でリダイレクトモードのOn/Offを検知して情報を表示する、というデザインも検討したのですが、基本的に外出先で使う WiFiSD8 上で「リダイレクトをOffにして下さい」と表示したとしても、FlashAir のリダイレクトOn/Off 切り替えは FlashAir カードをSDカードスロットに挿入し、設定変更ツールを使う必要があります。大抵の場合、外出先でこの設定を変更することは出来ません。

また、新ファームウェアでは既定ではリダイレクトがOnとなっています。既定値の設定変更を前提としたアプリのデザインは無理があると判断し、今回の動作変更となりました。
ご理解頂ければと思います。


画像の全画面表示でのダウンロード・切り替えの改善、UIの変更


画像の全画面表示 モデルは友人のJ君です(掲載許可を貰いました)
全画面表示中の素早い画像切り替えでダウンロードが停止する場合がある不具合を修正しました。
また、ダウンロードキャンセルボタンを追加し、ボタン配置を見直しました。


Microsoft Application Insights サービス の追加

アプリの使用状況を取得するサービスです。アプリの起動回数、アプリ内の各ページの表示回数等が個人を特定出来ない形で送信されます。
既定ではオンになっています。
送信を停止するには、設定チャーム→WiFiSD8 設定→「Microsoft Application Insights の使用」をオフにして下さい。

Application Insights の設定

2013年12月25日水曜日

BackgroundTransfer を諦めた技術的背景 (その1)


今回、ストアアプリ WiFiSD8 で、所謂ダウンローダ…IriaやIrvineのような、複数アイテムを順次ダウンロードする機能…を実現しようとしました。

が、結果的には
「ストアアプリ特有のApplication Lifecycle Management 環境下ではBackground Transfer機能をもってしても中断・終了への対応は困難であり、ユーザーにアプリを前面に表示し続けてもらわない限り、複数アイテムの順次DLは難しい」
という事になってしまいました。

以下はこの結論に至るまでの逡巡の記録です。
こうすれば出来たのでは、というツッコミは大歓迎です。是非真似させてください。

StoreApp の Application LifeCycle Management について


ストアアプリの終了・中断は基本的にOSにより管理されます。これをApplication Lifecycle Management, ALM と呼びます。
ALM下では、アプリは3つの状態で管理されます。

動作(Running) アプリが前面に表示されている状態。ユーザーと対話し、普通に動作している状態です。

中断(Suspend) アプリが背面に移動すると、OSはアプリを中断します(アプリに拒否権は無い)。アプリが前面に表示されるとすぐに動作状態に復帰します。

終了(Terminated) システムのメモリがきつくなってくる等した場合、OSはアプリを終了します(アプリ側に拒否権は無い)。

アプリが背面に移動すると数秒で中断されます。また、アプリを複数同時起動していると、アプリはそこそこ頻繁に終了されます。

Desktop Appと大きく異なる点として、
  • Appを(いつでも)中断・終了する権利をOSが持っていること
  • Suspend状態があり、極めて頻繁にSuspend状態に入れられる事 またそこそこ頻繁に終了されること
 が挙げられます。

前者により、ストアアプリは何時OSに叩き殺されても構わないようにデータをマメに保存し、後者により、長い時間のかかるタスクは結構困る、という特徴(弱点)を持っています。
反面、Desktopのように長い時間使っているとプロセスがやたら増えてなんとなく不調、DiskやNetworkのような資源をアプリが使い放題、的な状況は起きにくい、という事でもあります。
 

BackgroundTransfer


さて、今回の…いわゆるダウンローダ、複数アイテムを一括で順次ダウンロードするアプリの場合、普通にHttp Clientを使うとアプリ中断でダウンロードも中断してしまうので困ったことになります。

このため、Win8/8.1では「BackgroundTransfer」という機能がOSに用意されています。
これは、OSに「このURLからファイルをDLして下さい」と頼むと、OSがダウンロードを行ってくれる、という機能です。ダウンロードの主体はOSであるため、アプリが中断している間も継続します。

…ですがこの機能、二つ問題があります。

  1. 複数アイテムのDLが使いにくい
  2. アプリが終了されるとバッチDLが終了してしまう

まず「1 複数アイテムのDLが使いにくい」 について説明します。

この機能、APIの設計やサンプルを見るに、大きな1つのファイルをDLするためにデザインされている機能で、複数アイテムを一括でDLすることは(あまり)考えられていないのかな?という気がします(APIが用意されてはいるが、事実上動作として意味が無い)。

BackgroundTransfer が想定しているフローは、

  1. OSにDLアイテムを1個登録
  2. OSがDLを終え、アプリに通知
  3. アプリは次のDLアイテムをOSに登録
であるようです。
ですがこれはバッチダウンローダとしてはNGです。アプリが中断している間に2. に至った場合、次のアイテムを登録する事ができず、バッチプロセスが中断してしまいます。

このため、WiFiSD8 Release 1 では、(多分)想定外の使い方をしていました。

  1. OSにDLアイテムを一気に全部登録
  2. OSはひたすらDL

(想定外と言うのは…本来アイテム登録は await RunAsyncで行い、DLが終了したらawaitから返ってくる、のですが…Release1ではこのCallをasync voidのMethodに押し込み、Callしたら後は知らんぷりでぶん投げるという。酷い。でも、これでもDLの進捗・終了はCallbackで取得可能です。)

この場合、アプリが中断されてもOSは次から次へとDLを繰り返します。
ですがSideEffectがありまして…1の全部登録に結構時間が掛かります。100アイテム登録に一分くらい掛かってしまう。AsyncAwaitのお蔭でアプリのUIが固まる事こそ無いものの、1分はかなりの数のDLが済ませられる時間であり、どうしたものか…という所でした。
 
ですが(この文章ですがだらけですが!)、この想定外の使用をもってしても、
「2 アプリが終了されるとバッチDLが終了してしまう」
これは克服できません。
 正確には、1アイテムのDLはアプリが終了しても継続します。
が、次のアイテムのDLが始まらず、バッチ処理が止まってしまうのです。

ここまでの話をまとめると、

・BackgroundTransfer を使う事で、(開始に時間は掛かるが)アプリ中断でも終了しない一括ダウンロードを実現可能。ただしアプリ終了に対しては無力。

となります。WiFiSD8 Release 1はこの方法を取っていました。
アプリ中断に対しては大変有効な方法なのですが、困るのは…アプリが中断されるか終了されるか、ユーザーから見ると全く予測ができない所です(開発者でも無理ですが)。
そして、アプリ終了をユーザーが防ぐ唯一の方法は、

「アプリを背面に持っていかず、前面に表示し続ける」

これだけです。
・・・あれ?と。ここまで読んで頂いた忍耐深くまた賢明な貴方様なら、議論が循環している事にお気付きかと思います。

「前面に表示し続けるのがアリなのなら、そもそもBackgroundTransfer 使わなくても良くね?HttpClient 使っても同じじゃん!!」

という。
そういう矛盾をWiFiSD8 Release 1 は孕んでいたのでした。
矛盾はありますが、それでも機能を実装することで中断に対応する事が出来、損はしていないはずでした。

ですが、この状況は全く別の要因で大きく変わり、結果的にはBackgroundTransferを使わないRelease 2を作る事になるのでした。
長すぎなので章を分けます。
待て次号。

※ 今回、Background Taskについては15分にCPUTime 2秒ではDLには使えないだろうということで上の考察には入れていません。