TextureView SurfaceView 简介 案例

Posted 白乾涛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TextureView SurfaceView 简介 案例相关的知识,希望对你有一定的参考价值。

简介

android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次,因此效率相对较低。视频或者opengl内容往往是显示在SurfaceView中的,SurfaceView的工作方式是:创建一个置于应用窗口之后的新窗口。因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口,所以这种方式的效率非常高。

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

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

TextureView的使用非常简单,你唯一要做的就是获取用于渲染内容的SurfaceTexture。
Textureview必须在硬件加速开启的窗口中。

官方文档

Class Overview
A TextureView can be used to display a content stream. Such a content stream can for instance be a video or an OpenGL scene场景. The content stream can come from the application‘s process as well as a remote远程 process.

TextureView can only be used in a hardware accelerated硬件加速 window. When rendered in呈现在 software, TextureView will draw nothing.

Unlike SurfaceView, TextureView does not create a separate单独的 window but behaves as a regular像平常的 View. This key核心的 difference allows a TextureView to be moved, transformed, animated动画, etc. For instance, you can make a TextureView semi-translucent半透明 by calling myView.setAlpha(0.5f).

Using a TextureView is simple: all you need to do is get its SurfaceTexture. The SurfaceTexture can then be used to render展示 content. The following example demonstrates how to render the camera preview into a TextureView:

A TextureView‘s SurfaceTexture can be obtained获得 either by invoking引用 getSurfaceTexture() or by using a TextureView.SurfaceTextureListener. It is important to know that a SurfaceTexture is available only after the TextureView is attached to a window (and onAttachedToWindow() has been invoked.) It is therefore highly recommended推荐 you use a listener to be notified when the SurfaceTexture becomes available.

It is important to note that only one producer制片人 can use the TextureView. For instance, if you use a TextureView to display the camera preview, you cannot use lockCanvas() to draw onto the TextureView at the same time.

使用TextureView和MediaPlayer播放视频

/**
 * Desc:演示使用TextureView和MediaPlayer播放视频
 *
 * @author 白乾涛 <p>
 * @tag TextureView<p>
 * @date 2018/5/22 23:56 <p>
 */
public class TextureViewTestActivity extends Activity implements TextureView.SurfaceTextureListener {
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//取消状态栏
        TextureView textureView = new TextureView(this);
        textureView.setSurfaceTextureListener(this);
        textureView.setRotation(45.0f);//可以像普通View一样使用平移、缩放、旋转等变换操作
        textureView.setAlpha(0.5f);
        setContentView(textureView);
    }
    
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Log.i("bqt", "onSurfaceTextureAvailable");// SurfaceTexture准备就绪
        if (new Random().nextBoolean()) {
            String path = "http://ozvd186ua.bkt.clouddn.com/douyin.mp4";
            MediaPlayerManager.getInstance().playUrlMedia(new Surface(surface), path);
        } else {
            try {
                MediaPlayerManager.getInstance().playAssetMedia(new Surface(surface), getAssets().openFd("douyin.mp4"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        Log.i("bqt", "onSurfaceTextureSizeChanged");// SurfaceTexture缓冲大小变化
        
    }
    
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        Log.i("bqt", "onSurfaceTextureDestroyed");// SurfaceTexture即将被销毁
        MediaPlayerManager.getInstance().stopMedia();
        return true;
    }
    
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        //Log.i("bqt", "onSurfaceTextureUpdated");// SurfaceTexture通过updateImage更新
    }
}
52
52
 
1
/**
2
 * Desc:演示使用TextureView和MediaPlayer播放视频
3
 *
4
 * @author 白乾涛 <p>
5
 * @tag TextureView<p>
6
 * @date 2018/5/22 23:56 <p>
7
 */
8
public class TextureViewTestActivity extends Activity implements TextureView.SurfaceTextureListener {
9
    
10
    protected void onCreate(Bundle savedInstanceState) {
11
        super.onCreate(savedInstanceState);
12
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//取消状态栏
13
        TextureView textureView = new TextureView(this);
14
        textureView.setSurfaceTextureListener(this);
15
        textureView.setRotation(45.0f);//可以像普通View一样使用平移、缩放、旋转等变换操作
16
        textureView.setAlpha(0.5f);
17
        setContentView(textureView);
18
    }
19
    
20
    @Override
21
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
22
        Log.i("bqt", "onSurfaceTextureAvailable");// SurfaceTexture准备就绪
23
        if (new Random().nextBoolean()) {
24
            String path = "http://ozvd186ua.bkt.clouddn.com/douyin.mp4";
25
            MediaPlayerManager.getInstance().playUrlMedia(new Surface(surface), path);
26
        } else {
27
            try {
28
                MediaPlayerManager.getInstance().playAssetMedia(new Surface(surface), getAssets().openFd("douyin.mp4"));
29
            } catch (IOException e) {
30
                e.printStackTrace();
31
            }
32
        }
33
    }
34
    
35
    @Override
36
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
37
        Log.i("bqt", "onSurfaceTextureSizeChanged");// SurfaceTexture缓冲大小变化
38
        
39
    }
40
    
41
    @Override
42
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
43
        Log.i("bqt", "onSurfaceTextureDestroyed");// SurfaceTexture即将被销毁
44
        MediaPlayerManager.getInstance().stopMedia();
45
        return true;
46
    }
47
    
48
    @Override
49
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
50
        //Log.i("bqt", "onSurfaceTextureUpdated");// SurfaceTexture通过updateImage更新
51
    }
52
}
public class MediaPlayerManager {
    
    private MediaPlayer mPlayer;
    
    private static MediaPlayerManager instance = new MediaPlayerManager();
    
    private MediaPlayerManager() {//构造方法私有
    }
    
    public static MediaPlayerManager getInstance() {
        return instance;
    }
    
    /**
     * 播放网络或本地中的Media资源
     */
    public void playUrlMedia(Surface surface, String mediaPath) {
        try {
            if (mPlayer == null) {
                mPlayer = new MediaPlayer();
                mPlayer.setDataSource(mediaPath);
            } else {
                if (mPlayer.isPlaying()) {
                    mPlayer.stop();
                }
                mPlayer.reset();
                mPlayer.setDataSource(mediaPath);
            }
            mPlayer.setSurface(surface);
            mPlayer.setVolume(0.5f, 0.5f);
            mPlayer.setLooping(true);
            mPlayer.prepareAsync();
            mPlayer.setOnPreparedListener(MediaPlayer::start);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 播放Asset中的Media资源
     */
    public void playAssetMedia(Surface surface, AssetFileDescriptor fileDescriptor) {
        try {
            if (mPlayer == null) {
                mPlayer = new MediaPlayer();
                mPlayer.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getDeclaredLength());
            } else {
                if (mPlayer.isPlaying()) {
                    mPlayer.stop();
                }
                mPlayer.reset();
                mPlayer.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getDeclaredLength());
            }
            mPlayer.setSurface(surface);
            mPlayer.setVolume(0.5f, 0.5f);
            mPlayer.setLooping(true);
            mPlayer.prepareAsync();
            mPlayer.setOnPreparedListener(MediaPlayer::start);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 停止播放Media
     */
    public void stopMedia() {
        try {
            if (mPlayer != null) {
                if (mPlayer.isPlaying()) {
                    mPlayer.stop();
                }
                mPlayer.release();
                mPlayer = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
80
80
 
1
public class MediaPlayerManager {
2
    
3
    private MediaPlayer mPlayer;
4
    
5
    private static MediaPlayerManager instance = new MediaPlayerManager();
6
    
7
    private MediaPlayerManager() {//构造方法私有
8
    }
9
    
10
    public static MediaPlayerManager getInstance() {
11
        return instance;
12
    }
13
    
14
    /**
15
     * 播放网络或本地中的Media资源
16
     */
17
    public void playUrlMedia(Surface surface, String mediaPath) {
18
        try {
19
            if (mPlayer == null) {
20
                mPlayer = new MediaPlayer();
21
                mPlayer.setDataSource(mediaPath);
22
            } else {
23
                if (mPlayer.isPlaying()) {
24
                    mPlayer.stop();
25
                }
26
                mPlayer.reset();
27
                mPlayer.setDataSource(mediaPath);
28
            }
29
            mPlayer.setSurface(surface);
30
            mPlayer.setVolume(0.5f, 0.5f);
31
            mPlayer.setLooping(true);
32
            mPlayer.prepareAsync();
33
            mPlayer.setOnPreparedListener(MediaPlayer::start);
34
        } catch (Exception e) {
35
            e.printStackTrace();
36
        }
37
    }
38
    
39
    /**
40
     * 播放Asset中的Media资源
41
     */
42
    public void playAssetMedia(Surface surface, AssetFileDescriptor fileDescriptor) {
43
        try {
44
            if (mPlayer == null) {
45
                mPlayer = new MediaPlayer();
46
                mPlayer.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getDeclaredLength());
47
            } else {
48
                if (mPlayer.isPlaying()) {
49
                    mPlayer.stop();
50
                }
51
                mPlayer.reset();
52
                mPlayer.setDataSource(fileDescriptor.getFileDescriptor(), fileDescriptor.getStartOffset(), fileDescriptor.getDeclaredLength());
53
            }
54
            mPlayer.setSurface(surface);
55
            mPlayer.setVolume(0.5f, 0.5f);
56
            mPlayer.setLooping(true);
57
            mPlayer.prepareAsync();
58
            mPlayer.setOnPreparedListener(MediaPlayer::start);
59
        } catch (Exception e) {
60
            e.printStackTrace();
61
        }
62
    }
63
    
64
    /**
65
     * 停止播放Media
66
     */
67
    public void stopMedia() {
68
        try {
69
            if (mPlayer != null) {
70
                if (mPlayer.isPlaying()) {
71
                    mPlayer.stop();
72
                }
73
                mPlayer.release();
74
                mPlayer = null;
75
            }
76
        } catch (Exception e) {
77
            e.printStackTrace();
78
        }
79
    }
80
}

使用TextureView和Camera预览拍照

/**
 * Desc:演示使用TextureView和Camera预览拍照
 *
 * @author 白乾涛 <p>
 * @tag TextureView<p>
 * @date 2018/5/22 23:56 <p>
 */
public class TextureViewTestActivity extends Activity implements TextureView.SurfaceTextureListener {
    private Camera mCamera;//权限【android.permission.CAMERA】
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//取消状态栏
        TextureView mTextureView = new TextureView(this);
        mTextureView.setSurfaceTextureListener(this);
        mTextureView.setRotation(45.0f);//可以像普通View一样使用平移、缩放、旋转等变换操作
        mTextureView.setAlpha(0.5f);
        setContentView(mTextureView);
    }
    
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        Log.i("bqt", "onSurfaceTextureAvailable");// SurfaceTexture准备就绪
        try {
            mCamera = Camera.open();//如果提示【Fail to connect to camera service】很可能是没申请权限,或申请权限了单用户没有给你权限
            mCamera.setPreviewTexture(surface);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        Log.i("bqt", "onSurfaceTextureSizeChanged");// SurfaceTexture缓冲大小变化
        
    }
    
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        Log.i("bqt", "onSurfaceTextureDestroyed");// SurfaceTexture即将被销毁
        mCamera.stopPreview();
        mCamera.release();
        return true;
    }
    
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        //Log.i("bqt", "onSurfaceTextureUpdated");// SurfaceTexture通过updateImage更新
    }
}
51
 
1
/**
2
 * Desc:演示使用TextureView和Camera预览拍照
3
 *
4
 * @author 白乾涛 <p>
5
 * @tag TextureView<p>
6
 * @date 2018/5/22 23:56 <p>
7
 */
8
public class TextureViewTestActivity extends Activity implements TextureView.SurfaceTextureListener {
9
    private Camera mCamera;//权限【android.permission.CAMERA】
10
    
11
    protected void onCreate(Bundle savedInstanceState) {
12
        super.onCreate(savedInstanceState);
13
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//取消状态栏
14
        TextureView mTextureView = new TextureView(this);
15
        mTextureView.setSurfaceTextureListener(this);
16
        mTextureView.setRotation(45.0f);//可以像普通View一样使用平移、缩放、旋转等变换操作
17
        mTextureView.setAlpha(0.5f);
18
        setContentView(mTextureView);
19
    }
20
    
21
    @Override
22
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
23
        Log.i("bqt", "onSurfaceTextureAvailable");// SurfaceTexture准备就绪
24
        try {
25
            mCamera = Camera.open();//如果提示【Fail to connect to camera service】很可能是没申请权限,或申请权限了单用户没有给你权限
26
            mCamera.setPreviewTexture(surface);
27
            mCamera.startPreview();
28
        } catch (IOException e) {
29
            e.printStackTrace();
30
        }
31
    }
32
    
33
    @Override
34
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
35
        Log.i("bqt", "onSurfaceTextureSizeChanged");// SurfaceTexture缓冲大小变化
36
        
37
    }
38
    
39
    @Override
40
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
41
        Log.i("bqt", "onSurfaceTextureDestroyed");// SurfaceTexture即将被销毁
42
        mCamera.stopPreview();
43
        mCamera.release();
44
        return true;
45
    }
46
    
47
    @Override
48
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
49
        //Log.i("bqt", "onSurfaceTextureUpdated");// SurfaceTexture通过updateImage更新
50
    }
51
}
2018-5-23




以上是关于TextureView SurfaceView 简介 案例的主要内容,如果未能解决你的问题,请参考以下文章

SurfaceView 与 TextureView 详解

SurfaceView 与 TextureView 详解

相机的 SurfaceView 与 TextureView 对比?

TextureView SurfaceView 简介 案例

android - 使用没有surfaceview或textureview的相机

TextureView 简介 SurfaceView