Android使用TextureView播放视频
Posted 安辉就是我
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android使用TextureView播放视频相关的知识,希望对你有一定的参考价值。
1.引言
如果你想显示一段在线视频或者任意的数据流比如视频或者OpenGL 场景,你可以用android中的TextureView做到。
1).TextureView的兄弟SurfaceView
应用程序的视频或者opengl内容往往是显示在一个特别的UI控件中:SurfaceView。SurfaceView的工作方式是创建一个置于应用窗口之后的新窗口。这种 方式的效率非常高,因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者 是局部的刷新都会导致整个视图结构全部重绘一次,因此效率非常低下,不过满足普通应用界面的需求还是绰绰有余),但是SurfaceView也有一些非常 不便的限制。
因为SurfaceView的内容不在应用窗口上,所以不能使用变换(平移、缩放、旋转等)。也难以放在ListView或者ScrollView中,不能使用UI控件的一些特性比如View.setAlpha()
。
2).为了解决这个问题 Android 4.0中引入了TextureView。
TextureView与SurfaceView相比,TextureView并没有创建一个单独的Surface用来绘制,这使得它可以像一般的View一样执行一些变换操作,设置透明度等。另外,Textureview必须在硬件加速开启的窗口中。
项目中碰到的问题:1.之前用SurfaceView播放视频的时候,从图片切换到播放视频,会出现黑屏的现象。
2.SurfaceView灵活性没有TextureView好。
2.项目源码
MainActivity.java文件
<span style="font-size:14px;">package com.example.textureviewvideo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.content.res.AssetManager;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.TextureView.SurfaceTextureListener;
import android.widget.ImageView;
public class MainActivity extends Activity implements SurfaceTextureListener
// private TextureView textureView;
private MediaPlayer mMediaPlayer;
private Surface surface;
private ImageView videoImage;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextureView textureView=(TextureView) findViewById(R.id.textureview);
textureView.setSurfaceTextureListener(this);//设置监听函数 重写4个方法
// textureView=new TextureViewTest(this);
// setContentView(textureView);
videoImage=(ImageView) findViewById(R.id.video_image);
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,int height)
System.out.println("onSurfaceTextureAvailable onSurfaceTextureAvailable");
surface=new Surface(surfaceTexture);
new PlayerVideo().start();//开启一个线程去播放视频
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,int height)
System.out.println("onSurfaceTextureSizeChanged onSurfaceTextureSizeChanged");
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture)
System.out.println("onSurfaceTextureDestroyed onSurfaceTextureDestroyed");
surfaceTexture=null;
surface=null;
mMediaPlayer.stop();
mMediaPlayer.release();
return true;
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture)
// System.out.println("onSurfaceTextureUpdated onSurfaceTextureUpdated");
private class PlayerVideo extends Thread
@Override
public void run()
try
File file=new File(Environment.getExternalStorageDirectory()+"/ansen.mp4");
if(!file.exists())//文件不存在
copyFile();
mMediaPlayer= new MediaPlayer();
mMediaPlayer.setDataSource(file.getAbsolutePath());
mMediaPlayer.setSurface(surface);
mMediaPlayer.setAudiostreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnPreparedListener(new OnPreparedListener()
@Override
public void onPrepared(MediaPlayer mp)
videoImage.setVisibility(View.GONE);
mMediaPlayer.start();
);
mMediaPlayer.prepare();
catch (Exception e)
e.printStackTrace();
public interface PlayerController
public void play();
/**
* 如果sdcard没有文件就复制过去
*/
private void copyFile()
AssetManager assetManager = this.getAssets();
InputStream in = null;
OutputStream out = null;
try
in = assetManager.open("ansen.mp4");
String newFileName = Environment.getExternalStorageDirectory()+"/ansen.mp4";
out = new FileOutputStream(newFileName);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1)
out.write(buffer, 0, read);
in.close();
in = null;
out.flush();
out.close();
out = null;
catch (Exception e)
Log.e("tag", e.getMessage());
</span>
TextureView创建的时显示图片,然后初始化播放器,预加载视频,如果视频文件不存在,从assets下copy一份到sdcard目录下,视频加载完毕隐藏图片,我这边图片默认显示的是android项目自带的图片,你们可以根据需求显示想要的图片。
activity_main.xml布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextureView
android:id="@+id/textureview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/video_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_launcher"/>
</RelativeLayout>
放了一个TextureView跟一个ImageView
TextureView初始化显示ImageView...当视频播放的时候隐藏ImageView,并且切换过去的时候不会出现黑屏。
3.效果图
其他问题:如果播放在线视频出现闪屏的问题,需要开启一个线程异步播放视频,然后再用handle延时隐藏图片。我用的是延时300毫秒
private void sendEmpryMessage()
handler.sendEmptyMessageDelayed(0,300);//给主线程发送一个隐藏图片的消息
推荐下自己创建的android QQ群:202928390 欢迎大家的加入.
推荐一个Android开发者必关注公众号,每周都有原创干货
以上是关于Android使用TextureView播放视频的主要内容,如果未能解决你的问题,请参考以下文章
TextureView/SurfaceView/GLSurfaceView/VideoView渲染视频(点播播放器)