使用TextureView和MediaPlayer播放视频黑屏问题

227 阅读3分钟

背景

使用TextureView和MediaPlayer播放视频,recycleView滑动显示,滑动到对应的视频页面,会先黑屏再播放视频,用户体验不好。

原因

TextureView 出现黑闪现象通常是因为在视频开始播放前,它的内容是空的。当视频开始渲染时,TextureView 从无内容状态切换到有内容状态,这个过程可能会导致短暂的黑屏。

解决方案

使用占位图: 在视频加载并准备播放前,使用一个静态的占位图。当视频开始播放的时候,再移除占位图。这可以通过在TextureView上层放置一个ImageView并在视频准备好时将其隐藏来实现。

// 设置OnInfoListener
holder.videoView.setOnInfoListener { mp, what, extra ->
if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
        // 视频开始渲染
        // 这里可以执行一些操作,例如隐藏加载指示器
        holder.imageView.visibility = View.GONE
true
    } else {
        false
    }
} 

media的监听方法源码:

/**
 * Interface definition of a callback to be invoked to communicate some
 * info and/or warning about the media or its playback.
 */
public interface OnInfoListener
{
    /**
     * Called to indicate an info or a warning.
     *
     * @param mp      the MediaPlayer the info pertains to.
     * @param what    the type of info or warning.
     * <ul>
     * <li>{@link #MEDIA_INFO_UNKNOWN}
     * <li>{@link #MEDIA_INFO_VIDEO_TRACK_LAGGING}
     * <li>{@link #MEDIA_INFO_VIDEO_RENDERING_START}
     * <li>{@link #MEDIA_INFO_BUFFERING_START}
     * <li>{@link #MEDIA_INFO_BUFFERING_END}
     * <li><code>MEDIA_INFO_NETWORK_BANDWIDTH (703)</code> -
     *     bandwidth information is available (as <code>extra</code> kbps)
     * <li>{@link #MEDIA_INFO_BAD_INTERLEAVING}
     * <li>{@link #MEDIA_INFO_NOT_SEEKABLE}
     * <li>{@link #MEDIA_INFO_METADATA_UPDATE}
     * <li>{@link #MEDIA_INFO_UNSUPPORTED_SUBTITLE}
     * <li>{@link #MEDIA_INFO_SUBTITLE_TIMED_OUT}
     * </ul>
     * @param extra an extra code, specific to the info. Typically
     * implementation dependent.
     * @return True if the method handled the info, false if it didn't.
     * Returning false, or not having an OnInfoListener at all, will
     * cause the info to be discarded.
     */
    boolean onInfo(MediaPlayer mp, int what, int extra);
}

这段代码定义了一个名为 OnInfoListener 的接口,它是一个回调接口,用于在媒体播放过程中传达一些信息或警告。这个接口通常在Android的 MediaPlayer 类中使用。当播放媒体时,MediaPlayer 可能会遇到各种事件和状态变化,OnInfoListener 允许开发者在这些情况发生时得到通知。

接口中的 onInfo 方法会在有信息或警告时被调用。这个方法有三个参数:

  1. mpMediaPlayer 对象,它是触发信息事件的媒体播放器。
  2. what:信息或警告的类型。这是一个整数值,代表不同的信息或警告。例如,MEDIA_INFO_VIDEO_RENDERING_START 表示视频开始渲染。
  3. extra:附加的整数值,提供有关信息的额外数据。这通常依赖于实现,不同的 what 类型可能会有不同的 extra 值。

onInfo 方法返回一个布尔值,表示是否处理了这个信息。如果返回 true,表示应用处理了这个信息。如果返回 false 或者没有设置 OnInfoListener,那么这个信息就会被丢弃。

下面是 what 参数可能包含的一些值的解释:

  • MEDIA_INFO_UNKNOWN:未知的信息或警告。
  • MEDIA_INFO_VIDEO_TRACK_LAGGING:视频跟踪落后,可能是因为处理不过来。
  • MEDIA_INFO_VIDEO_RENDERING_START:视频开始渲染,这可以用来处理视频播放开始的黑屏问题。
  • MEDIA_INFO_BUFFERING_START:开始缓冲,媒体播放器需要填充缓冲区。
  • MEDIA_INFO_BUFFERING_END:缓冲结束,缓冲区已填满,播放可以继续。
  • MEDIA_INFO_NETWORK_BANDWIDTH (703):网络带宽信息可用,extra 表示以kbps为单位的带宽。
  • MEDIA_INFO_BAD_INTERLEAVING:媒体文件的交错格式不佳,可能影响播放。
  • MEDIA_INFO_NOT_SEEKABLE:媒体不可寻址,不能跳转到指定的播放位置。
  • MEDIA_INFO_METADATA_UPDATE:元数据更新了。
  • MEDIA_INFO_UNSUPPORTED_SUBTITLE:不支持的字幕格式。
  • MEDIA_INFO_SUBTITLE_TIMED_OUT:字幕超时。