首页 > 系统 > Android > 正文

Android中使用TextureView播放视频

2019-10-22 18:13:15
字体:
来源:转载
供稿:网友

如果你想显示一段在线视频或者任意的数据流比如视频或者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文件

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布局文件

<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毫秒

private void sendEmpryMessage(){   handler.sendEmptyMessageDelayed(0,300);//给主线程发送一个隐藏图片的消息 } 

最终效果

Android,TextureView,播放视频

Demo源码下载


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表