Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之TextureView淺析

Android之TextureView淺析

編輯:關於Android編程

最近,在修改Android4.4的原生相機Camera2,很習慣的去尋找SurfaceView,結果任憑我使用grep還是ack,都無法搜索到SurfaceView,最後還是通過代碼CameraActivity-->CameraModule-->PhotoUI-->R.layout.photo_module找到,原來是使用了TextureView。不是很了解此控件,百度之,在官方API文檔中找到此控件:

 

官方文檔大概的意思是:

TextureView可以用來顯示內容流。這樣一個內容流例如可以視頻或者OpenGL的場景。內容流可以來自本應用程序以及其他進程。

Textureview必須在硬件加速開啟的窗口中。

與SurfaceView相比,TextureView不會創建一個單獨的窗口,這使得它可以像一般的View一樣執行一些變換操作,比如移動、動畫等等,例如,你可以通過調用myView.setAlpha(0.5f)將TextureView設置成半透明。

使用TextureView很簡單:你需要使用的就是SurfaceTexture,SurfaceTexture可以用於呈現內容。

 

下面是我寫一個小例子來演示如何渲染相機預覽到TextureView,在官方文檔例子的基礎上稍微改動了一下:

main.xml:

 




    <framelayout android:id="@+id/camera_preview" android:layout_height="fill_parent" android:layout_weight="1" android:layout_width="fill_parent"></framelayout>

 

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;
        }
    }

}


 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved