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

  1. <span style="font-size:14px;">package com.example.textureviewvideo;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.InputStream;  
  6. import java.io.OutputStream;  
  7.   
  8. import android.app.Activity;  
  9. import android.content.res.AssetManager;  
  10. import android.graphics.SurfaceTexture;  
  11. import android.media.AudioManager;  
  12. import android.media.MediaPlayer;  
  13. import android.media.MediaPlayer.OnPreparedListener;  
  14. import android.os.Bundle;  
  15. import android.os.Environment;  
  16. import android.util.Log;  
  17. import android.view.Surface;  
  18. import android.view.TextureView;  
  19. import android.view.View;  
  20. import android.view.TextureView.SurfaceTextureListener;  
  21. import android.widget.ImageView;  
  22.   
  23. public class MainActivity extends Activity implements SurfaceTextureListener{  
  24. //  private TextureView textureView;  
  25.     private MediaPlayer mMediaPlayer;  
  26.     private Surface surface;  
  27.       
  28.     private ImageView videoImage;  
  29.       
  30.     @Override  
  31.     protected void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.activity_main);  
  34.         TextureView textureView=(TextureView) findViewById(R.id.textureview);  
  35.         textureView.setSurfaceTextureListener(this);//设置监听函数  重写4个方法  
  36.           
  37. //      textureView=new TextureViewTest(this);  
  38. //      setContentView(textureView);  
  39.         videoImage=(ImageView) findViewById(R.id.video_image);  
  40.     }  
  41.       
  42.     @Override  
  43.     public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,int height) {  
  44.         System.out.println("onSurfaceTextureAvailable onSurfaceTextureAvailable");  
  45.         surface=new Surface(surfaceTexture);  
  46.         new PlayerVideo().start();//开启一个线程去播放视频  
  47.     }  
  48.     @Override  
  49.     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,int height) {  
  50.         System.out.println("onSurfaceTextureSizeChanged onSurfaceTextureSizeChanged");  
  51.     }  
  52.       
  53.     @Override  
  54.     public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {  
  55.         System.out.println("onSurfaceTextureDestroyed onSurfaceTextureDestroyed");  
  56.         surfaceTexture=null;  
  57.         surface=null;  
  58.         mMediaPlayer.stop();  
  59.         mMediaPlayer.release();  
  60.         return true;  
  61.     }  
  62.       
  63.     @Override  
  64.     public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {  
  65. //      System.out.println("onSurfaceTextureUpdated onSurfaceTextureUpdated");  
  66.     }  
  67.       
  68.     private class PlayerVideo extends Thread{  
  69.         @Override  
  70.         public void run(){  
  71.              try {  
  72.                   File file=new File(Environment.getExternalStorageDirectory()+"/ansen.mp4");  
  73.                   if(!file.exists()){//文件不存在  
  74.                       copyFile();  
  75.                   }  
  76.                   mMediaPlayer= new MediaPlayer();  
  77.                   mMediaPlayer.setDataSource(file.getAbsolutePath());   
  78.                   mMediaPlayer.setSurface(surface);  
  79.                   mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
  80.                   mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {  
  81.                     @Override  
  82.                     public void onPrepared(MediaPlayer mp){  
  83.                         videoImage.setVisibility(View.GONE);  
  84.                         mMediaPlayer.start();  
  85.                     }  
  86.                   });  
  87.                   mMediaPlayer.prepare();  
  88.               } catch (Exception e) {    
  89.                   e.printStackTrace();  
  90.               }  
  91.         }  
  92.     }  
  93.       
  94.     public interface PlayerController{  
  95.         public void play();  
  96.     }  
  97.       
  98.     /** 
  99.      * 如果sdcard没有文件就复制过去 
  100.      */  
  101.     private void copyFile() {  
  102.         AssetManager assetManager = this.getAssets();  
  103.         InputStream in = null;  
  104.         OutputStream out = null;  
  105.         try {  
  106.             in = assetManager.open("ansen.mp4");  
  107.             String newFileName = Environment.getExternalStorageDirectory()+"/ansen.mp4";  
  108.             out = new FileOutputStream(newFileName);  
  109.             byte[] buffer = new byte[1024];  
  110.             int read;  
  111.             while ((read = in.read(buffer)) != -1) {  
  112.                 out.write(buffer, 0, read);  
  113.             }  
  114.             in.close();  
  115.             in = null;  
  116.             out.flush();  
  117.             out.close();  
  118.             out = null;  
  119.         } catch (Exception e) {  
  120.             Log.e("tag", e.getMessage());  
  121.         }  
  122.     }  
  123. }</span>  

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



activity_main.xml布局文件

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <TextureView  
  7.         android:id="@+id/textureview"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"/>  
  10.       
  11.       
  12.     <ImageView  
  13.         android:id="@+id/video_image"  
  14.         android:layout_width="match_parent"  
  15.         android:layout_height="match_parent"  
  16.         android:src="@drawable/ic_launcher"/>  
  17. </RelativeLayout>  
放了一个TextureView跟一个ImageView   TextureView初始化显示ImageView... 当视频播放的时候隐藏ImageView,并且切换过去的时候不会出现黑屏。


3.效果图

   播放之前显示的图片:                                                  播放之后显示的图片:

                              


下载源码


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

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

推荐下自己创建的android QQ群:202928390 欢迎大家的加入.


目录
相关文章
|
3月前
|
编解码 前端开发 Android开发
Android经典实战之TextureView原理和高级用法
本文介绍了 `TextureView` 的原理和特点,包括其硬件加速渲染的优势及与其他视图叠加使用的灵活性,并提供了视频播放和自定义绘制的示例代码。通过合理管理生命周期和资源,`TextureView` 可实现高效流畅的图形和视频渲染。
247 12
|
4月前
|
编解码 开发工具 Android开发
Android平台RTSP|RTMP播放器如何实现TextureView渲染
本文介绍了在Android平台上使用TextureView进行RTSP和RTMP视频流渲染的技术背景和实现方法。TextureView相较于SurfaceView具备更高性能、更强功能性和更灵活的绘制方式等优势,但也有必须在硬件加速环境下运行和较高内存占用等局限。文中详细展示了如何在SmartPlayerV2工程中创建和配置TextureView,并通过代码示例解释了如何根据视频分辨率信息调整显示比例,以及处理TextureView的各种生命周期回调。此外,还列举了该播放器SDK支持的多项高级功能,如多实例播放、多种编码格式支持、硬解码能力等,旨在帮助开发者更好地理解和实现高性能的直播播放器。
|
5月前
|
Android开发 开发者
Android经典面试题之SurfaceView和TextureView有什么区别?
分享了`SurfaceView`和`TextureView`在Android中的角色。`SurfaceView`适于视频/游戏,独立窗口低延迟,但变换受限;`TextureView`支持复杂变换,视图层级中渲染,适合动画/视频特效,但性能略低。两者在性能、变换、使用和层级上有差异,开发者需按需选择。
86 1
|
Android开发 API
Android Camera2 拍照(二)——使用TextureView
原文:Android Camera2 拍照(二)——使用TextureView 上一篇博文简单介绍了使用Camera2 API拍摄照片,并使用SurfaceView作为预览界面。
2982 0
|
Android开发
Android TextureView &amp; MediaPlayer implements video media player
Android TextureView & MediaPlayer implements video media player code: import android.
1171 0
|
Android开发 数据格式 XML
基于Android TextureView与SurfaceTexture实现相机Camera拍照预览与保存照片
基于Android TextureView与SurfaceTexture实现相机Camera拍照预览与保存照片 写一个简单的例子,实现一个常见的开发功能:拍照功能。
2114 0
|
9天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
14天前
|
搜索推荐 Android开发 开发者
探索安卓开发中的自定义视图:打造个性化UI组件
【10月更文挑战第39天】在安卓开发的世界中,自定义视图是实现独特界面设计的关键。本文将引导你理解自定义视图的概念、创建流程,以及如何通过它们增强应用的用户体验。我们将从基础出发,逐步深入,最终让你能够自信地设计和实现专属的UI组件。
|
16天前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异和挑战
【10月更文挑战第37天】在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统扮演着主角。它们各自拥有独特的特性、优势以及面临的开发挑战。本文将深入探讨这两个平台在开发过程中的主要差异,从编程语言到用户界面设计,再到市场分布的不同影响,旨在为开发者提供一个全面的视角,帮助他们更好地理解并应对在不同平台上进行应用开发时可能遇到的难题和机遇。
|
18天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
【10月更文挑战第35天】在数字化时代,安卓应用的开发成为了一个热门话题。本文旨在通过浅显易懂的语言,带领初学者了解安卓开发的基础知识,同时为有一定经验的开发者提供进阶技巧。我们将一起探讨如何从零开始构建第一个安卓应用,并逐步深入到性能优化和高级功能的实现。无论你是编程新手还是希望提升技能的开发者,这篇文章都将为你提供有价值的指导和灵感。