方法: Windows Phone のバックグラウンド オーディオを再生する

2012/02/09

ここでは、フォアグラウンドにないときもオーディオの再生を続ける Windows Phone 7.5 用 Windows Phone アプリケーションを作成する方法を示します。次の 2 種類のバックグラウンド オーディオ アプリケーションがあります。1 つはローカル メディアを再生するもので、もう 1 つはストリーミング メディアを再生するものです。この記事では、オーディオ再生エージェントを使用してローカル メディアを再生する Windows Phone アプリケーションの実装方法を説明します。

ヒントヒント:

バックグラウンド オーディオ アプリケーションのアーキテクチャの説明については、「Windows Phone のバックグラウンド オーディオの概要」を参照してください。この概要には、アプリケーションを実装するときに従う必要のあるベスト プラクティスも含まれます。

バックグラウンド オーディオを再生するには、Visual Studio で Windows Phone 用の Silverlight プロジェクト テンプレートを使用して、Windows Phone オーディオ再生エージェントを作成します。次に、このバックグラウンド エージェントをアプリケーションから参照します。

ヒントヒント:

Windows Phone アプリケーション内でバックグラウンド オーディオを再生することの詳細については、「Windows Phone のコード サンプル」ページからバックグラウンド オーディオ プレーヤーのサンプルおよびバックグラウンド オーディオ ストリーマーのサンプルをダウンロードしてください。

重要な注重要な注:

この記事では、Windows Phone SDK を使用する必要があります。「Windows Phone SDK のインストール」を参照してください。

Windows Phone バックグラウンド オーディオ アプリケーションの作成

  1. [ファイル] メニューの [新しいプロジェクト] をクリックして、新しいプロジェクトを作成します。

  2. [新しいプロジェクト] ダイアログが表示されます。Visual C# のテンプレートを展開してから、Silverlight for Windows Phone のテンプレートを選択します。

  3. Windows Phone アプリケーション テンプレートを選択します。適切な [名前] を入力し、[OK] をクリックします。

  4. ターゲット バージョンとして [Windows Phone 7.1] を選択し、[OK] をクリックします。

  5. ソリューション エクスプローラーで、[ソリューション] ノードを右クリックし、[追加]、[新しいプロジェクト] の順にクリックします。

  6. [新しいプロジェクトの追加] ダイアログで、[Windows Phone オーディオ再生エージェント] をクリックします。

  7. 適切な [名前] を入力し、[OK] をクリックします。

  8. これで、ソリューションのプロジェクトは、アプリケーション プロジェクトとバックグラウンド エージェント プロジェクトの 2 つになります。

    BackgroundAudioSolution

    アプリケーション プロジェクトの [参照] ノードを右クリックし、[参照の追加] を選択します。

  9. [参照の追加] ダイアログで、[プロジェクト] タブをクリックします。作成したバックグラウンド エージェントを選択し、[OK] をクリックします。

オーディオ ファイルの追加

  1. ソリューション エクスプローラーで、使用するアプリケーション プロジェクトを右クリックし、[追加]、[新しいフォルダー] の順にクリックします。フォルダーに「Audio」という名前を付けます。

  2. 作成した Audio フォルダーを右クリックし、コンテキスト メニューの [追加]、[既存の項目] の順にクリックします。

  3. [既存の項目の追加] ダイアログで、"%PUBLIC%\Music\Sample Music" (通常は C:\Users\Public\Music\Sample Music) に移動し、オーディオ ファイルをいくつか選択します。バックグラウンド オーディオ プレーヤーでサポートされているファイル形式については、「Windows Phone のサポートされるメディア コーデック」を参照してください。

  4. [追加] をクリックします。

  5. ソリューション エクスプローラーで、Audio ディレクトリに追加したすべてのオーディオ ファイルを選択します。[プロパティ] ペインで、[出力ディレクトリにコピー] フィールドを "コピーしない" から "新しい場合はコピーする" に変更します。

    BackgroundAudioAddMedia

ユーザー インターフェイスの作成

  1. このアプリケーションのユーザー インターフェイスは、とてもシンプルです。ソリューション エクスプローラーで、[MainPage.xaml] をダブルクリックして XAML デザイナー/エディターで開きます。

  2. TitlePanel という名前の StackPanel 要素を、次の XAML コードに置き換えます。

    <!--TitlePanel contains the name of the application and page title-->
    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="BACKGROUND AUDIO PLAYER" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="play a song" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>
    
  3. ContentPanel という名前の Grid 要素を、次の XAML コードに置き換えます。

    <!--ContentPanel - place additional content here-->
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <StackPanel Orientation="Horizontal" Width="420" Margin="18,40,18,0" VerticalAlignment="Top">
            <Button Content="prev" x:Name="prevButton" Height="140" Width="140" Click="prevButton_Click"/>
            <Button Content="play" x:Name="playButton" Height="140" Width="140" Click="playButton_Click"/>
            <Button Content="next" x:Name="nextButton" Height="140" Width="140" Click="nextButton_Click"/>
        </StackPanel>
        <TextBlock x:Name="txtCurrentTrack" Height="75" HorizontalAlignment="Left" Margin="12,193,0,0" VerticalAlignment="Top" Width="438" TextWrapping="Wrap" />
    </Grid>
    

    StackPanel は、ボタンを配置するときに非常に便利な要素です。この場合、Orientation プロパティを適切に設定することによってボタンを水平に並べます。

  4. デザイナーのユーザー インターフェイスの外観は、次のとおりです。

    BackgroundAudioUI

ユーザー インターフェイスの背後でのコードの変更

  1. ソリューション エクスプローラーで、[MainPage.xaml] を右クリックし、コンテキスト メニューの [コードの表示] をクリックします。

  2. MainPage.xaml.cs ファイルの先頭に次の using ステートメントを追加します。

    using System.Windows.Navigation;
    using Microsoft.Phone.BackgroundAudio;
    
  3. 次のボタン クリック イベント ハンドラー コードを、MainPage.xaml.cs の MainPage クラスに追加します。

    #region Button Click Event Handlers
    
    private void prevButton_Click(object sender, RoutedEventArgs e)
    {
        BackgroundAudioPlayer.Instance.SkipPrevious();
    }
    
    private void playButton_Click(object sender, RoutedEventArgs e)
    {
        if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)
        {
            BackgroundAudioPlayer.Instance.Pause();
        }
        else
        {
            BackgroundAudioPlayer.Instance.Play();
        }
    }
    
    private void nextButton_Click(object sender, RoutedEventArgs e)
    {
        BackgroundAudioPlayer.Instance.SkipNext();
    }
    
    #endregion Button Click Event Handlers
    

    現在の再生状態に応じて、playButton_Click ハンドラーによって再生と一時停止が切り替わることを実際に確認してください。

  4. MainPage クラスのコンストラクターで、PlayStateChanged イベントのイベント ハンドラーを追加します。

    BackgroundAudioPlayer.Instance.PlayStateChanged += new EventHandler(Instance_PlayStateChanged);
    
  5. 次のように Instance_PlayStateChanged メソッドを実装します。

    void Instance_PlayStateChanged(object sender, EventArgs e)
    {
        switch (BackgroundAudioPlayer.Instance.PlayerState)
        {
          case PlayState.Playing:
            playButton.Content = "pause";
            break;
    
          case PlayState.Paused:
          case PlayState.Stopped:
            playButton.Content = "play";
            break;
        }
    
        if (null != BackgroundAudioPlayer.Instance.Track)
        {
          txtCurrentTrack.Text = BackgroundAudioPlayer.Instance.Track.Title +
                                 " by " +
                                 BackgroundAudioPlayer.Instance.Track.Artist;
        }
    }
    
  6. このアプリケーションはオーディオをバックグラウンドで再生するように設計されているため、ユーザーがこのアプリケーションに戻ってくるときはオーディオが再生されていることが考えられます。ユーザー インターフェイスは、現在の再生状態および再生中のトラックが適切に反映されるように更新して、そのことを示す必要があります。アプリケーションが読み込まれたときに UI を更新するには、次のコードを MainPage.xaml.cs の MainPage クラスに追加することにより、OnNavigatedTo 仮想メソッドをオーバーライドします。

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        if (PlayState.Playing == BackgroundAudioPlayer.Instance.PlayerState)
        {
            playButton.Content = "pause";
            txtCurrentTrack.Text = BackgroundAudioPlayer.Instance.Track.Title +
                             " by " +
                             BackgroundAudioPlayer.Instance.Track.Artist;
    
        }
        else
        {
            playButton.Content = "play";
            txtCurrentTrack.Text = "";
        }
    }
    
  7. ソリューション エクスプローラーで、[App.xaml] を右クリックし、コンテキスト メニューの [コードの表示] をクリックします。

  8. App.xaml.cs に次の using ステートメントを追加します。

    using System.IO.IsolatedStorage;
    using System.Windows.Resources;
    
  9. BackgroundAudioPlayer で再生できるのは、分離ストレージまたはリモート URI にあるファイルだけです。App クラスに次のメソッドを追加します。files アレイに、プロジェクトに追加したオーディオ ファイルの名前が含まれていることを確認します。

    private void CopyToIsolatedStorage()
    {
        using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
        {
            string[] files = new string[] { "Kalimba.mp3", "Maid with the Flaxen Hair.mp3", "Sleep Away.mp3" };
    
            foreach (var _fileName in files)
            {
                if (!storage.FileExists(_fileName))
                {
                    string _filePath = "Audio/" + _fileName;
                    StreamResourceInfo resource = Application.GetResourceStream(new Uri(_filePath, UriKind.Relative));
    
                    using (IsolatedStorageFileStream file = storage.CreateFile(_fileName))
                    {
                        int chunkSize = 4096;
                        byte[] bytes = new byte[chunkSize];
                        int byteCount;
    
                        while ((byteCount = resource.Stream.Read(bytes, 0, chunkSize)) > 0)
                        {
                            file.Write(bytes, 0, byteCount);
                        }
                    }
                }
            }
        }
    }
    
  10. App クラスのコンストラクターに CopyToIsolatedStorage メソッドへの呼び出しを追加します。

    // Copy media to isolated storage.
    CopyToIsolatedStorage();
    

AudioPlayerAgent は、ユーザーが別のフォアグラウンド アプリケーションに切り替えてもバックグラウンドで実行を続けるアプリケーションです。

オーディオ再生エージェントの実装

  1. ソリューション エクスプローラーで Agent プロジェクトの [AudioPlayer.cs] をダブルクリックして、ファイルをコード エディターで開きます。

  2. AudioPlayer.cs の先頭に、次の using ステートメントを追加します。

    using System.Collections.Generic;
    
  3. AudioPlayer.cs ファイルで、AudioPlayer クラスのクラス コード レベルで静的な整数を宣言します。この変数は、現在のトラック番号を保持します。

    // What's the current track?
    static int currentTrackNumber = 0;
    
  4. AudioPlayer.cs の AudioPlayer クラスに次のコードを追加することにより、トラックの静的なリストを作成します。

    // A playlist made up of AudioTrack items.
    private static List<AudioTrack> _playList = new List<AudioTrack>
    {
        new AudioTrack(new Uri("Kalimba.mp3", UriKind.Relative), 
                        "Kalimba", 
                        "Mr. Scruff", 
                        "Ninja Tuna", 
                        null),
    
        new AudioTrack(new Uri("Maid with the Flaxen Hair.mp3", UriKind.Relative), 
                        "Maid with the Flaxen Hair", 
                        "Richard Stoltzman", 
                        "Fine Music, Vol. 1", 
                        null),
    
        new AudioTrack(new Uri("Sleep Away.mp3", UriKind.Relative), 
                        "Sleep Away", 
                        "Bob Acri", 
                        "Bob Acri", 
                        null),
    
        // A remote URI
        new AudioTrack(new Uri("http://traffic.libsyn.com/wpradio/WPRadio_29.mp3", UriKind.Absolute), 
                        "Episode 29", 
                        "Windows Phone Radio", 
                        "Windows Phone Radio Podcast", 
                        null)
    };
    

    このリストはクラスのスコープで宣言されているため、エージェントへの呼び出しのたびに作成し直されることがないように、static と指定することが重要です。

  5. [play]、[next]、[previous] の各ボタンのクリックなど、ユーザー操作を処理するために、AudioPlayer.cs の AudioPlayer クラスに次の 3 つのメソッドを追加します。

    private void PlayNextTrack(BackgroundAudioPlayer player)
    {
        if (++currentTrackNumber >= _playList.Count)
        {
            currentTrackNumber = 0;
        }
    
        PlayTrack(player);
    }
    
    private void PlayPreviousTrack(BackgroundAudioPlayer player)
    {
        if (--currentTrackNumber < 0)
        {
            currentTrackNumber = _playList.Count - 1;
        }
    
        PlayTrack(player);
    }
    
    private void PlayTrack(BackgroundAudioPlayer player)
    {
        // Sets the track to play. When the TrackReady state is received, 
        // playback begins from the OnPlayStateChanged handler.
        player.Track = _playList[currentTrackNumber];
    }
    
  6. 再生状態の変化を処理するために、OnPlayStateChanged メソッド内の NotifyComplete への呼び出しの前に、次の switch ステートメントを追加します。

    switch (playState)
    {
      case PlayState.TrackReady:
        // The track to play is set in the PlayTrack method.
        player.Play();
        break;
    
      case PlayState.TrackEnded:
        PlayNextTrack(player);
        break;
    }
    
  7. ユーザー操作を処理するために、OnUserAction メソッド内の NotifyComplete への呼び出しの前に、次の switch ステートメントを追加します。

    switch (action)
    {
      case UserAction.Play:
        PlayTrack(player);
        break;
    
      case UserAction.Pause:
        player.Pause();
        break;
    
      case UserAction.SkipPrevious:
        PlayPreviousTrack(player);
        break;
    
      case UserAction.SkipNext:
        PlayNextTrack(player);
        break;
    }
    

バックグラウンドでオーディオを再生する非常に基本的なアプリケーションを実装するために必要なコードは、これですべてです。このアプリケーションはロック画面でも実行され、このアプリケーションからの再生は Universal Volume Control (UVC) で制御することもできます。当然、大幅に充実したユーザー インターフェイス、オーディオ ファイルに Web URI を使用するリモート ソースのオーディオ再生のサポートなど、これよりもより多くのものを実装することができます。また、ここでは停止、早送り、巻き戻し、シークといったユーザー操作のサポートも実装しませんでした。

表示: