Windows Phone

Windows Phone 向けにメディア アプリを作成する

Mark Hopkins

 

Windows Phone は、メディアの利用者にとってはすばらしいプラットフォームです。音楽やお気に入りのポッドキャストといったリスニング素材は、組み込みのメディア プレーヤーと Windows Phone Marketplace を利用して探すことができます。ジムでのトレーニング中、車やバスでの移動中だけでなく、身支度しているときでも、見つけたリスニング素材を視聴しています。これまで知らなかった素材を見つけるのに役立つメディア アプリが大好きです。たとえば、組み込みの Smart DJ 機能をはじめ、さまざまなストリーミング音楽アプリを使って、たくさんの新しい音楽を見つけています。YouTube や Vimeo から配信されるビデオ コンテンツにアクセスできるアプリもあります。

Windows Phone 向けにメディア アプリを作成することを考えている方は、いくつか準備を整えて、OS と適切に統合する必要があります。具体的には、アプリを Music + Videos ハブに登録して、このハブに表示されるようにします。

Music + Videos ハブに統合する

"ハブ" は、ユーザーが簡単にコンテンツを見つけられるように用意されている場所です。Music + Videos ハブは、Windows Phone ベースのデバイス上に存在するメディアを集めた場所です。作成したコンテンツをこのハブに置く目的はコンテンツを表示するためですが、それだけではなく、作成したコンテンツに最も関連性の高いメディアに簡単にアクセスできるからです。Windows Phone チームの調査によると、ユーザーが最も行いたいことは、以下のことだとわかりました。

  1. 以前再生したコンテンツをもう一度再生する
  2. 最も頻繁に再生するコンテンツに移動する
  3. 携帯電話に最近追加したコンテンツを探す

Music + Videos ハブは、この 3 つの重要なカテゴリーにコンテンツを振り分け、メディア アプリとローカル メディア ライブラリを 1 つのエクスペリエンスにまとめます。図 1 に、Windows Phone の Music + Videos ハブのパノラマ ビュー全体を示しています。

The Music + Videos Hub on Windows Phone
図 1 Windows Phone の Music + Videos ハブ

Music + Videos ハブはエンド ユーザーにとってすばらしいだけでなく、アプリにも多くの価値を与えます。事前にユーザーがカスタマイズしなくても、コンテンツが簡単に見つかります。音楽コンテンツやビデオ コンテンツの再生機能を提供するアプリは、Music + Videos ハブに統合すべきです。これを行うかどうかによって、適切な Window Phone エクスペリエンスを提供できるかどうかが決まります。

音楽とビデオのエクスペリエンスでアプリが利用できる主な統合ポイントは次の 4 つです。

  1. [プレイビュー] タイルを設定する。
  2. [新着] および [履歴] の一覧にアイテムを追加する。
  3. アプリが [新着] アイテムまたは [履歴] アイテムから起動されたかどうかを特定する。
  4. アプリ一覧に統合する。

[プレイビュー] タイルを設定する

このタイルは、Music + Videos ハブで最も目立つ場所で、現在一時停止中のコンテンツや最後に再生されたコンテンツを比較的大きい画像で表示します。このタイルをタップすると、表示されているコンテンツの再生が再開または開始されます。この画像を設定することで、コンテンツが広まり、アプリの再生エクスペリエンスに新たなエントリ ポイントが生み出されます。以下のコード スニペットに示すように、MediaHistory.Instance.NowPlaying プロパティを設定することで、[プレイビュー] のアイテムを更新します (ここでは、C# を使用しています)。

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();
// <hubTileImageStream> must be a valid ImageStream.
mediaHistoryItem.ImageStream = <hubTileImageStream>;
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "NowPlaying";
mediaHistoryItem.PlayerContext.Add("keyString", "Song Name");
MediaHistory.Instance.NowPlaying = mediaHistoryItem;

[履歴] にアイテムを追加する

MediaHistory.Instance.WriteRecentPlay メソッドを呼び出すことにより、携帯電話で最近再生したコンテンツを [履歴] タイルに表示できます。[プレイビュー] タイルと同じように、[履歴] タイルにも画像が表示されます。これをタップして、画像に含まれているコンテンツの再生を開始できます。[履歴] 一覧を更新する方法を次に示します。

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();
// <hubTileImageStream> must be a valid ImageStream.
mediaHistoryItem.ImageStream = <hubTileImageStream>;
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "RecentPlay";
mediaHistoryItem.PlayerContext.Add("keyString", "Song Name");
MediaHistory.Instance.WriteRecentPlay(mediaHistoryItem);

[新着] にアイテムを追加する

[新着] タイルは [履歴] タイルと同じように機能しますが、携帯電話に最近追加されたコンテンツを表示します。たとえば、[新着] タイルは、携帯電話にダウンロードされたばかりの音楽ファイルを表示します。ただし、[新着] タイルは、新たに作成したラジオ局やプレイリストなどにも使用できます。ここでもタイルにタッチして再生を開始します。以下のコードは、[新着] 一覧を更新する方法を示します。

MediaHistoryItem mediaHistoryItem = new MediaHistoryItem();
// <hubTileImageStream> must be a valid ImageStream.
mediaHistoryItem.ImageStream = <hubTileImageStream>;
mediaHistoryItem.Source = "";
mediaHistoryItem.Title = "MediaHistoryNew";
mediaHistoryItem.PlayerContext.Add("keyString", "Song Name");
MediaHistory.Instance.WriteAcquiredItem(mediaHistoryItem);

アプリの起動方法を特定する

[履歴] タイルと [新着] タイルは再生の開始に使用し、アプリの汎用起動ポイントとして使用すべきではありません。アプリが起動され、UI が表示される場合は問題ありません。音楽やビデオは 1 回のタップで開始する必要があるため、エクスペリエンスは効率的で一貫していることが重要です。

アプリが [履歴] タイルまたは [新着] タイルから起動されたかどうかを特定するには、まず、OnNavigatedTo 仮想メソッドをオーバーライドします。NavigationContext の情報を使用して、アイテムに関連付けられたメディア (この場合は、デバイスのメディア ライブラリの楽曲) を特定します。ページの読み込みが完了すると、PhoneApplicationPage の Loaded イベント ハンドラーで、この楽曲の再生が開始されます。詳細については、MSDN ライブラリ (bit.ly/y0tEiX、英語) の Music + Videos ハブのサンプルをダウンロードしてください。

図 2 のコードは、アプリが [履歴] または [新着] の一覧のアイテムから起動されたかどうかを特定する方法を示しています。

図 2 アプリが [履歴] または [新着] の一覧のアイテムから起動されたかどうかを特定する

// Indicates whether the app was launched from a MediaHistoryItem.
bool _historyItemLaunch = false;
// Key for MediaHistoryItem key-value pair.
const String _playSongKey = "keyString";   
// The song to play.
Song _playingSong = null;
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
  MediaLibrary library = new MediaLibrary();
  if (NavigationContext.QueryString.ContainsKey(_playSongKey))
  {
    // The app launched from a history item.
    // Change _playingSong even if something was already playing
    // because the user directly chose a song history item.
    // Use the navigation context to find the song by name.
    String songToPlay = NavigationContext.QueryString[_playSongKey];
    foreach (Song song in library.Songs)
    {
      if (0 == String.Compare(songToPlay, song.Name))
      {
        _playingSong = song;
        break;
      }
    }
    // Set a flag to indicate that the app started from a
    // history item and that it should immediately start
    // playing the song after the UI has finished loading.
    _historyItemLaunch = true;
  }
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
  if (_historyItemLaunch)
  {
    // Launched from a history item, start playing the song.
    if (_playingSong != null)
    {
      MediaPlayer.Play(_playingSong);
    }
  }
}

[アプリ] ページと統合する

アプリが前述の API を 1 つ以上呼び出す場合は、アプリが、ハブ内のアプリ一覧に自動的に表示されるだけでなく、メインのアプリ一覧にも表示されます。これにより、アプリの検索やアクセスが簡単になり、このアプリはコア メディア エクスペリエンスの一部になります。アプリが MediaHistory および MediaHistoryItem という API を呼び出し、HubType 属性を設定してこれがメディア アプリであることを示すようにアプリのマニフェストを変更したことを、App Hub の申請と認定のプロセスが検出した場合に、この自動統合が行われます。Windows Phone プロジェクトの WMAppManifest.xml ファイルの <App> 要素を更新することにより、申請前にこれを自分で設定できます (テスト目的のみ)。

<App  ... HubType="1">

これにより、テスト中にアプリ一覧にプログラムを表示できます。App Hub の申請プロセスは、アプリで呼び出していることを検出した API に基づいて、公開前にこのファイルを上書きします。

必要なグラフィックス ファイル

Music + Videos ハブはコンテンツ中心のため、各アプリが占有する場所は使用率に基づきます。つまり、アプリが使用されればされるほど、コンテンツは目立つ場所に配置されます。アプリを定期的に使用するユーザーがいると、Music + Videos ハブにコンテンツが表示されるようになるため、アプリを広めるすばらしいチャンスになります。

Music + Videos ハブにはさまざまなソースからコンテンツが集められるため、自身のアプリを他のアプリと区別できるよう、タイルの外観のデザインを考慮することが重要です。この意味は、アプリによって異なります。たとえば、アプリ一覧には実際のアルバムの汎用アルバム アートも表示されます。アルバムからの楽曲を再生するラジオ局アプリを開発している場合は、メディア ライブラリからの楽曲を再生しているときに表示するアルバム カバーのアートワークと見た目で区別できるタイルを表示する必要があります。ブランドとコンテンツのアートワークを同時に表示するタイルを使用することを検討します。

Music + Videos ハブに表示するタイルのグラフィックは、以下の規則に従う必要があります。

  • 各タイルにアプリのタイトルまたはロゴを含める
  • [プレイビュー] タイルを 358 x 358 ピクセルにし、ファイル サイズを 75 KB 以下にする
  • 他のタイルは 173 x 173 ピクセルにする
  • MediaHistoryItem クラスの Title プロパティに、局名やビデオ タイトルといった、コンテンツを表すテキストを設定する

ユーザーの混乱を避けるため、タイルをタップしてアルバムを再生している場合以外は、タイルにアルバム アートを表示しないようにします。ストリームを再生するアプリの場合は、再生中のストリームがタイルのグラフィックでわかるようにします。これは認定要件ではなく、ベスト プラクティスです。

メディアを再生する

ビデオの再生では、XNA Framework アプリと Silverlight アプリのどちらを作成しても、エクスペリエンスは変わりません。XNA Framework アプリでは、MediaPlayerLauncher クラスを使用します。このクラスは、MediaPlayerLauncher.Show を呼び出したときに、Windows Phone メディア プレーヤーを起動します。Silverlight アプリでは、MediaElement APIを使用します。この API を使用すると、コントロールの外観や配置などのユーザー エクスペリエンスをより細かくカスタマイズできますが、最終的には、Windows Phone メディア プレーヤーを使用してビデオを表示します。オーディオの場合は、もう少しおもしろくなります。

MediaElement と SoundEffect の比較

XNA Framework アプリでは、SoundEffect クラス (または関連する SoundEffectInstance クラスか DynamicSoundEffectInstance クラス) を使用してオーディオを再生します。これらのクラスは、WAV オーディオ ソースの再生のみをサポートします。ただし、再生をよりきめ細かく制御でき、最大 16 個のサウンドを一度に再生し、出力時にそれらのサウンドをミキシングするといった、より優れた機能をいくつか使用できます。

Silverlight アプリでは、オーディオとビデオの再生に MediaElement クラスを使用できます。MediaElement は、WAV、WMA、MP3 などのオーディオ ソースの再生をサポートします。Windows Phone で再生できるオーディオ形式の完全な一覧については、「Windows Phone のサポートされるメディア コーデック」(msdn.microsoft.com/ja-jp/library/ff462087(v=VS.92).aspx) を参照してください。MediaElement では、一度に再生できるサウンドは 1 つだけです。既に別のサウンドが再生されている場合、MediaElement は、新しいサウンドの再生を開始するときに、再生中のサウンドを停止します。

Silverlight アプリでは、オーディオの再生に SoundEffect クラスを使用することもできます。Silverlight アプリで XNA Framework API を使用するには、XNA Framework アプリのゲーム ループのシミュレーションを行う必要があります。このシュミレーションを行うには、通常、StartGameLoop というメソッドを作成して、GameTimer を設定します。PhoneApplicationPage 派生クラスのコンストラクターから StartGameLoop メソッドを呼び出します (図 3 参照)。GameTimer は、Windows Phone 7.1 SDK で使用できる新しいクラスで、Silverlight と XNA Framework の統合を容易にします。

図 3 XNA Framework ゲーム ループのシミュレーションを行う Silverlight の StartGameLoop

// Constructor
public MainPage()
{
  InitializeComponent();
   StartGameLoop();
}
private void StartGameLoop()
{
  // Timer to simulate the XNA game loop (SoundEffect
  // class is from the XNA Framework).
  GameTimer gameTimer = new GameTimer();
  gameTimer.UpdateInterval = TimeSpan.FromMilliseconds(33);
  // Call FrameworkDispatcher.Update to update the XNA Framework internals.
  gameTimer.Update += delegate { try { FrameworkDispatcher.Update(); } catch { } };
  // Start the GameTimer running.
  gameTimer.Start();
  // Prime the pump or you'll get an exception
  // on the first XNA Framework call.
  FrameworkDispatcher.Update();
}

このタイマー ループを実装したら、PhoneApplicationPage 派生クラスの任意の場所で XNA Framework API を呼び出すことができます。

Marketplace 認定

アプリから MediaHistory クラスまたは MediaHistoryItem クラスを呼び出すと、Music + Videos ハブのアプリと見なされ、携帯電話にインストールされるとアプリ一覧に表示されます。アプリの申請プロセスは、アプリがこれらのクラスを使用していることを検出して、Windows Phone アプリのマニフェスト ファイルのハブの種類を Music + Videos に自動的に更新します。

アプリが Marketplace に受け入れられるには、メディアの再生に関連するさまざまな認定要件に従う必要があります。この記事の執筆時点では、これらの認定要件は「Windows Phone のアプリケーション認定の要件」(msdn.microsoft.com/ja-jp/library/hh184843(v=VS.92).aspx) の「特定のアプリケーションの種類についての追加の要件」の条項 6.4 および 6.5 に記載されています。認定要件は、絶えず変化し、定期的に更新されるため、以下のいずれのガイダンスも、最新のバージョンを確認するようにしてください。

認定要件では、アプリの起動時に、ユーザーが再生中の音楽を中断してはならないことが定められています。たとえば、ユーザーがゲームの操作中にお気に入りの音楽を聴く場合があるので、これは理にかなっています。条項 6.5.1 および 6.5.2 では、このシナリオについて取り上げています。

他にも興味深い条項として 6.5.3 があります。この条項では、以下のことが取り上げられています。

アプリは、携帯電話で現在再生中の音楽を中断し、インタラクティブではないフルモーション ビデオや、インタラクティブではないオーディオ セグメント (カットシーンやメディア クリップなど) を、ユーザーに同意を求めずに再生することができます。

アプリを終了したら、以前に再生していた音楽を再開する必要があります。

では、どのようにしてユーザーの音楽を一時停止および再開するのでしょう。Silverlight アプリを作成している場合は、先ほど詳しく説明したように、ゲーム ループのシミュレーションを設定する必要があります。

今回、現在再生中のオーディオを一時停止して、サウンド効果を再生し、再生中だったオーディオをすぐに再開するという実験をしました。この実験では、不快なユーザー エクスペリエンスが生み出され、再生したかったサウンド効果が失われました。そこで、結局、ユーザーが今回のデモ ページに移動してきたときに現在再生中のオーディオを一時停止し、別のページに移動していったときにオーディオを再開することにしました。これは、OnNavigatedTo メソッドと OnNavigatedFrom メソッドをオーバーライドすることによって実行します。オーバーライドしたメソッドでは、ヘルパー関数を呼び出して、オーディオを一時停止および再開します (図 4 参照)。

図 4 OnNavigatedTo メソッドと OnNavigatedFrom メソッドをオーバーライドしてオーディオを一時停止する

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  // If the MediaPlayer is already playing music,
  // pause it upon entering the app.
  PauseMediaPlayer();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
  // If the MediaPlayer was already playing music,
  // resume playback as the user leaves the app.
  ResumeMediaPlayer();
}
private void PauseMediaPlayer()
{
  // See the MainPage Constructor earlier in the
  // article where the GameTimer object is created.
  // This enables the use of the XNA Framework MediaPlayer
  // class by pumping the XNA FrameworkDispatcher.
  // Pause the media player if it's already playing music.
  if (!MediaPlayer.GameHasControl)
  {
    MediaPlayer.Pause();
    resumeMediaPlayerAfterDone = true;
  }
}
private void ResumeMediaPlayer()
{
  // If music was playing, resume playback.
  if (resumeMediaPlayerAfterDone)
  {
    MediaPlayer.Resume();
  }
}

適格なアプリにする

要点をまとめると、Windows Phone OS 向けのメディア アプリを作成する場合は、実際のメディアの処理に関する低レベルの詳細にとどまらず、さまざまなことを検討します。

Music + Videos ハブに統合して、ユーザーがすべてのメディア アプリに期待する方法で、アプリのユーザー エクスペリエンスを生み出します。[履歴] タイルと [新着] タイルにコンテンツを設定し、アプリ一覧にプログラムを表示します。

メディア アプリに関する認定要件を理解し、アプリが Windows Phone Marketplace の申請プロセスに合格できるようにします。

これらのガイドラインに従うことで、ユーザーがアプリの操作方法を知るうえで幸先の良いスタートを切れるようにします。また、アプリとコンテンツが Music + Videos ハブの適切な領域に表示されるようにすることで、アプリとコンテンツの認知度を高めます。その結果、アプリは Windows Phone に "適格なアプリ" になります。

Mark Hopkins は、Windows Phone 開発者向けドキュメント チームのシニア プログラミング ライターです。彼は、1992 年からマイクロソフトに勤務しており、開発者サポート、Visual C++、MFC、Windows Platform SDK、Internet Explorer SDK、Tablet PC SDK、Surface SDK、Windows Phone SDK など、開発者に重点を置いた製品に携わってきました。また、ミュージシャンでもあり、Seattle Sounders FC の熱心なファンでもあります。

この記事のレビューに協力してくれた技術スタッフの Andrew ByrneKim CameronRobert LyonNitya RaviCheryl Simmons、および Matt Stroshane に心より感謝いたします。