热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在androidwebview的全屏上播放HTML5视频。-PlayingHTML5videoonfullscreeninandroidwebview

Well,Ivebeensearchingfewdaysalready,howtodisplayHTML5videoinfull-screenmodeonandroi

Well, I've been searching few days already, how to display HTML5 video in full-screen mode on android WebView.

好吧,我已经搜索了几天了,如何在android WebView的全屏模式下显示HTML5视频。

I managed to play HTML5 videos on my webview. Problems are arising when displaying video in fullscreen mode.

我设法在我的webview上播放HTML5的视频。在全屏模式显示视频时出现问题。

As I figured out, android has two ways of handling the

正如我所指出的,android有两种方式来处理 <视频> 标签:

  1. On android versions <= 2.3.3, the onShowCustomView method is fired, and I can have the VideoView instance, and set listeners when the video completes, set controllers etc. So far so good.

    在android版本的<= 2.3.3中,onShowCustomView方法被触发,我可以有视频视图实例,在视频完成时设置监听器,设置控制器等等。

  2. On ICS (and probably 3.0 and above), it looks like the

    在ICS(可能是3.0或以上)上,它看起来像 <视频> ,以不同的方式处理。当HTML5视频播放onShowCustomView不是被称为正常模式——它看起来像有一个内部业务WebView中播放视频,和所有的控件中定义的 <视频> 标记所示——我不能以任何方式访问它。实际上,如果视频在正常模式下播放,这是可以的,因为控制在那里并且正在工作。

That led me to the big problem: when displaying the video in full screen mode the onShowCustomView is being called - but on ICS the "view" parameter isn't an instance of VideoView.

这让我想到了一个大问题:当在全屏模式下显示视频时,onShowCustomView正在被调用,但在ICS上,“view”参数并不是VideoView的实例。

I managed to find out that the instance is of VideoSurfaceView, a private inner class of HTML5VideoFullScreen class. The only way we can access this inner-class is via reflection.

我设法找到了VideoSurfaceView的实例,它是HTML5VideoFullScreen类的一个私有内部类。我们可以通过反射来访问这个内部类。

After looking at GrepCode for this class, I learnt that unlike VideoView, the HTML5VideoFullScreen$VideoSurfaceView doesn't hold a MediaPlayer instance that I can listen to its events or access its controls. The only thing I can do is take this VideoSurfaceView as it is and put it inside a full-screen-layout without controlling it.

在查看了这个类的GrepCode之后,我了解到,与VideoView不同的是,HTML5VideoFullScreen$VideoSurfaceView不包含一个MediaPlayer实例,我可以侦听它的事件或访问它的控件。我能做的唯一一件事就是把这个VideoSurfaceView放到一个全屏幕布局中而不去控制它。

Bottom line - When displaying video in full-screen, I don't know when the video ends, its controls aren't shown - this is pretty sad. I can't get the trigger for closing the full-screen.

底线——当在全屏显示视频时,我不知道视频什么时候结束,它的控制没有显示出来——这是相当可悲的。我无法得到关闭全屏的触发器。

I tried few unsuccessful workarounds:

我尝试了几个不成功的方法:

  1. Reflection: I tried to reach the HTML5VideoFullScreen instance, which holds a MediaPlayer member, from the inner-class VideoSurfaceView. I didn't manage to get it, I'm not sure this is possible (ViewSurfaceView doesn't hold its owner's instance).

    反射:我试着访问了HTML5VideoFullScreen实例,它包含一个MediaPlayer成员,来自于内部类VideoSurfaceView。我没有得到它,我不确定这是可能的(ViewSurfaceView不保存它的所有者的实例)。

  2. Register for the video events via Javascript (onended, for example), and handle what I need back in JAVA via JavascriptInterface: I found this solution isn't reliable because while doing this I encountered another problem: the

    通过Javascript(例如onend)注册视频事件,并通过JavascriptInterface处理我在JAVA中需要的东西:我发现这个解决方案不可靠,因为在做这个过程时,我遇到了另一个问题:

I'm still searching for a solution, very little is written about this issue. Did anyone manage to solve it? Help would be much appreciated!

我还在寻找解决方案,关于这个问题的文章很少。有人能解决吗?非常感谢您的帮助!

VideoView class: Here (has MediaPlayer)

VideoView类:这里(有MediaPlayer)

HTML5VideoFullScreen$VideoSurfaceView class: Here (doesn't have MediaPlayer)

HTML5VideoFullScreen$VideoSurfaceView类:这里(没有MediaPlayer)

7 个解决方案

#1


157  

Edit 2014/10: by popular demand I'm maintaining and moving this to GitHub. Please check cprcrack/VideoEnabledWebView for the last version. Will keep this answer only for reference.

Edit 2014/01: improved example usage to include the nonVideoLayout, videoLayout, and videoLoading views, for those users requesting more example code for better understading.

编辑2014/01:改进的示例用法包括非视频播放、视频播放和视频播放视图,这些用户请求更多的示例代码,以便更好地理解。

Edit 2013/12: some bug fixes related to Sony Xperia devices compatibility, but which in fact affected all devices.

编辑2013/12:一些与索尼Xperia设备兼容性相关的bug修复,但实际上影响了所有设备。

Edit 2013/11: after the release of Android 4.4 KitKat (API level 19) with its new Chromium webview, I had to work hard again. Several improvements were made. You should update to this new version. I release this source under WTFPL. Donations are accepted (find Donate link at bottom).

编辑2013/11:Android 4.4 KitKat (API level 19)发布后,我不得不再次努力工作。了一些改进。您应该更新到这个新版本。我在WTFPL下释放这个源。捐赠被接受(在底部发现捐赠链接)。

Edit 2013/04: after 1 week of hard work, I finally have achieved everything I needed. I think this two generic classes that I have created can solve all you problems.

编辑2013/04:经过一周的辛苦工作,我终于实现了我所需要的一切。我认为我创建的这两个通用类可以解决您所有的问题。

VideoEnabledWebChromeClient can be used alone if you do not require the functionality that VideoEnabledWebView adds. But VideoEnabledWebView must always rely on a VideoEnabledWebChromeClient. Please read all the comments of the both classes carefully.

如果你不需要VideoEnabledWebView添加的功能,VideoEnabledWebChromeClient可以单独使用。但VideoEnabledWebView必须始终依赖于VideoEnabledWebChromeClient。请仔细阅读这两门课的所有评论。

VideoEnabledWebChromeClient class

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.webkit.WebChromeClient;
import android.widget.FrameLayout;

/**
 * This class serves as a WebChromeClient to be set to a WebView, allowing it to play video.
 * Video will play differently depending on target API level (in-line, fullscreen, or both).
 *
 * It has been tested with the following video classes:
 * - android.widget.VideoView (typically API level <11)
 * - android.webkit.HTML5VideoFullScreen$VideoSurfaceView/VideoTextureView (typically API level 11-18)
 * - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView (typically API level 19+)
 * 
 * Important notes:
 * - For API level 11+, android:hardwareAccelerated="true" must be set in the application manifest.
 * - The invoking activity must call VideoEnabledWebChromeClient's onBackPressed() inside of its own onBackPressed().
 * - Tested in Android API levels 8-19. Only tested on http://m.youtube.com.
 *
 * @author Cristian Perez (http://cpr.name)
 *
 */
public class VideoEnabledWebChromeClient extends WebChromeClient implements OnPreparedListener, OnCompletionListener, OnErrorListener
{
    public interface ToggledFullscreenCallback
    {
        public void toggledFullscreen(boolean fullscreen);
    }

    private View activityNonVideoView;
    private ViewGroup activityVideoView;
    private View loadingView;
    private VideoEnabledWebView webView;

    private boolean isVideoFullscreen; // Indicates if the video is being displayed using a custom view (typically full-screen)
    private FrameLayout videoViewContainer;
    private CustomViewCallback videoViewCallback;

    private ToggledFullscreenCallback toggledFullscreenCallback;

    /**
     * Never use this constructor alone.
     * This constructor allows this class to be defined as an inline inner class in which the user can override methods
     */
    @SuppressWarnings("unused")
    public VideoEnabledWebChromeClient()
    {
    }

    /**
     * Builds a video enabled WebChromeClient.
     * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.
     * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.
     */
    @SuppressWarnings("unused")
    public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView)
    {
        this.activityNOnVideoView= activityNonVideoView;
        this.activityVideoView = activityVideoView;
        this.loadingView = null;
        this.webView = null;
        this.isVideoFullscreen = false;
    }

    /**
     * Builds a video enabled WebChromeClient.
     * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.
     * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.
     * @param loadingView A View to be shown while the video is loading (typically only used in API level <11). Must be already inflated and without a parent view.
     */
    @SuppressWarnings("unused")
    public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView, View loadingView)
    {
        this.activityNOnVideoView= activityNonVideoView;
        this.activityVideoView = activityVideoView;
        this.loadingView = loadingView;
        this.webView = null;
        this.isVideoFullscreen = false;
    }

    /**
     * Builds a video enabled WebChromeClient.
     * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.
     * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.
     * @param loadingView A View to be shown while the video is loading (typically only used in API level <11). Must be already inflated and without a parent view.
     * @param webView The owner VideoEnabledWebView. Passing it will enable the VideoEnabledWebChromeClient to detect the HTML5 video ended event and exit full-screen.
     * Note: The web page must only contain one video tag in order for the HTML5 video ended event to work. This could be improved if needed (see Javascript code).
     */
    public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView, View loadingView, VideoEnabledWebView webView)
    {
        this.activityNOnVideoView= activityNonVideoView;
        this.activityVideoView = activityVideoView;
        this.loadingView = loadingView;
        this.webView = webView;
        this.isVideoFullscreen = false;
    }

    /**
     * Indicates if the video is being displayed using a custom view (typically full-screen)
     * @return true it the video is being displayed using a custom view (typically full-screen)
     */
    public boolean isVideoFullscreen()
    {
        return isVideoFullscreen;
    }

    /**
     * Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)
     * @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback
     */
    public void setOnToggledFullscreen(ToggledFullscreenCallback callback)
    {
        this.toggledFullscreenCallback = callback;
    }

    @Override
    public void onShowCustomView(View view, CustomViewCallback callback)
    {
        if (view instanceof FrameLayout)
        {
            // A video wants to be shown
            FrameLayout frameLayout = (FrameLayout) view;
            View focusedChild = frameLayout.getFocusedChild();

            // Save video related variables
            this.isVideoFullscreen = true;
            this.videoViewCOntainer= frameLayout;
            this.videoViewCallback = callback;

            // Hide the non-video view, add the video view, and show it
            activityNonVideoView.setVisibility(View.INVISIBLE);
            activityVideoView.addView(videoViewContainer, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            activityVideoView.setVisibility(View.VISIBLE);

            if (focusedChild instanceof android.widget.VideoView)
            {
                // android.widget.VideoView (typically API level <11)
                android.widget.VideoView videoView = (android.widget.VideoView) focusedChild;

                // Handle all the required events
                videoView.setOnPreparedListener(this);
                videoView.setOnCompletionListener(this);        
推荐阅读
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本章将深入探讨移动 UI 设计的核心原则,帮助开发者构建简洁、高效且用户友好的界面。通过学习设计规则和用户体验优化技巧,您将能够创建出既美观又实用的移动应用。 ... [详细]
  • 本文详细探讨了JDBC(Java数据库连接)的内部机制,重点分析其作为服务提供者接口(SPI)框架的应用。通过类图和代码示例,展示了JDBC如何注册驱动程序、建立数据库连接以及执行SQL查询的过程。 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
  • 中科院学位论文排版指南
    随着毕业季的到来,许多即将毕业的学生开始撰写学位论文。本文介绍了使用LaTeX排版学位论文的方法,特别是针对中国科学院大学研究生学位论文撰写规范指导意见的最新要求。LaTeX以其精确的控制和美观的排版效果成为许多学者的首选。 ... [详细]
  • 本文探讨了在Django项目中,如何在对象详情页面添加前后导航链接,以提升用户体验。文章详细描述了遇到的问题及解决方案。 ... [详细]
  • Google排名优化-面向Google(Search Engine Friendly)的URL设计 ... [详细]
  • andr ... [详细]
  • 本文详细介绍了 com.facebook.drawee.view.SimpleDraweeView 中的 setScaleType 方法,提供了多个实际代码示例,并解释了其在不同场景下的应用。 ... [详细]
  • 基因组浏览器中的Wig格式解析
    本文详细介绍了Wiggle(Wig)格式及其在基因组浏览器中的应用,涵盖variableStep和fixedStep两种主要格式的特点、适用场景及具体使用方法。同时,还提供了关于数据值和自定义参数的补充信息。 ... [详细]
  • 本文介绍如何使用Python进行文本处理,包括分词和生成词云图。通过整合多个文本文件、去除停用词并生成词云图,展示文本数据的可视化分析方法。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
  • 在现代Web应用中,当用户滚动到页面底部时,自动加载更多内容的功能变得越来越普遍。这种无刷新加载技术不仅提升了用户体验,还优化了页面性能。本文将探讨如何实现这一功能,并介绍一些实际应用案例。 ... [详细]
author-avatar
moses_945_5e245a
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有