Android中使用TextureView播放視頻
如果你想顯示一段在線視頻或者任意的數(shù)據(jù)流比如視頻或者OpenGL 場景,你可以用android中的SurfaceView或者TextureView做到。
1).TextureView的兄弟SurfaceView
應(yīng)用程序的視頻或者opengl內(nèi)容往往是顯示在一個特別的UI控件中:SurfaceView。
SurfaceView的工作方式是創(chuàng)建一個置于應(yīng)用窗口之后的新窗口。這種 方式的效率非常高,因為SurfaceView窗口刷新的時候不需要重繪應(yīng)用程序的窗口(android普通窗口的視圖繪制機(jī)制是一層一層的,任何一個子元素或者 是局部的刷新都會導(dǎo)致整個視圖結(jié)構(gòu)全部重繪一次,因此效率非常低下,不過滿足普通應(yīng)用界面的需求還是綽綽有余),但是SurfaceView也有一些非常 不便的限制。
因為SurfaceView的內(nèi)容不在應(yīng)用窗口上,所以不能使用變換(平移、縮放、旋轉(zhuǎn)等)。也難以放在ListView或者ScrollView中,不能使用UI控件的一些特性比如View.setAlpha()。
2).Android 4.0中的TextureView。
為了解決這個問上面那個我們剛說到的問題Android 4.0中引入了TextureView;
TextureView與SurfaceView相比,TextureView并沒有創(chuàng)建一個單獨(dú)的Surface用來繪制,這使得它可以像一般的View一樣執(zhí)行一些變換操作,設(shè)置透明度等。
另外,Textureview必須在硬件加速開啟的窗口中。
項目中碰到的問題:
1.之前用SurfaceView播放視頻的時候,從圖片切換到播放視頻,會出現(xiàn)黑屏的現(xiàn)象。
2.SurfaceView靈活性沒有TextureView好。
下面是實現(xiàn)源碼,大家參考一下
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);//設(shè)置監(jiān)聽函數(shù) 重寫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沒有文件就復(fù)制過去 */ 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創(chuàng)建的時顯示圖片,然后初始化播放器,預(yù)加載視頻,如果視頻文件不存在,從assets下copy一份到sdcard目錄下,視頻加載完畢隱藏圖片,我這邊圖片默認(rèn)顯示的是android項目自帶的圖片,你們可以根據(jù)需求顯示想要的圖片。
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...當(dāng)視頻播放的時候隱藏ImageView,并且切換過去的時候不會出現(xiàn)黑屏。
如果播放在線視頻出現(xiàn)閃屏的問題,需要開啟一個線程異步播放視頻,然后再用handle延時隱藏圖片。我用的是延時300毫秒
private void sendEmpryMessage(){ handler.sendEmptyMessageDelayed(0,300);//給主線程發(fā)送一個隱藏圖片的消息 }
最終效果
- Android中TextureView與SurfaceView用法區(qū)別總結(jié)
- Android使用MediaPlayer和TextureView實現(xiàn)視頻無縫切換
- Android OpenGL入門之GLSurfaceView
- Android中SurfaceView和普通view的區(qū)別及使用
- Android SurfaceView基礎(chǔ)用法詳解
- Android 2d游戲開發(fā)之貪吃蛇基于surfaceview
- Android中SurfaceTexture TextureView SurfaceView GLSurfaceView的區(qū)別
- Android?中TextureView和SurfaceView的屬性方法及示例說明
相關(guān)文章
Android自定義View實現(xiàn)圓形進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Android自定義View實現(xiàn)圓形進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-10-10Android實現(xiàn)自定義帶文字和圖片Button的方法
這篇文章主要介紹了Android實現(xiàn)自定義帶文字和圖片Button的方法,涉及Android針對Button按鈕的布局與設(shè)計技巧,需要的朋友可以參考下2015-05-05Android中設(shè)置RadioButton在文字右邊的方法實例
這篇文章主要介紹了Android中設(shè)置RadioButton在文字右邊的方法實例,本文直接給出XML配置實現(xiàn)代碼,需要的朋友可以參考下2015-04-04Android程序開發(fā)之動態(tài)設(shè)置ImageView的亮度
這篇文章主要介紹了Android程序開發(fā)之動態(tài)設(shè)置ImageView的亮度 的相關(guān)資料,需要的朋友可以參考下2016-01-01基于linux與windows平臺下 如何下載android sdk源代碼的方法詳解
本文主要是介紹在linux和windows平臺下,如何下載android sdk的源代碼,注意是sdk的源代碼,而不是android的所有源代碼,同時介紹如何把sdk源代碼加入到eclipse里,使android 平臺手機(jī)開發(fā)者可以直接查看源代碼,通過閱讀SDK源碼,能更好的理解和運(yùn)用Android的API2013-05-05