2015/11/05

Android 使用TextureView接收Camera影像


Layout:
<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"
    tools:context="com.cyfang.test.MainActivity" >

    <TextureView
        android:id="@+id/textureView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="拍照" />

</RelativeLayout>

Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cyfang.test"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="15"
        android:targetSdkVersion="15" />

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-feature android:name="android.hardware.camera.autofocus" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>




Code:
package com.cyfang.test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.util.Log;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity implements SurfaceTextureListener, PictureCallback {

 /** 相機 */
 private Camera camera;

 /** 拍照按鈕 */
 private Button buttonTake;

 /** TextureView */
 private TextureView textureView;

 /** Surface */
 private SurfaceTexture surface;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  buttonTake = (Button) findViewById(R.id.button1);
  // 按鈕點擊事件
  buttonTake.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    camera.takePicture(null, null, MainActivity.this);
   }
  });

  textureView = (TextureView) findViewById(R.id.textureView);
  textureView.setSurfaceTextureListener(this);
  surface = textureView.getSurfaceTexture();
 }

 @Override
 protected void onStop() {
  super.onStop();

 }

 @Override
 public void onPictureTaken(byte[] data, Camera camera) {
  try {

   ByteArrayInputStream stream = new ByteArrayInputStream(data);
   Bitmap bitmap = BitmapFactory.decodeStream(stream);
   stream.close();
   stream = null;

   FileOutputStream fileOutputStream = new FileOutputStream(
     new File("/sdcard/" + new Date().getTime() + ".jpg"));
   bitmap.compress(CompressFormat.JPEG, 90, fileOutputStream);
   bitmap = null;

   // 寫入檔案
   fileOutputStream.flush();
   fileOutputStream.close();
   fileOutputStream = null;
   camera.startPreview();

  } catch (IOException e) {
   Log.i("Tack_IOException", e.getMessage());
  }
 }

 @Override
 public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
  try {
   camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
   // 取得相機參數
   Parameters parameters = camera.getParameters();

   // 關閉閃光燈
   parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);

   // 設定最佳預覽尺寸
   List<Size> listPreview = parameters.getSupportedPreviewSizes();
   parameters.setPreviewSize(listPreview.get(0).width, listPreview.get(0).height);
   listPreview = null;

   // 設定最佳照片尺寸
   List<Size> listPicture = parameters.getSupportedPictureSizes();
   parameters.setPictureSize(listPicture.get(0).width, listPicture.get(0).height);
   listPicture = null;

   // 設定照片輸出為90度
   parameters.setRotation(90);

   // 設定預覽畫面為90度
   camera.setDisplayOrientation(90);

   // 設定相機參數
   camera.setParameters(parameters);

   // 設定顯示的Surface
   camera.setPreviewTexture(surface);
   // 開始顯示
   camera.startPreview();
  } catch (IOException e) {
  }

 }

 @Override
 public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
   if (camera != null) {
   camera.stopPreview();
   camera.release();
  }
  return true;
 }

 @Override
 public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onSurfaceTextureUpdated(SurfaceTexture surface) {

 }

}


執行結果: