Android之TextureView浅析

仓廪实则知礼节,衣食足则知荣辱。这篇文章主要讲述Android之TextureView浅析相关的知识,希望能为你提供帮助。
近期,在改动android4.4的原生相机Camera2,非常习惯的去寻找SurfaceView,结果任凭我使用grep还是ack。都无法搜索到SurfaceView,最后还是通过代码CameraActivity--> CameraModule--> PhotoUI--> R.layout.photo_module找到,原来是使用了TextureView。
不是非常了解此控件。百度之。在官方API文档中找到此控件:
http://android.toolib.net/reference/android/view/TextureView.html
官方文档大概的意思是:
TextureView能够用来显示内容流。这样一个内容流比如能够视频或者OpenGL的场景。内容流能够来自本应用程序以及其它进程。

Textureview必须在硬件加速开启的窗体中。
与SurfaceView相比。TextureView不会创建一个单独的窗体,这使得它能够像一般的View一样运行一些变换操作,比方移动、动画等等,比如,你能够通过调用myView.setAlpha(0.5f)将TextureView设置成半透明。
使用TextureView非常easy:你须要使用的就是SurfaceTexture。SurfaceTexture能够用于呈现内容。




以下是我写一个小样例来演示怎样渲染相机预览到TextureView。在官方文档样例的基础上略微修改了一下:
main.xml:

< ?xml version=" 1.0" encoding=" utf-8" ?> < LinearLayout xmlns:android=" http://schemas.android.com/apk/res/android" android:layout_width=" fill_parent" android:layout_height=" fill_parent" android:orientation=" horizontal" > < FrameLayout android:id=" @+id/camera_preview" android:layout_width=" fill_parent" android:layout_height=" fill_parent" android:layout_weight=" 1" /> < Button android:id=" @+id/button_capture" android:layout_width=" wrap_content" android:layout_height=" wrap_content" android:layout_gravity=" center" android:text=" Capture" /> < /LinearLayout>


CameraPreview.java:
import java.io.IOException; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.view.TextureView; @SuppressLint(" NewApi" ) public class CameraPreview extends TextureView implements TextureView.SurfaceTextureListener { private Camera mCamera; private TextureView mTextureView; public CameraPreview(Context context , Camera camera) { super(context); mCamera = camera; // TODO Auto-generated constructor stub }public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { //mCamera = Camera.open(); try { mCamera.setPreviewTexture(surface); mCamera.startPreview(); } catch (IOException ioe) { // Something bad happened } }public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { // Ignored, Camera does all the work for us }public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { mCamera.stopPreview(); mCamera.release(); return true; }public void onSurfaceTextureUpdated(SurfaceTexture surface) { // Invoked every time there' s a new Camera preview frame }}


CameraTest.java:
【Android之TextureView浅析】
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.Toast; import com.example.mycamera.R.id; @SuppressLint(" NewApi" ) public class CameraTest extends Activity { public static final int MEDIA_TYPE_IMAGE = 1; public static final int MEDIA_TYPE_VIDEO = 2; private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100; private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200; private Camera mCamera; private CameraPreview mPreview; private static final String TAG = " ERROR" ; private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null) { Log.d(TAG, " Error creating media file, check storage permissions: " + " e.getMessage()" ); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, " File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, " Error accessing file: " + e.getMessage()); } } }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.main); // 创建Camera实例 mCamera = getCameraInstance(); // 创建Preview view并将其设为activity中的内容 mPreview = new CameraPreview(this, mCamera); mPreview.setSurfaceTextureListener(mPreview); //设置浑浊 mPreview.setAlpha(0.5f); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); // preview.setAlpha(0.0f); preview.addView(mPreview); // 在Capture按钮中增加listener Button captureButton = (Button) findViewById(id.button_capture); captureButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 从摄像头获取图片 mCamera.takePicture(null, null, mPicture); } }); }/** 安全获取Camera对象实例的方法 */public static Camera getCameraInstance() { Camera c = null; try { c = Camera.open(); // 试图获取Camera实例 } catch (Exception e) { // 摄像头不可用(正被占用或不存在) } return c; // 不可用则返回null }/** 为保存图片或视频创建File */ private static File getOutputMediaFile(int type) { // 安全起见,在使用前应该 // 用Environment.getExternalStorageState()检查SD卡是否已装入 File mediaStorageDir = new File( Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), " MyCameraApp" ); // 假设期望图片在应用程序卸载后还存在、且能被其他应用程序共享, // 则此保存位置最合适 // 假设不存在的话,则创建存储文件夹 if (!mediaStorageDir.exists()) { if (!mediaStorageDir.mkdirs()) { Log.d(" MyCameraApp" , " failed to create directory" ); return null; } Log.d(" MyCameraApp" , " failed to create directory" ); } // 创建媒体文件名称 String timeStamp = new SimpleDateFormat(" yyyyMMdd_HHmmss" ) .format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + " IMG_" + timeStamp + " .jpg" ); } else if (type == MEDIA_TYPE_VIDEO) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + " VID_" + timeStamp + " .mp4" ); } else { return null; } return mediaFile; }@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) { if (resultCode == RESULT_OK) { // 捕获的图像保存到Intent指定的fileUri Toast.makeText(this, " Image saved to:\n" + data.getData(), Toast.LENGTH_LONG).show(); } else if (resultCode == RESULT_CANCELED) { // 用户取消了图像捕获 } else { // 图像捕获失败,提示用户 } }if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) { if (resultCode == RESULT_OK) { // 捕获的视频保存到Intent指定的fileUri Toast.makeText(this, " Video saved to:\n" + data.getData(), Toast.LENGTH_LONG).show(); } else if (resultCode == RESULT_CANCELED) { // 用户取消了视频捕获 } else { // 视频捕获失败,提示用户 } } }@Override protected void onPause() { super.onPause(); releaseCamera(); // 在暂停事件中马上释放摄像头 }private void releaseCamera() { if (mCamera != null) { mCamera.release(); // 为其他应用释放摄像头 mCamera = null; } }}











    推荐阅读