前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android中使用TextureView播放视频

Android中使用TextureView播放视频

作者头像
砸漏
发布2020-11-05 10:22:28
2.5K0
发布2020-11-05 10:22:28
举报
文章被收录于专栏:恩蓝脚本

如果你想显示一段在线视频或者任意的数据流比如视频或者OpenGL 场景,你可以用android中的SurfaceView或者TextureView做到。

1).TextureView的兄弟SurfaceView

应用程序的视频或者opengl内容往往是显示在一个特别的UI控件中:SurfaceView。

SurfaceView的工作方式是创建一个置于应用窗口之后的新窗口。这种 方式的效率非常高,因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者 是局部的刷新都会导致整个视图结构全部重绘一次,因此效率非常低下,不过满足普通应用界面的需求还是绰绰有余),但是SurfaceView也有一些非常 不便的限制。

因为SurfaceView的内容不在应用窗口上,所以不能使用变换(平移、缩放、旋转等)。也难以放在ListView或者ScrollView中,不能使用UI控件的一些特性比如View.setAlpha()。

2).Android 4.0中的TextureView。

为了解决这个问上面那个我们刚说到的问题Android 4.0中引入了TextureView;

TextureView与SurfaceView相比,TextureView并没有创建一个单独的Surface用来绘制,这使得它可以像一般的View一样执行一些变换操作,设置透明度等。

另外,Textureview必须在硬件加速开启的窗口中。

项目中碰到的问题:

1.之前用SurfaceView播放视频的时候,从图片切换到播放视频,会出现黑屏的现象。

2.SurfaceView灵活性没有TextureView好。

下面是实现源码,大家参考一下

MainActivity.java文件

代码语言:javascript
复制
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()); 
} 
} 
}

TextureView创建的时显示图片,然后初始化播放器,预加载视频,如果视频文件不存在,从assets下copy一份到sdcard目录下,视频加载完毕隐藏图片,我这边图片默认显示的是android项目自带的图片,你们可以根据需求显示想要的图片。

activity_main.xml布局文件

代码语言:javascript
复制
<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,并且切换过去的时候不会出现黑屏。

如果播放在线视频出现闪屏的问题,需要开启一个线程异步播放视频,然后再用handle延时隐藏图片。我用的是延时300毫秒

代码语言:javascript
复制
private void sendEmpryMessage(){ 
handler.sendEmptyMessageDelayed(0,300);//给主线程发送一个隐藏图片的消息 
} 

最终效果

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-09-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2).Android 4.0中的TextureView。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档