【问题标题】:Cordova media plugin - stop streaming not working - release() freezes the deviceCordova 媒体插件 - 停止流式传输不起作用 - release() 冻结设备
【发布时间】:2017-04-30 21:54:16
【问题描述】:

我正在使用 cordova 6.4.0cordova-plugin-media 在 Android 应用程序中流式传输广播电台。不幸的是,有一种情况是应用程序不再正确响应。

假设用户想要流式传输广播电台,但在加载流时,他想中止它(例如因为流已关闭或加载时间很长)。

在这种情况下,我无法取消该过程!

media = new Media("http://direct.franceinfo.fr/live/franceinfo-midfi.mp3?ID=f9fbk29m84", mediaPlayerSuccess, mediaPlayerFail, mediaPlayerStatus);
media.play();

现在我想取消缓冲流的过程,但我做不到。功能:

media.pause();
media.stop();

在 ADB 日志中抛出错误消息并调用 mediaPlayer-onError 回调。

D/AudioPlayer( 3362): AudioPlayer Error: pausePlaying() called during invalid state: 1
...
D/AudioPlayer( 3362): AudioPlayer Error: stopPlaying() called during invalid state: 1

media.release() 命令停止加载流!然而,仅仅释放流而不停止它会导致其他相当大的问题:

如果您在媒体对象上调用media.release(),大多数情况下系统的反应非常缓慢并挂起几秒钟。但如果您经常这样做,系统会完全冻结。这意味着它不再接受远程控制命令。 Adb-log 仍在工作,但在这种情况下没有显示任何错误。只有电源按钮仍在工作(它锁定和解锁屏幕)。从这种搞砸的状态中恢复的唯一方法是重新启动设备。

如果媒体流尚未播放,我应该如何取消它?这是插件中的错误吗?

附加的是code-sn-p,我用它来处理媒体流逻辑。如上所述...它基本上可以工作,但如果您多次调用它,它会减慢甚至冻结设备。

function radioControl(action, media_src){
  //media_src is a webradio-streamurl.

  if(action == 'play') {

    // Initial Play
    if(media === null){
      mediaCreateObject(media_src);
    }

    // If we get PLAY but on antoher station
    else if(media.src != media_src){
      mediaReleaseRessources();
      mediaCreateObject(media_src);
    }

    //interrupt_timer = false;
    if(media === null){
      mediaCreateObject(media_src);
    }
    media.play();
  }
  else if (action === 'pause') {
    //If we get "pause", but it didn't even start yet
    if(media._duration == -1){
      mediaReleaseRessources();
    }
    else{
      media.pause();
    }
  }
}

function mediaCreateObject(media_src){
  media = new Media(media_src, mediaPlayerSuccess, mediaPlayerFail, mediaPlayerStatus);
}

function mediaReleaseRessources(){
  media.release();
}

【问题讨论】:

  • 这是离子 1 或 2 还是其他离子?
  • 没有离子,只有科尔多瓦6.4.0
  • @MichaelB 我觉得你得先调用 media.stop() 然后调用 media.release() 来释放资源。请试用
  • 正如我在问题中已经写过的......在媒体对象上调用media.stop(),尚未播放会导致以下错误:D/AudioPlayer( 3362): AudioPlayer Error: stopPlaying() called during invalid state: 1
  • @MichaelB 您是否尝试过像这样在停止和释放之前执行检查 - if (lastMedia != null && lastMedia.isPlaying()) ??

标签: android cordova cordova-media-plugin


【解决方案1】:

我发现这不是科尔多瓦问题,而是一个 8 岁 (!) android-bug,从未修复过。见这里:

https://code.google.com/p/android/issues/detail?id=959

重置或释放未使用的 MediaPlayer 时,MediaPlayer “崩溃”(使调用线程死锁)

基本上问题是:如果你尝试“释放”一个媒体对象没有播放(还),它会死锁调用线程,这会导致我在问题中提到的冻结。不幸的是,他们从未修复此错误,只是将其标记为“已过时”。在安卓 5.1.1 中。该错误显然仍然存在。也许他们在以后的版本中修复了它。


我为这个问题做了一个相当丑陋的解决方法,但它正在工作。基本上我所做的是: 我们将每个媒体对象保存在一个 javaScript 对象中。如果用户在它播放时停止它,我们可以停止并删除该对象。但如果它没有播放,我们将这个媒体对象留在这个 javaScript 对象media_objects = {}; 我们还将当前的active_media 流保存在一个变量中。

如果cordova 调用mediaPlayerStatusChange-callback,我们循环遍历media_objects 并检查“待处理”对象之一的状态现在是否已更改为“正在运行”。 - Cordova 只是调用 media-status-change-callback 而没有任何指示是什么媒体对象刚刚改变了状态。这是不幸的,所以我们必须检查一个未决的“过时”对象现在是否开始播放。如果是这样,我们可以停止并释放它。 (如果对象实际上正在播放,停止和释放按预期工作 - 只有当它没有播放时,才会导致崩溃)

function mediaPlayerStatusChange(status){
  mediaReleaseRessources();
  // handle status change....
  // ......
}

function mediaReleaseRessources(){

  for(var key in media_objects) {
    // We can only stop-and release an object, if it is playing
    // If an object started playing, the "_duration"-value is != -1
    if(key !== active_media && media_objects[key]._duration != -1) {
      media_objects[key].stop();
      media_objects[key].release();
      delete media_objects[key];
    }
  }
}

这个解决方案对我有用,但是我仍然对在 cordova 中处理多个媒体流的更好、更清洁的方法感兴趣。

【讨论】:

    猜你喜欢
    • 2017-08-05
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多