【问题标题】:Play MP3 using Media with phonegap/Cordova使用带有 phonegap/Cordova 的媒体播放 MP3
【发布时间】:2012-06-03 10:38:53
【问题描述】:

我的问题:

我使用 Cordova 的媒体类。 MP3 文件只播放一次(第一次)。

代码:

将此代码添加到 Cordova Starter 项目以重现我的问题:

    var playCounter = 0;
    function playMP3(){
      console.log("playMP3() counter " + playCounter);
      var my_media = new Media("app/www/test.mp3");//ressource buildAction == content
      my_media.play();
      playCounter++;
    }
    [...]
    <p onclick="playMP3();">Click to Play MP3</p>

VS 输出:

[...]
GapBrowser_Navigated :: /app/www/index.html
'UI Task' (Managed): Loaded 'System.ServiceModel.Web.dll'
'UI Task' (Managed): Loaded 'System.ServiceModel.dll'
Log:"onDeviceReady. You should see this message in Visual Studio's output window."
'UI Task' (Managed): Loaded 'Microsoft.Xna.Framework.dll'
Log:"playMP3() counter 0"
'UI Task' (Managed): Loaded 'System.SR.dll'
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 1}"
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 2}"
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 2, \"value\": 2.141}"
Log:"media on status :: {\"id\": \"fa123123-bc55-a266-f447-8881bd32e2aa\", \"msg\": 1, \"value\": 4}"
Log:"playMP3() counter 1"
A first chance exception of type 'System.ArgumentException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll
A first chance exception of type 'System.IO.IsolatedStorage.IsolatedStorageException' occurred in mscorlib.dll
Log:"media on status :: {\"id\": \"2de3388c-bbb6-d896-9e27-660f1402bc2a\", \"msg\": 9, \"value\": 5}"

我的配置:

  • cordova-1.6.1.js
  • Lumia 800
  • WP 7.5 (7.10.7740.16)

解决方法(某种):

  • 停用应用程序(关闭屏幕)
  • 重新激活应用(打开屏幕)
  • -> 你再打一枪。

欢迎任何帮助,因为我从五月开始就被阻止了,而且我在任何地方都找不到有用的信息。

另外,你能告诉我这段代码是否适用于你的配置吗?

.

.

.

更新:添加演示代码,Cordova 1.8.0rc1

使用全局变量。使实例保持活动状态。

结果

  • test2.mp3 播放完毕,可以正常回放。
  • test.mp3 根本没有播放。
  • 这是您播放的第一个有效的文件。

代码

  function onDeviceReady()
  {
  document.getElementById("welcomeMsg").innerHTML += "Cordova is ready! version=" + window.device.cordova;
  console.log("onDeviceReady. You should see this message in Visual Studio's output window.");
  my_media = new Media("app/www/test.mp3");//ressource buildAction == content
  my_media2 = new Media("app/www/test2.mp3");//ressource buildAction == content
  }

  var playCounter = 0;
  var my_media = null;
  function playMP3(){
    console.log("playMP3() counter " + playCounter);
    my_media.play();
    playCounter++;
  }

  var my_media2 = null;
  function playMP32(){
    console.log("playMP32() counter " + playCounter);
    my_media2.play();
    playCounter++;
  }

</script>
[...]

<p onclick="playMP3();">Click to Play MP3</p>
<p onclick="playMP32();">Click to Play MP3 2</p>

VS 输出:

Log:"onDeviceReady. You should see this message in Visual Studio's output window."
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b
Log:"playMP32() counter 0"
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b
Log:"playMP32() counter 1"
Log:"playMP3() counter 2"
INFO: startPlayingAudio could not find mediaPlayer for b60fa266-d105-a295-a5be-fa2c6b824bc1
A first chance exception of type 'System.ArgumentException' occurred in System.Windows.dll
Error: El parámetro es incorrecto. 
Log:"playMP32() counter 3"
INFO: startPlayingAudio could not find mediaPlayer for 71888b14-86fe-4769-95c9-a9bb05d5555b

.

.

.

更新:Cordova 2.0.0

我用 2.0.0 的测试用例更新了 Apache 错误报告。

任何人都可以复制这个吗?

错误报告链接: https://issues.apache.org/jira/browse/CB-941

【问题讨论】:

  • 我尝试使用来自 GitHub 的最新版本 (1.8 rc1)。同样的问题。
  • 注意:问题与1.8相同,但错误不同。
  • 如果你关心这个问题,我把它报告给 Apache :issues.apache.org/jira/browse/CB-941

标签: windows-phone-7 cordova cordova-2.0.0


【解决方案1】:

我看到您在第二次单击时收到了 IsolatedStorageException,这让我认为该文件被第一个 Media 实例保持打开状态,这会阻止它再次被访问。

我建议确保您要么只为每个文件创建一个 Media 实例,要么先看看是否有办法处理旧实例。

这是我会尝试的(但我还没有测试过):

 var playCounter = 0;

 // moved my_media here so it won't be recreated
 var my_media = new Media("app/www/test.mp3");//ressource buildAction == content

    function playMP3(){
      console.log("playMP3() counter " + playCounter);
      my_media.play();
      playCounter++;
    }
    [...]
    <p onclick="playMP3();">Click to Play MP3</p>

【讨论】:

  • 不适用于 1.6.1。如果您只播放一个文件,请使用 1.8.0rc1。 (您不能使用其他 MEDIA 实例加载其他文件)。日志:System.Windows.dll 中发生了“System.ArgumentException”类型的第一次机会异常;错误:参数不正确。
  • 但是你能按问题多次按下按钮播放一个声音吗?播放多个不同的声音会使事情变得更加复杂,因为您说您不能一次拥有多个 Media 实例。在每个播放按钮开始时,您需要检查 my_media 是否为空,如果它不为空,则停止并可能释放(如@Onur_TOPAL 所说),然后创建一个新实例。反正这是我的猜测。
  • 让我们澄清一下:只有第一个要播放的文件才能工作(如果您保持实例处于活动状态,则可以多次播放)。如果您尝试播放其他文件(通过创建 MEDIA 的新实例),它将无法正常工作。 .release() .stop() 不能解决问题。
  • 您可能想提出一个新问题或更改此问题以反映您想要播放多种不同的声音。
  • 问题是关于一个 mp3,因为它是重现错误的最简单情况。显然,我的应用程序中有不止一个 mp3,我想不止一次地播放它们。也许我不清楚,我不会同时播放它们(混音器),而是一个接一个地播放(在 btn 点击时)。
【解决方案2】:

差点忘了……这对我有用。希望它有所帮助;-)

WP7.5/科尔多瓦 1.9.0

要求:据我所知,仅适用于 .wav 文件。我必须转换我的 .mp3 文件,因为它们会抛出丑陋的异常。

插件:C#:

namespace Cordova.Extension.Commands
{
    public class PGSoundFX : BaseCommand
    {
        public Dictionary <string, SoundEffect> fxSoundMap = new Dictionary<string,SoundEffect>();

    public enum FXType
    {
        Load=0,
        Play=1
    }

    [DataContract]
    public class FXOption
    {
        [DataMember]
        public string audioSrc;
        [DataMember]
        public string audioRef;
        [DataMember]
        public FXType fxType; 
    }

    public void groAudio(string options)
    {
        FrameworkDispatcher.Update(); 
        FXOption opts;

        opts = WP7CordovaClassLib.Cordova.JSON.JsonHelper.Deserialize<FXOption>(options);

        if (opts != null)
        {
            try
            {
                switch (opts.fxType)
                {
                    case FXType.Load:
                        loadSound(opts.audioSrc, opts.audioRef);
                        break;
                    case FXType.Play:
                        Dictionary<string, SoundEffect>.KeyCollection keyCol = fxSoundMap.Keys;
                        foreach (string tmp in keyCol)
                        {
                            if ((opts.audioRef).Equals(tmp))
                                playSound(fxSoundMap[tmp]);
                        }
                        break;
                }
            }
            catch
            {
                Debug.WriteLine("PGSoundFX: loadSound Error ... null parameter(s).");
            }
        }
    }

    /// <summary> 
    /// Loads a wav file into an XNA Framework SoundEffect. 
    /// </summary> 
    /// <param name="Sound">The SoundEffect to play.</param> 
    private void playSound(SoundEffect Sound)
    {
        Sound.Play();
        DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
    }

    /// <summary> 
    /// Loads a wav file into an XNA Framework SoundEffect. 
    /// </summary> 
    /// <param name="SoundFilePath">Relative path to the wav file.</param> 
    /// <param name="Sound">The SoundEffect to load the audio into.</param> 
    private void loadSound(String SoundFilePath, String SoundName)
    {
        if (fxSoundMap.Keys != null)
        {
            Dictionary<string, SoundEffect>.KeyCollection keyColl = fxSoundMap.Keys;
            foreach (string tmp in keyColl)
            {
                if (SoundName.Equals(tmp))
                    return;
            }
        }

        SoundEffect Sound = null;

        try
        {
            // Holds informations about a file stream. 
            StreamResourceInfo SoundFileInfo = Application.GetResourceStream(new Uri(SoundFilePath, UriKind.Relative));
            // Create the SoundEffect from the Stream 
            Sound = SoundEffect.FromStream(SoundFileInfo.Stream);
            fxSoundMap[SoundName] = Sound;
            DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
        }
        catch (NullReferenceException)
        {
            Debug.WriteLine("Couldn't load sound " + SoundFilePath);
        }
        } 
    }
}

Javascript:插件:

PhoneGap.addConstructor(function() {

navigator.plugins.pgSoundFX = 
{
    playSound:function(fxName)
    {
    var options = {"audioRef":fxName,"fxType":1};
    PhoneGap.exec(null, null, "PGSoundFX", "groAudio", options);
    },

    loadSound:function(fxSrc, fxName)
    {
    var options = {"audioSrc":fxSrc,"audioRef":fxName,"fxType":0};
    PhoneGap.exec(null, null, "PGSoundFX", "groAudio", options);
    }
}
});

Javascript:使用:

//NOTE: Allows you to pre-load sound effect files

//initialize pgSoundFX plugin
if (!navigator.plugins) {
    console.log("plugIns do not exist!");
    navigator.plugins = {};
}

navigator.plugins.pgSoundFX.loadSound("www/audio/file1.wav", "item1");
navigator.plugins.pgSoundFX.loadSound("www/audio/file2.wav", "item2");
navigator.plugins.pgSoundFX.loadSound("www/audio/file3.wav", "item3");
    :
    :

//NOTE: Play whenever needed
navigator.plugins.pgSoundFX.playSound("item1");

当然,您的文件位置(www/audio/)、名称(file1 等)和参考名称(item1 等)都是您想要的。与大多数人一样,有很多方法可以改进此代码……请随意。我的用例预加载了 5 个 .wav 文件,大小从 28k 到 364k 不等,并在整个用户游戏过程中播放。

【讨论】:

    【解决方案3】:

    我不确定这是不是正确的答案,因为我没有尝试过,但认为这是一次头脑风暴。

    首先使用var my_media = new Media(src, onSuccess, onError); ctor 创建您的音频,成功时播放它,出错时首先尝试使用media.release 代码释放它。

    如果您知道要发布的其他事件或动作会更合适。

    编辑:我刚刚注意到它,您没有将stop 用于媒体,您也可以在需要时尝试使用它,例如playMP3() 的开头如果媒体不为空,请先尝试停止它。

    干杯。

    【讨论】:

    • 感谢您的意见。我确实尝试调用 .stop 。在重新创建对象之前释放和“= null”:没有成功。
    • 如果您的代码仍然与您的问题中的相同(我的意思是媒体变量是本地的)这些函数将不起作用。您应该像奥斯汀的回答一样将其定义为全球性的。如果它仍然不能作为全局变量工作,我完全不知道。
    【解决方案4】:

    我认为问题可能在于 Silverlight 每页只允许一个媒体实例的限制......并且由于 PG/Cordova 本质上是一个单页 webBrowser 实例,它只能有一个媒体实例。我正在尝试构建一个 XNA SoundEffect 插件来解决这个问题。

    【讨论】:

    • 感谢您的回答。项目公开后不要忘记发布项目链接。
    【解决方案5】:

    是一个 Cordova 错误 https://issues.apache.org/jira/browse/CB-941

    由 purpulecabbage 在他的 gitHub 仓库中解决。请参阅对错误报告的评论。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多