停止在三星设备上的科尔多瓦 webview 中无休止地缓冲 html5 视频

Posted

技术标签:

【中文标题】停止在三星设备上的科尔多瓦 webview 中无休止地缓冲 html5 视频【英文标题】:Stop endless buffering of html5 video in cordova webview on Samsung devices 【发布时间】:2014-03-06 23:58:03 【问题描述】:

我正在使用 Cordova (PhoneGap 3.0.0-0.14.4) 构建一个跨平台移动应用程序,并将 android 作为目标平台之一。 该应用程序的一个(主要但不仅是)部分功能是播放视频。 我选择了 html5 <video> 标签作为实现视频播放器的首选方法。 这些视频托管在 Vimeo 上。 该应用程序以单个 html 文档的形式实现,其中导航是通过使用 javascript 更改内容来实现的。

我使用的视频标签看起来像:

<video autoplay controls id="videotag">
    <source id="videosrc" src="http://player.vimeo.com/external/..."/>
    Din apparat stöder inte denna video.
</video>

只需将视频标签添加到 html 即可开箱即用地播放视频。 在 HTC One mini (Android 4.3) 上,这个解决方案没有问题。 在三星 Galaxy S4 mini (Android 4.2.2) 上,视频也会播放,但会出现另一个问题: 视频正在由 MediaPlayer 组件缓冲,并且这种缓冲永远不会停止。 日志由以下消息填充,无限重复:

01-25 13:45:36.698: V/MediaPlayer(2814): message received msg=3, ext1=34, ext2=0
01-25 13:45:36.698: V/MediaPlayer(2814): buffering 34 
01-25 13:45:36.698: V/MediaPlayer(2814): callback application
01-25 13:45:36.698: V/MediaPlayer(2814): back from callback

即使在播放停止、视频标签被移除并且用户退出(暂停)应用后,这种缓冲也会继续。 暂停应用程序不会停止缓冲,但会终止应用程序。 缓冲达到 100% 时甚至不会停止,而是显然无限期地继续。 没有声音在后台播放,但互联网连接保持打开状态,电池电量耗尽并且设备发热。 这对我们来说是个大问题,因为我们不愿意发布会导致过热的应用程序。

三星 Galaxy S3 的 Beta 测试人员也报告了与检测到的问题类似的症状。 该问题可能仅限于三星,因为它不会出现在 HTC 设备上。

即使不再需要视频,MediaPlayer 组件似乎也没有收到停止缓冲的消息。

我尝试了以下方法,但没有成功:

观看完毕后,我已将视频标签从 DOM 中完全移除。 我使用 javascript 通过调用 pause() 来停止播放 移除前的视频元素。 关注HTML5 Video: Force abort of buffering 我尝试使用 javscript 清除视频标签内的 src url,然后在视频标签上调用 load()。 根据对上述问题的评论,我尝试将视频标签放在 iframe 中,完成后会从 DOM 中删除 观看。 我已尝试将以上所有内容结合起来。 我曾尝试将视频标签放在一个单独的页面上,该页面被导航离开。这与 single-page-with-js 背道而驰 其他使用的模型。 我尝试过通过oEmbed使用Vimeo播放器,而不是直接使用html5视频标签。

这已经用尽了我能够找到的与平台无关的技巧。 有一些基于原生Android代码的方法

Stop Android MediaPlayer automatically launched by webpage within WebView 提供了一个潜在的解决方案,但根据问题作者的评论,接受的解决方案只会停止播放音频,但不会杀死 MediaPlayer。 Android WebView Playing HTML5/h.264/mp4 Video, How to get at the MediaPlayer 似乎是一个类似的问题,但使用自定义 web 视图而不是 cordova。我不知道如何尝试将其应用于科尔多瓦。

我正在寻找任何解决方案,以解决允许播放视频而不会导致过热的问题。 这应该是其他人需要解决的问题,所以希望有一个cordova插件已经解决了这个问题。 有这样的插件吗? 如果没有,上面提到的两种 Android 原生方法中的任何一种都可以在 cordova 中实现吗?它们能解决问题吗?

一个潜在的解决方法是在应用暂停时将其终止。 这很丑陋,不符合 Android 指南。 实现这一目标的最不丑陋的方法是什么?

【问题讨论】:

【参考方案1】:

在类似的事情上挣扎了一天多之后,我发现您可以通过将WebView 发送到带有 HTML5 视频标签和错误视频 URL 的页面来使 WebView 内的 MediaPlayer 崩溃。下面的示例是具有有效视频标签的主要活动。如果您按下播放键,MediaPlayer 将接管并开始永远运行...但是当您单击返回或主页并离开应用程序时,onPause() 被触发,WebView 被重定向到一个错误的页面视频网址并告诉自动播放。尝试玩游戏会使MediaPlayer 崩溃,瞧! MediaPlayer 已不复存在。

package com.test.webviewtest;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity 
    WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        webView = new WebView(this);
        webView.setWebChromeClient(new WebChromeClient());
        webView.setWebViewClient(new WebViewClient());
        String html = "<video width=\"320\" height=\"240\" controls>" +
                "<source src=\"http://www.w3schools.com/html/movie.mp4\" " +
                "type=\"video/mp4\"></video>";
        webView.loadData(html, "text/html", null);
        setContentView(webView);
    

    @Override
    protected void onPause()
        super.onPause();
        // attempt to kill the MediaPlayer here...
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient()
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon)
                String js = "javascript:document.getElementsByTagName('video')[0].play();";
                webView.loadUrl(js);
            
        );
        String html = "<video width=\"320\" height=\"240\" controls>" +
                "<source src=\"http://www.w3schools.com/html/" +
                "NOT_A_MOVIE.mp4" +
                "\" type=\"video/mp4\"></video>";
        webView.loadData(html, "text/html", null);
    

注意日志:

02-26 13:19:13.010    220-25370/? V/MediaPlayerService﹕ [607] notify (0x43a3aeb8, 100, 1, -1004)
02-26 13:19:13.010  25262-25274/com.test.webviewtest V/MediaPlayer﹕ message received msg=100, ext1=1, ext2=-1004
02-26 13:19:13.010  25262-25274/com.test.webviewtest E/MediaPlayer﹕ error (1, -1004)
02-26 13:19:13.010  25262-25274/com.test.webviewtest V/MediaPlayer﹕ callback application
02-26 13:19:13.020  25262-25274/com.test.webviewtest V/MediaPlayer﹕ back from callback
02-26 13:19:13.020  25262-25262/com.test.webviewtest E/MediaPlayer﹕ Error (1,-1004)

然后是没有更多MediaPlayer日志的幸福沉默......

更多讨论请见Android WebView HTML5 Video Spawns MediaPlayer that lives forever on Samsung S4 [Hacked answer found]。

【讨论】:

我可以确认这确实解决了三星设备上的问题,因此我接受您的回答。但是,您对自己的问题发表了评论:“它确实破坏了其他设备,因此这不是一个好的解决方案。在其他设备上(经过 Nexus 7 测试),此代码将使 WebView 对任何未来的调用都无用。”,所以我会要么继续寻找解决方案,要么将其作为三星特有的解决方案(呃,越来越丑……)

以上是关于停止在三星设备上的科尔多瓦 webview 中无休止地缓冲 html5 视频的主要内容,如果未能解决你的问题,请参考以下文章

Android 设备接收无休止的推送通知

如何检测屏幕截图事件并在科尔多瓦中停止它

JobIntentService 上的 IllegalArgumentException 主要在三星设备上

android中三星设备上的相机捕捉方向

某些三星设备上的编辑文本有限?

使用 MediaStore 存储图像会导致特定三星设备上的应用程序崩溃