Android使用MediaPlayer和TextureView实现视频无缝切换

需求描述

比如广告播放,每个视频15秒,视频之间切换的时候,性能不太好的机器可能会黑屏一段时间,体验不太好,接下来我们就是要解决这个黑屏问题。

解决方案

使用两个surfaceView方式,经过测试不行
使用一个MediaPlayer,在MediaPlayer上面加一层ImageView,每次播放完成后,获取视频的最后一帧的图像给ImageView,视频切换完成,ImageView隐藏,如此往复循环,可行

实践

1.获取视频流图片方式,通过MediaMetadataRetriever,测试发现,部分机器获取的Bitmap可能为空,无法解决,放弃

2.使用TextureView方式,可以获取当前帧的Bitmap,可行,下面贴代码

package com.winson.blog.video;

import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import java.io.IOException;

public class VideoFragment extends Fragment {

 public static final String TAG = VideoFragment.class.getSimpleName();

 String TEST_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/testmp4.mp4";
 int mIndex = 0;
 String path1 = TEST_PATH;
 String[] paths = new String[]{TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH, TEST_PATH};

 boolean destory;
 Handler mHandler;
 Runnable mPlayRun;
 FrameLayout content;
 TextureView textureView;
 ImageView frameImage;
 MediaPlayer mediaPlayer;
 Bitmap lastFrameBitmap;

 public void updateResources(String[] paths) {
 this.paths = paths;
 if(mHandler != null && mPlayRun!= null){
  mHandler.post(mPlayRun);
 }
 }

 @Override
 public void onCreate(@Nullable Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);

 mHandler = new Handler();
 mediaPlayer = new MediaPlayer();
 mPlayRun = new Runnable() {

  @Override
  public void run() {

  if (mediaPlayer == null || destory) {
   return;

  }
  mediaPlayer.pause();
  mediaPlayer.reset();

  try {
   String path = paths[mIndex % paths.length];
   mIndex++;

   mediaPlayer.setDataSource(getActivity(), Uri.parse(path));
   mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

   @Override
   public void onPrepared(MediaPlayer arg0) {
    mediaPlayer.start();
    frameImage.setVisibility(View.GONE);
   }
   });
   mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
   @Override
   public void onCompletion(MediaPlayer mp) {
    frameImage.setVisibility(View.VISIBLE);
    Bitmap currentFrameBitmap = textureView.getBitmap();
    frameImage.setImageBitmap(currentFrameBitmap);
    if (lastFrameBitmap != null) {
    lastFrameBitmap.recycle();
    }
    lastFrameBitmap = currentFrameBitmap;

    mHandler.post(mPlayRun);
   }
   });
   mediaPlayer.prepareAsync();

  } catch (Exception e) {
   e.printStackTrace();
  }
  }

 };
 }

 public void release() {
 mHandler.removeCallbacks(mPlayRun);
 if (mediaPlayer != null) {
  mediaPlayer.pause();
  mediaPlayer.release();
 }
 }

 public Bitmap getBitmap() {
 return textureView == null ? null : textureView.getBitmap();
 }

 @Override
 public void onDestroy() {
 super.onDestroy();
 release();
 }

 @Nullable
 @Override
 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 content = new FrameLayout(getActivity());

 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
 lp.gravity = Gravity.LEFT | Gravity.TOP;

 textureView = new TextureView(getActivity());
 textureView.setLayoutParams(lp);
 content.addView(textureView);

 frameImage = new ImageView(getActivity());
 frameImage.setScaleType(ImageView.ScaleType.FIT_XY);
 frameImage.setLayoutParams(lp);
 content.addView(frameImage);

 textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
  @Override
  public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
  Surface s = new Surface(surface);
  mediaPlayer.setSurface(s);

  }

  @Override
  public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
  }

  @Override
  public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
  return false;
  }

  @Override
  public void onSurfaceTextureUpdated(SurfaceTexture surface) {
  }
 });

 return content;
 }

 @Override
 public void onActivityCreated(@Nullable Bundle savedInstanceState) {
 super.onActivityCreated(savedInstanceState);

 testPlay();
 }

 public void testPlay() {
// mediaPlayer.pause();
// mediaPlayer.reset();
//
// try {
//  mediaPlayer.setDataSource(getActivity(), Uri.parse(TEST_PATH));
//  mediaPlayer.prepare();
//  mediaPlayer.start();
// } catch (IOException e) {
//  e.printStackTrace();
// }

 mHandler.post(mPlayRun);
 }

}

相关链接,github地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android 实现视频字幕Subtitle和横竖屏切换示例

    系统自带的VideoView有些视频格式不支持,那么我们可以用第三方实现的VideoView替代系统的来播放视频,比较流行的有ijkplayer.vitamio. 最近有个需求就是需要给视频添加字幕,其实也挺简单的.字幕比较常用的格式是srt,实际它就是文本,把它解析出来,然后根据时间再展示就OK.还有就是实现了即使旋转按钮关闭,根据方向感应器也能做到横竖屏切换. 本文用的是系统VideoView,然后播放sd卡中的视频来作为演示(源码中带有f2.mp4和f2.srt,运行时拷贝到sd卡就行).

  • android播放视频时在立体声与单声道之间切换无变化原因分析及解决

    部分客户客户使用第三方视频播放器,有立体声与单声道之间切换,发现切换后无作用 原因是由于在HAL层默认没有处理上层发的stereo 转mono的命令,所以会没有效果, 可按如下修改,添加相关处理: 1修改AudioMTKHardware.cpp 添加:static String8 keySetStereo2MonoMode = String8("EnableStereoOutput"); 2.修改status_t AudioMTKHardware::setParameters(cons

  • Android编程实现播放视频时切换全屏并隐藏状态栏的方法

    本文实例讲述了Android编程实现播放视频时切换全屏并隐藏状态栏的方法.分享给大家供大家参考,具体如下: 1. Demo示例: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (this.getResources().getConfiguration().ori

  • Android使用WebView实现全屏切换播放网页视频功能

    首先写布局文件activity_main.xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="fill_parent" and

  • Android使用MediaPlayer和TextureView实现视频无缝切换

    需求描述 比如广告播放,每个视频15秒,视频之间切换的时候,性能不太好的机器可能会黑屏一段时间,体验不太好,接下来我们就是要解决这个黑屏问题. 解决方案 使用两个surfaceView方式,经过测试不行 使用一个MediaPlayer,在MediaPlayer上面加一层ImageView,每次播放完成后,获取视频的最后一帧的图像给ImageView,视频切换完成,ImageView隐藏,如此往复循环,可行 实践 1.获取视频流图片方式,通过MediaMetadataRetriever,测试发现,

  • Android中使用TextureView播放视频

    如果你想显示一段在线视频或者任意的数据流比如视频或者OpenGL 场景,你可以用android中的SurfaceView或者TextureView做到. 1).TextureView的兄弟SurfaceView 应用程序的视频或者opengl内容往往是显示在一个特别的UI控件中:SurfaceView. SurfaceView的工作方式是创建一个置于应用窗口之后的新窗口.这种 方式的效率非常高,因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制

  • Android仿微信长按录制视频并播放功能

    本文实例为大家分享了Android仿微信长按录制视频并播放功能的具体代码,供大家参考,具体内容如下 一.点击按钮进行录制 首先要获取摄像拍照的权限和读取权限 <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <use

  • Android编程实现获取多媒体库视频、音频、图片的方法

    本文实例讲述了Android编程实现获取多媒体库视频.音频.图片的方法.分享给大家供大家参考,具体如下: 从媒体库中查找音频.视频.图片文件的相关信息,并获取视频.图片.专辑图片的缩略图 和一些文件操作 package com.uwatch.swconnectservice.util; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNot

  • android 仿QQ动态背景、视频背景的示例代码

    本文介绍了android 仿QQ动态背景.视频背景的示例代码,分享给大家,具体如下: 效果如下: 如上图类似效果图: 1, 自定义视频类 继承VideoView public class CustomVideoView extends VideoView { public CustomVideoView(Context context) { super(context); } public CustomVideoView(Context context, AttributeSet attrs)

  • Android中简单调用图片、视频、音频、录音和拍照的方法

    本文实例讲述了Android中简单调用图片.视频.音频.录音和拍照的方法.分享给大家供大家参考,具体如下: //选择图片 requestCode 返回的标识 Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT); //"android.intent.action.GET_CONTENT" innerIntent.setType(contentType); //查看类型 String IMAGE_UNSPECIFIED =

  • Android 使用mediaplayer播放res/raw文件夹中的音乐的实例

    Android 使用mediaplayer播放res/raw文件夹中的音乐的实例 (1)在res文件夹中新建一个文件夹重命名为raw,并且将要播放的音乐放到raw文件夹里面 (2)修改layout目录下的xml布局文件,添加3个按钮空间和一个文本控件,用于提示当前播放状态和 播放暂停 停止等功能.具体代码如下 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layou

  • Android实现调用摄像头拍照与视频功能

    应用场景: 在Android开发过程中,有时需要调用手机自身设备的功能,上篇文章主要侧重摄像头拍照功能的调用.本篇文章将综合实现拍照与视频的操作. 知识点介绍: 该部分请阅读 [Android 调用摄像头功能] 使用方式: 第一步: 新建一个Android项目CameraPhotoVedio,包含两个Activity: MainActivity.CameraActivity. 第二步: activity_main.xml <RelativeLayout xmlns:android="htt

  • Android WebView实现全屏播放视频

    目录 介绍 主要代码 介绍 最近项目开发中用到了WebView播放视频的功能,总结了开发中犯过的错误,这些错误在开发是及容易遇到的,所以我这里总结了一下,希望大家看到后不要再犯类似的错误,尽可能提高开发效率: 这个Demo我这里也参考了网上写的一个比较好的一个Demo,经过总结修改,写出来的. 主要代码 以下是相应代码: MainActivity: package com.androidwebviewdemo; import android.app.Activity; import androi

随机推荐