この記事は機械翻訳されたものです。

快適な動作

Windows Phone 7.5 のバックグラウンド オーディオ (機械翻訳)

Charles Petzold

コード サンプルをダウンロードします。

Charles Petzold昔の MS-DOS で、プログラマはタスク切り替えの原油フォーム終了と滞在常駐 (TSR とも呼ばれます) と呼ばれる手法を実装できます。 TSR プログラムは、キーボード割り込みまたは OS の他のメカニズムにフックをインストールし、プログラム メモリには、特定のキーの組み合わせまたは興味の何が起こったときにアクションをキックする準備ができてまま終了します。

MS-DOS は、これらの Tsr いくつかの深刻な問題を作成このレベルでも初歩的なタスクの切り替え、処理するように装備ではなかった。 彼らは互いに競合し、全体の OS を頻繁にクラッシュします。 これは、いくつかの私たちを補完し、後で MS-DOS を置換する Windows を歓迎する主な理由の1 つだった。

私はこの古代史 Windows Phone 7.5 アプリケーションからバック グラウンドで音楽ファイルを再生する方法を示しますつもりのだし、開発者、ボックスの外側を考える傾向にあることを知っているので言及します。 一般的に、これは良いことですが、この手法を使用して音楽ファイルを再生する以外の目的べきではないです。 そう、Windows Phone 市場では拒否するようにアプリケーションを可能性があります。

紹介する手法は、Web 上の場所または分離ストレージからのサウンドまたは音楽ファイルを再生するためにのみです。 アプリケーションが携帯電話の音楽ライブラリから曲を再生する必要がある場合は、前述の以前の問題で、MediaLibrary MediaPlayer クラスを使用して行うことができます (msdn.microsoft.com/magazine/hh708760)。

アプリケーションと DLL

Windows Phone 7.5 では、アプリケーションを支援するために、バック グラウンドで実行されるオブジェクトは、エージェントとして知られています。 バック グラウンドで音楽ファイルを再生するには、AudioPlayerAgent から派生したクラスを使用します。 このクラスは、プログラムによって参照されているダイナミック リンク ライブラリでする必要があります。 プログラム コード自体はバック グラウンドで実行されません。 何がバック グラウンドで実行される AudioPlayerAgent から派生したこのクラスです。

この記事が SimpleBackgroundAudio という名前の Visual Studio ソリューションには、ダウンロード可能なコードに含まれています。 明快さのために、このプログラムには最小限バック グラウンド動作するようにオーディオを得るために必要なコードだけにはが含まれています。 私は Windows Phone アプリケーションをクリックし、[Windows Phone 7.1 を指定して、[新しいプロジェクト] ダイアログ ボックスから、ソリューション作成。 (7.1 の指定、Windows Phone OS と Windows Phone アプリケーション内で内部的に使用されますより一般的な 7.5 の指定と同じものを意味)。

SimpleBackgroundAudio プロジェクトの Page クラスには、ボタンと、そのボタンの Click ハンドラーを追加しました。

void OnPlayButtonClick(object sender, RoutedEventArgs args)
{
  AudioTrack audioTrack = 
    new AudioTrack(new Uri("http://www.archive.org/.../Iv.Presto.mp3"), 
                   "Symphony No.
9: 4th Movement", 
                   "Felix Weingartner", 
                   "Beethoven: Symphony No.
9", 
                   null, 
                   null, 
                   EnabledPlayerControls.Pause);
  BackgroundAudioPlayer.Instance.Track = audioTrack;
}

AudioTrack と BackgroundAudioPlayer のクラス、Microsoft.Phone.BackgroundAudio 名前空間にあります。 インターネット ベートーベンの交響曲第の最後の動きを含むアーカイブ (archive.org) 上に MP3 ファイルを (ここで、雑誌の列幅に合わせてを短縮した) URL を参照します。 フェリックス ・ ワインガルトナーによって、1935年記録として 9。 (分離ストレージ内のファイルに対応する URL または指定することができます; 場合に、UriKind.Relative 引数、Uri コンス トラクターを使用します。)次の 3 つの引数、AudioTrack コンス トラクターのアルバム、アーティスト、トラックの情報を提供します。

BackgroundAudioPlayer クラスは、フォア グラウンドでのオーディオ ファイルを再生する MediaElement または MediaPlayer クラスに似ています。 BackgroundAudioPlayer には、コンス トラクターがない; 代わりに、静的インスタンス プロパティの唯一のインスタンスを取得します。 このコードでは、トラック プロパティは作成した AudioTrack オブジェクトに設定されます。

コンパイルし、このプログラムを実行することができますが、何もしません。 歌う BackgroundAudioPlayer を確認するには、AudioPlayerAgent から派生したクラスを含む DLL する必要があります。 Visual Studio このクラス ライブラリ プロジェクトを作成することができます。 私のプログラムは、私は Visual Studio で、SimpleBackgroundAudio ソリューション名を右クリックしてメニューからの新しいプロジェクトの追加を選択、Windows Phone オーディオ再生エージェントを [テンプレート] リストから選んだ。 この新しいプロジェクトの SimpleAudioPlaybackAgent という名前の。

Visual Studio と AudioPlayerAgent、いくつかのスケルトン メソッドが初期化されてから派生したオーディオをという名前のクラス ライブラリ プロジェクトを作成します。 これは、バック グラウンドで実行するクラスです。

非常に重要。この DLL は、アプリケーションからの参照を作成 ! これを行うで、参照セクションの下の SimpleBackgroundAudio のプロジェクトは、選択した参照の追加] を右クリックし、[] ダイアログ ボックスでは [プロジェクト] タブをクリックし、SimpleAudioPlaybackAgent プロジェクト身を選択します。

AudioPlayerAgent 派生では、少なくとも 2 つの方法を変更します。OnPlayStateChanged と OnUserAction。 完全なオーディオ クラス (マイナス ディレクティブとコメントを使用して) このプロジェクトから表示されます図 1

図 1 SimpleBackgroundAudio のオーディオ クラス

namespace SimpleAudioPlaybackAgent
{
  public class AudioPlayer : AudioPlayerAgent
  {
    protected override void OnPlayStateChanged(BackgroundAudioPlayer player,
                                      AudioTrack track, PlayState playState)
    {
      switch (playState)
      {
        case PlayState.TrackReady:
          player.Play();
          break;

        case PlayState.TrackEnded:
          player.Track = null;
          break;
      }
      NotifyComplete();
    }
    protected override void OnUserAction(BackgroundAudioPlayer player, 
                                      AudioTrack track, UserAction action, 
                                      object param)
    {
      switch (action)
      {
        case UserAction.Pause:
          player.Pause();
          break;

        case UserAction.Play:
          player.Play();
          break;
      }
      NotifyComplete();
    }

    protected override void OnError(BackgroundAudioPlayer player, 
                                      AudioTrack track, Exception error, 
                                      bool isFatal)
    {
        base.OnError(player, track, error, isFatal);
        NotifyComplete();
    }
    protected override void OnCancel()
    {
        base.OnCancel();
        NotifyComplete();
    }
  }
}

まず、OnPlayStateChanged を見てをオーバーライドします。 このメソッドは、BackgroundAudioPlayer の PlayState プロパティが変更されたときに呼び出されます。 最初の引数、プログラム コードで参照されて、同じ BackgroundAudioPlayer である; 最後の引数は、PlayState 列挙体のメンバーです。

プログラムが、Click イベント ハンドラーで、BackgroundAudioPlayer のトラック プロパティを設定すると、BackgroundAudioPlayer、音楽ファイル、インターネット上にアクセス; SimpleAudioPlaybackAgent DLL が読み込まれ、OnPlayStateChanged メソッドは PlayState.TrackReady に設定、playState 引数で、呼び出しを取得します最終的に。 それは、そのトラックの再生を開始するには、BackgroundAudioPlayer オブジェクトの Play メソッドを呼び出す OnPlayStateChanged の責任です。

電話番号の正規の音楽プレーヤー何か、時に再生する場合は、停止します。 この時点で、プログラムから離れて移動またはも、携帯電話の戻るボタンを押して終了することができ、音楽再生が続行されます。

Windows Phone エミュレーターでは、このプログラムを実行することができますが、携帯電話のボリューム コントロール キーを押すことができますので、実際の電話にしようとする必要があります。 これは少しドロップダウンで、普遍的なボリューム コントロール (UVC として)、バック グラウンド音声の重要な部分は知られて呼び出します。 UVC には、再生中のトラックの名前と、アプリケーション、AudioTrack コンス トラクターには、引数に基づいて、アーティストが表示されます。 UVC には、前のトラック、一時停止、次のトラックのためのボタンも表示されます。 AudioTrack コンス トラクターへの最後の引数で指定したものであるためこのプログラムでは、[一時停止] ボタンのみが有効です。 [一時停止] ボタンを押すと、一時停止と再生を切り替えます。

これらの一時停止と再生のコマンドに示すように、OnUserAction のオーバーライドで、オーディオ クラスを処理図 1。 UserAction 引数がユーザーによって押された特定のボタンを示します。 OnUserAction は、BackgroundAudioPlayer オブジェクトの適切なメソッドを呼び出すことによって応答します。

トラックの再生が終了すると、PlayState.TrackEnded を呼び出すと OnPlayStateChanged を取得します。 メソッドは、UVC からアイテムを削除、BackgroundAudioPlayer は null のトラック プロパティを設定することによって応答します。 する場合は、アプリケーションに戻るし、再度遊ぶ音楽を開始できます。

OnPlayStateChanged と OnUserAction の両方 NotifyComplete への呼び出しを完了することに注意してください。これが必要です。 また、どちらのメソッドに基本クラスのメソッドへの呼び出しが含まれることにも注意してください。 これらの基本クラスの呼び出しは Visual Studio が作成するテンプレートの一部が、基本メソッドが呼び出されたときは、OnUserAction のオーバーライドの問題があった。 背景のオーディオのサンプル コードを Microsoft (利用可能なオンライン Windows Phone 7.5 ドキュメント領域から) また、基本メソッドの呼び出しが含まれていません。

非常に奇妙な DLL

バック グラウンド音声を試す場合は、Visual Studio の出力ウィンドウのウォッチを維持する必要があります。 デバッガーから SimpleBackgroundAudio を実行すると、[出力] ウィンドウに SimpleBackgroundAudio.dll は、プログラム自体と同様に、プログラムを実行するには、電話で読み込まれているすべてのシステム ライブラリ一覧表示されます。 これらのライブラリを一覧表示、[出力] ウィンドウの行は、単語「UI タスク プログラムを示す、「開始します。

SimpleBackgroundAudio のボタンをタップすると、多くの同一 Dll を読み込んで表示されます-が、今、それぞれの行、単語「バック グラウンド タスク」で始まりますこれらの Dll には、SimpleAudioPlaybackAgent.dll と同様、アプリケーション DLL が含まれます。 これらの Dll の読み込みボタンをタップした後の再生を開始するには、音楽のための時間を少しかかる理由の 1 つです。

バック グラウンド音声を再生するプログラムをみると、おそらく、オーディオ クラスのすべてのメソッドのオーバーライドで Debug.WriteLine ステートメントを挿入して [出力] ウィンドウでのリアルタイム挙動を研究します。

別の Debug.WriteLine ステートメントで、クラスのコンス トラクターは、オーディオを作成することも可能性があります。 電話 OnPlayStateChanged または OnUserAction にする必要があるときにオーディオの新しいインスタンスがインスタンス化されることを発見するでしょう。 すべての呼び出しでは、新しいインスタンスを取得します !

この単純な事実は、深遠な意味があります。OnPlayStateChanged への呼び出しと OnUserAction 間の情報を維持するためにこのオーディオ クラス必要がある場合は、その情報を維持する必要があります­に関する静的フィールドまたはプロパティ。

どのような場合、SimpleBackgroundAudio プログラム内のクラスから、オーディオ ライブラリ クラスに、SimpleAudioPlaybackAgent 情報を渡す必要があるか。 オーディオ クラスでは、パブリックな静的メソッドを定義し、MainPage または、プログラム内の別のクラスからメソッドを呼び出すに合理的なようです。 確かにこれを行うことができますが、何をしたいのか。何かこの方法から保存の呼び出し中に OnPlayStateChanged と OnUserAction できなくなります。

なぜ使用できませんか? Visual Studio の出力ウィンドウの UI タスクとバック グラウンド タスクの指定を思い出してください。 これらの 2 つの別個のプロセスです。 プログラムによって参照される DLL のインスタンスは、バック グラウンドでのインスタンスと同じではないと UI タスクと、バック グラウンド タスク間この DLL 内のクラスにも静的データを共有するため。

背景のオーディオ アプリケーションをデバッガーから Visual Studio でテストすると、いくつかの追加の奇妙を体験します。 いくつかバック グラウンド音声を開始しているプログラムを終了すると、オーディオ再生、Visual Studio コードがまだ実行されていることを示します。 あなたのプログラムの編集を再開するには、直接 Visual Studio から、デバッグを停止する必要がありもし音楽よくプレーを続けるでしょう。 背景のオーディオ プログラムの開発時に、おそらく自分で頻繁に携帯電話から、プログラムをアンインストールを見つけること。

アプリケーションを強化

SimpleBackgroundAudio プログラムは、大きな問題があります。 それは音楽の再生を開始するためのボタンがありますが、それを一時停止またはシャット ダウンする方法はありません。 ときに音楽を終了または他の何かが起こっているかを知っていません。 はい、ユーザーは常にバック グラウンド音声を制御するには、UVC を呼び出すことができますが、音楽の再生を開始する任意のプログラムはまたそれをシャット ダウンするには、独自のコントロールを含める必要があります。

再生リストの名前のプロジェクトでこれらの機能強化が含まれている­プレーヤー。 名前が示すように、このプログラムの一連の連続したトラックを再生 — この場合は、クロード ・ ドビュッシー プレリュードからの 12 の小さなピアノ作品予約 1、アルフレッド ・ コルトーで、1949 年に実行記録をインターネット ・ アーカイブから利用できます。

私はもともと、プログラム内のすべての AudioTrack オブジェクトを作成し、それらをバック グラウンド音声 DLL に渡していました。 より一般化されたプログラム構造に見えたが、アプリケーション、DLL、バック グラウンドで実行している 1 つ以上の別のインスタンスにアクセスしているため、動作しませんでしたを発見しました。 代わりに、すべての AudioTrack オブジェクト自体を作成し、再生リストと呼ばれる汎用リストに格納するには、オーディオ クラスを書いた。

ややより困難をプログラムを確認するには、再生リストは円形ではない決定。私は、最後のトラックを最初のトラックからまたは、最初から最後のスキップを望んでいません。 その理由は、AudioTrack コンス トラクターの最初の EnabledPlayerControls.Pause と EnabledPlayerControls.SkipNext のフラグを組み合わせた、最後の引数がある; 最後の AudioTrack、一時停止、SkipPrevious フラグを組み合わせたものです。 他のすべての 3 つのすべてのフラグがあります。 これは、3 つのボタンどのように様々 なトラックの UVC で有効になっているです。

図 2 OnPlayStateChanged と OnUserAction のオーバーライドを示しています。 1 つのトラックを終了すると、OnPlayStateChanged では、次のトラック、BackgroundAudioPlayer のトラック プロパティに設定されます。 OnUserAction、前のトラックと次のトラック コマンドから UVC、前または次の AudioTrack、再生リスト内に、トラック プロパティを設定して処理をオーバーライドします。

図 2 PlaylistPlayer 内のオーディオのオーバーライド

static List<AudioTrack> playlist = new List<AudioTrack>();
static int currentTrack = 0;

...
protected override void OnPlayStateChanged(BackgroundAudioPlayer player, 
  AudioTrack track, PlayState playState)
{
  switch (playState)
  {
    case PlayState.TrackReady:
      player.Play();
      break;

    case PlayState.TrackEnded:
      if (currentTrack < playlist.Count - 1)
      {
        currentTrack += 1;
        player.Track = playlist[currentTrack];
      }
      else
      {
        player.Track = null;
      }
      break;
  }
  NotifyComplete();
}

protected override void OnUserAction(BackgroundAudioPlayer player, 
  AudioTrack track, UserAction action, object param)
{
  switch (action)
  {
    case UserAction.Play:
      if (player.Track == null)
      {
        currentTrack = 0;
        player.Track = playlist[currentTrack];
      }
      else
      {
        player.Play();
      }
      break;

    case UserAction.Pause:
      player.Pause();
      break;

    case UserAction.SkipNext:
      if (currentTrack < playlist.Count - 1)
      {
        currentTrack += 1;
        player.Track = playlist[currentTrack];
      }
      else
      {
        player.Track = null;
      }
      break;

    case UserAction.SkipPrevious:
      if (currentTrack > 0)
      {
        currentTrack -= 1;
        player.Track = playlist[currentTrack];
      }
      else
      {
        player.Track = null;
      }
      break;

    case UserAction.Seek:
      player.Position = (TimeSpan)param;
      break;
  }
  NotifyComplete();
}

プログラムの Page クラス、一連のと、UVC 同じ機能を実行する 4 つの標準的なアプリケーション バー ボタンがあります。 それも現在のトラック情報を画面を更新するには、イベント、PlayStateChanged イベントのハンドラーを BackgroundAudioPlayer トラックの進捗をスライダーを更新するには、CompositionTarget.Rendering ハンドラーを示すように設定と図 3

The PlaylistPlayer Program
図 3 PlaylistPlayer プログラム

有効にして、アプリケーション バー ボタンを無効にするためのロジックは、いたって単純です。[前のトラックと次のトラック] ボタンは、現在の AudioTrack の PlayerControls プロパティに基づいて有効になっている; したがって、UVC と一貫性のある必要があります。 プレーヤーを再生している場合、[一時停止] ボタンが有効な; [再生] ボタンは、プレーヤーを一時停止した場合に有効になります。 現在のトラックが null の場合は、再生が有効になっているし、他のすべてのボタンは無効になります。

4 アプリケーション バー ボタンのクリック ハンドラーそれぞれ SkipPrevious、再生、一時停止、SkipNext、BackgroundAudioPlayer メソッドへの呼び出しを確認します。 これらのメソッド呼び出しが直接音楽再生の動作を制御しないことを理解することが重要です。 代わりに、OnUserAction 呼び出し、オーディオ クラスで、プログラムからこれらのメソッドの呼び出しをトリガーし、それが実際に開始し、音楽を停止するオーディオのコードです。

BackgroundAudioPlayer の再生と一時停止メソッドを呼び出し、プログラムまたは OnUserAction オーバーライドから呼ばれるしているかどうかによって異なる動作、ためやや独特です。

また、トラックの特定の場所に移動するには、スライダーの ValueChanged ハンドラー追加。 ハンドラーはトラックの新しい位置を計算し、適切な TimeSpan オブジェクトは、BackgroundAudioPlayer の位置プロパティを設定します。 場合と同様に、再生と一時停止の呼び出しで、このプロパティを設定、トラックの位置変更されません。 代わりに、それ OnUserAction オーバーライドの呼び出しオーディオで UserAction.Seek とパラメーター引数でエンコードされた TimeSpan のアクション引数を生成します。 OnUserAction をオーバーライドし、この TimeSpan オブジェクトは、BackgroundAudioPlayer の位置プロパティを設定し、ジャンプの原因は何実際にです。

実際には、このスライダーはあなただけが前方に移動するか、または 10% にトラックをバックアップをタップすると正しく動作します。 それをスライドする場合は、シークの複数の呼び出しを作成するようだし、音の混乱になります。 多くため、スライダーではなく、通常のスクロール バーを使用することを希望し、コントロールを操作するユーザーを停止したときに発生します、EndScroll イベントを待つこと。 残念ながら、私はスクロール バーすべてで仕事を Windows Phone を説得することが行ったことがないです。

制限事項

それはどのように Windows Phone 7.5 プログラマより直接アクセス (フィード、ビデオなど)、携帯電話のハードウェアにいくつかのバック グラウンド処理を実行するには、能力だけでなく、与えているを見るは興味深いしています。 しかし、このバック グラウンド音声の実装から行方不明部分はそこにある思考を助けることはできません。

プログラムが順番に再生する音楽ファイルの一覧からを選択できるようにしたいと仮定します。 それは責任を各トラックを終了したときに、BackgroundAudioPlayer のトラック プロパティを設定する必要があるプログラム、全体のリストを DLL には、手をすることはできません。 しかし、これは、プログラムをフォア グラウンドで実行されているときにのみ発生することができます。

それは、アプリケーションと背景 DLL 文字列 AudioTrack クラスの Tag プロパティをいくつかの情報を渡すことは可能です。 しかし、DLL に追加情報を渡すことを願って AudioTrack から新しいクラスを派生する気にしないでください。DLL に渡すをオーバーライドするため、アプリケーションによって作成された AudioTrack オブジェクトのコピーが作成されます。

幸いにも、DLL、アプリケーションの分離ストレージ領域にプログラム再生リストを説明する小さなファイルを保存することができ、DLL、プレイリストからファイルにアクセスできるようにアクセスします。 この列のボーナス プログラム PlaylistFilePlayer は、この手法は単純なアプローチを示しますという名前のプロジェクトです。

Charles Petzold は、長年の貢献エディター MSDN magazine です。 彼の最近の本は、「プログラミング Windows Phone 7」(マイクロソフト プレス、2010) は無料ダウンロードとして利用可能な bit.ly/cpebookpdf

この記事のレビュー、技術スタッフのおかげでに: Mark Hopkins