zoukankan      html  css  js  c++  java
  • 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:

    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:
    " + 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:
    " + 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;
            }
        }
    
    }


  • 相关阅读:
    web安全与防御
    网页的分段传输与渲染
    关于promise的详细讲解
    mvc/mvvm小小的总结
    瀑布流布局:从上往下布局方式(——)往同级元素中高度最低的元素后面排列
    页面刷新-导航高亮不变
    safari浏览器会将时间、自动识别为号码(包括电话号码、qq号码全部标注为蓝色)
    fullpage.js配合bootstrap制作响应式网站
    bootstrap ----tooltip
    范围选择器,jquery.range插件使用
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7119379.html
Copyright © 2011-2022 走看看