Windows Phone で XNA.Framework で効果音を鳴らす時の注意


環境 Windows Phone 7

5.1 .2 Application Reliability (InvalidOperation Exception) でリジェクトされましたので、その原因と対策をさらしておきます。

症状

XNA Framework で効果音を使用していた。音楽を連続再生している状態で、アプリケーションを実行していると、InvalidOperation Exception で落ちる。

原因

Windows Phone で、XNA Framework を使うと、次のような感じで簡単に効果音を鳴らすことができます。

soundPath = "sounds/abc.wav";
var soundUri = App.GetResourceStream(new Uri(soundPath, UriKind.Relative));
var sound = SoundEffect.FromStream(soundUri .Stream);
SoundEffect.MasterVolume = (float)…settings.SoundVolume;
var mySoundInstance = sound .CreateInstance();
mySoundInstance.Play();

音楽を再生した状態で、しばらくすると、次の例外メッセージで、InvalidOperation でクラッシュします。

注意しなければならないのが、音楽を再生状態で、アプリを起動しないと、クラッシュしません(たぶん)。

例外メッセージ
FrameworkDispatcher.Update has not been called. Regular FrameworkDispatcher.Update calls are necessary for fire and forget sound effects and framework events to function correctly. See http://go.microsoft.com/fwlink/?LinkId=193853 for details.

なぜテストで見つからなかったか

テストケース漏れ。

音楽再生中でないと、例外が発生しない可能性があります。また、例外発生まで、多少の時間がかかる場合があるようです。このため、音楽の再生、停止を繰り返しながら、ある程度の時間アプリを操作し続けるというテストが必要だとおもいます。

いつもは、Walkman やPCで音楽を聴いていたので、Windows Phone で音楽を聴きながら、アプリを操作するというテストケースが、完全に頭から抜けていました。

Windows Phone の審査では、音楽を再生中に、アプリケーションが勝手に音楽再生を停止しないという基準がありますが、そのテストケースに加えて、音楽の連続再生中に、ある程度の時間アプリを操作するというテストケースも必要です。

対策

Windows Phone アプリケーションでの XNA Framework イベントの有効化

にあるように、Game クラスを実装していないアプリケーション
(たとえば Silverlight アプリケーション モデルを使用する Windows Phone アプリケーション、具体的には上記効果音を鳴らすだけのために XNA を呼んだ場合)から、
XNA Framework を使用する場合は、自身で FrameworkDispatcher.Update メソッドを呼び出して、XNA Framework メッセージ キュー内にあるメッセージをディスパッチする必要があります。

具体的には、次の App.xaml に、

xmlns:s="clr-namespace:MyAppNameSpace;assembly=MyAppNameSpace"


<Application.ApplicationLifetimeObjects>
    <!–アプリケーションのライフタイム イベントを処理する必須オブジェクト–>
    <shell:PhoneApplicationService
        Launching="Application_Launching" Closing="Application_Closing"
        Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    <s:XNAFrameworkDispatcherService />
</Application.ApplicationLifetimeObjects>

次の XNAUpdate.cs を追加。MyAPpNameSpace は、プロジェクトに合わせて変更。

using System;
using System.Windows;
using System.Windows.Threading;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework;

namespace MyAppNameSpace
{
    public class XNAFrameworkDispatcherService : IApplicationService
    {
        private DispatcherTimer frameworkDispatcherTimer;

        public XNAFrameworkDispatcherService()
        {
            this.frameworkDispatcherTimer = new DispatcherTimer();
            this.frameworkDispatcherTimer.Interval = TimeSpan.FromTicks(333333);
            this.frameworkDispatcherTimer.Tick += frameworkDispatcherTimer_Tick;
            FrameworkDispatcher.Update();
        }

        void frameworkDispatcherTimer_Tick(object sender, EventArgs e) { FrameworkDispatcher.Update(); }

        void IApplicationService.StartService(ApplicationServiceContext context)
        {
            this.frameworkDispatcherTimer.Start();
        }

        void IApplicationService.StopService()
        {
            this.frameworkDispatcherTimer.Stop();
        }

    }
}

参考

あと、Zuneで接続しているときには、写真や音楽系のデバッグができませんが、その回避方法など。

秋コン:実質5行で作るMusicPlayer

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中


%d人のブロガーが「いいね」をつけました。