草庐IT

android - Cordova 媒体插件 - 停止流式传输不起作用 - release() 卡住设备

coder 2023-11-26 原文

我将 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(),大多数情况下系统 react 非常缓慢并会挂起几秒钟。但如果您经常这样做,系统就会完全死机。这意味着它不再接受远程控制命令。 Adb 日志仍在工作,但在这种情况下没有显示任何错误。只有电源按钮仍在工作(它锁定和解锁屏幕)。从这种搞砸状态中恢复的唯一方法是重启设备。

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

附件是我用来处理媒体流逻辑的代码 fragment 。如上所述...它基本上可以工作,但如果您多次调用它,它会减慢甚至卡住设备。

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();
}

最佳答案

我发现,这不是 cordova 问题,而是一个 8 岁 (!) android-bug,它从未得到修复。看这里:

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

MediaPlayer "crash" (deadlocks the calling thread) when resetting or releasing an unused MediaPlayer

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


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

如果 cordova 调用 mediaPlayerStatusChange - 回调,我们循环遍历 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 中处理多个媒体流的更好、更简洁的方法感兴趣。

关于android - Cordova 媒体插件 - 停止流式传输不起作用 - release() 卡住设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41161735/

有关android - Cordova 媒体插件 - 停止流式传输不起作用 - release() 卡住设备的更多相关文章

  1. 怎样用一台手机做自媒体? - 2

    其实做自媒体的成本并不高,入门只需要一部手机即可!在手机上找视频素材、使用手机剪辑视频、最后使用手机发布视频作品获得收益!方法并不难,今天这期内容就来给粉丝们分享一种小方法,每天稳定收益100-300,抓紧点赞收藏!1、找素材(1)使用手机拍摄自己喜欢的经典段落,使用程序把文案内容提取出来(2)也可以在豆瓣、知乎、微博等网站中找一些自己需要的文案素材(3)把文案进行润色修改,可以加入一些自己的观点(4)视频素材可以使用软件中自带的素材,也可以在素材网站中下载完整版的素材2、文案配音(1)把复制好的文案直接导入小程序中(2)调整音色、音调后一键合成音频即可(3)可以选择自己朗读配音,需要花一点时

  2. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  3. ruby - 使用 Ruby Daemons gem 检测停止 - 2

    我正在使用rubydaemongem。想知道如何向停止操作添加一些额外的步骤?希望我能检测到停止被调用,并向其添加一些额外的代码。任何人都知道我如何才能做到这一点? 最佳答案 查看守护程序gem代码,它似乎没有用于此目的的明显扩展点。但是,我想知道(在守护进程中)您是否可以捕获守护进程在发生“停止”时发送的KILL/TERM信号...?trap("TERM")do#executeyourextracodehereend或者你可以安装一个at_exit钩子(Hook):-at_exitdo#executeyourextracodehe

  4. ruby - 如何停止 jekyll 本地服务器 - 2

    我刚刚在本地设置了我的第一个Jekyll项目。我已经让服务器运行,但我忘了使用自动标志。所以现在我想停止服务器并使用标志重新启动。但是,在我启动服务器后的命令行中,我没有得到新的提示,所以我无法输入任何新命令。我不太习惯命令行,所以我真的很感激知道我应该做什么!我正在使用MacOSX和terminal.app,如果有区别的话! 最佳答案 psaux|grepjekyll|awk'{print$2}'|xargskill-9 关于ruby-如何停止jekyll本地服务器,我们在StackO

  5. ruby - 带有 header 的 Sinatra 流式响应 - 2

    我想通过Sinatra应用程序代理远程文件。这需要将带有header的HTTP响应从远程源流式传输回客户端,但我不知道如何在Net::HTTP#提供的block内使用流式API时设置响应header获取响应。例如,这不会设置响应头:get'/file'dostreamdo|out|uri=URI("http://manuals.info.apple.com/en/ipad_user_guide.pdf")Net::HTTP.get_response(uri)do|file|headers'Content-Type'=>file.header['Content-Type']file.re

  6. ruby - 使用 Ruby 将 HTTP GET 的响应主体流式传输到 HTTP POST - 2

    我正在尝试下载一个大文件,然后使用Ruby将该文件发布到REST端点。该文件可能非常大,即超过可以存储在内存中甚至磁盘上的临时文件中的容量。我一直在用Net::HTTP尝试这个,但我愿意接受任何其他库(rest-client等)的解决方案,只要他们做我想做的事情。这是我尝试过的:require'net/http'source_uri=URI("https://example.org/very_large_file")source_request=Net::HTTP::Get.new(source_uri)source_http=Net::HTTP.start(source_uri.ho

  7. ruby-on-rails - 将 Heroku 环境变量传输到 Docker 实例 - 2

    我在Heroku上构建了一个必须在Docker容器内运行的RoR应用程序。为此,我使用officialDockerfile.因为它在Heroku中很常见,所以我需要一些附加组件才能使这个应用程序完全运行。在生产中,变量DATABASE_URL在我的应用程序中可用。但是,如果我尝试其他一些使用环境变量(在我的例子中是Mailtrap)的加载项,变量不会在运行时复制到实例中。所以我的问题很简单:如何让docker实例在Heroku上执行时知道环境变量?您可能会问,我已经知道我们可以在docker-compose.yml中指定一个environment指令。我想避免这种情况,以便能够通过项目

  8. ruby-on-rails - EC2 实例在负载均衡器中停止服务 - 2

    我有一个EC2实例正在运行。我有一个负载均衡器,它与EC2实例相关联。PingTarget:HTTP:3001/healthCheckTimeout:5secondsInterval:24secondsUnhealthythreshold:2Healthythreshold:10现在该实例显示为OutofService。我什至尝试更改监听端口等等。一切正常,直到重新启动我的EC2实例。任何帮助将不胜感激。仅供引用:我有一个在端口3001上运行的Rails应用程序,我有一个用于HTTP:80(loadbalancer)到HTTP:3001的监听器。我还在终端中通过ssh检查了正在运行的应

  9. c - ruby的rb_raise如何停止调用它的c函数的执行? - 2

    如果你在C中将一个ruby​​方法写成一个使用rb_raise的函数,调用后的函数部分将不会被执行,程序将停止,你会认为rb_raise使用了exit()。但是如果你在ruby​​中拯救异常,比如:beginmethod_that_raises_an_exceptionrescueendputs'Youwilstillgethere.'ruby代码将继续,但您的函数将停止执行。rb_raise如何实现这一目标? 最佳答案 推测它使用了setjmp(在调用方法之前)和longjmp(在rb_raise中)。

  10. ruby - 停止分布式 Ruby 服务 - 2

    我有一个启动DRb服务的脚本,然后生成处理程序对象并通过DRb.thread.join等待。我希望脚本一直运行直到被明确杀死,所以我添加了trap"INT"doDRb.stop_serviceend在Ruby1.8下成功停止DRb服务并退出,但在1.9下似乎死锁(在OSX10.6.7上)。对该进程进行采样显示在semaphore_wait_signal_trap中有几个线程在旋转。我假设我在调用stop_service时做错了什么,但我不确定是什么。谁能给我任何关于如何正确处理它的指示? 最佳答案 好的,我想我已经找到了解决方案。如

随机推荐