1. 程式人生 > >android通過camera和surfaceview選擇攝像頭並即時預覽

android通過camera和surfaceview選擇攝像頭並即時預覽

在使用android裝置的攝像頭的時候我們有兩種選擇:

1.呼叫intent方法使用攝像頭

2.通過camera類使用攝像頭

第一種方法非常方便,不過需要跳到新的activity中,這樣的使用者體驗並不是特別好

生氣使用camera能有更大的自定義空間!

使用camera就需要用surfaceview顯示攝像頭的即時畫面

我們這樣設定layout:

<LinearLayout 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"
    android:gravity="center"
    android:orientation="vertical"
    tools:context="com.example.video_activity.MainActivity" >

    <SurfaceView
        android:id="@+id/surfaceview"
        android:layout_width="320dp"
        android:layout_height="240dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/change"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="change" />
    </LinearLayout>

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="which camera" />

</LinearLayout>

一個靜態的surfaceview、Button和Textview

button是用於後面切換攝像頭的

textview用於顯示攝像頭id

例項化以上控制元件再宣告一個camera物件。

	private Camera mCamera;

例項化控制元件後還要給surfaceview一個holder用於接收camera的內容。

一個layoutParameters用於改變surfaceview尺寸(否則會產生畸變)

lp = surfaceView.getLayoutParams();
sh = surfaceView.getHolder();

選一個攝像頭的id(預設可以為0或者1),獲取它的資訊

private Void OpenCameraAndSetSurfaceviewSize(int cameraId) {
		mCamera = Camera.open(cameraId);//id用於選中不同的攝像頭,有的相機會有很多的
		Camera.Parameters parameters = mCamera.getParameters();
		Size pre_size = parameters.getPreviewSize();
		Size pic_size = parameters.getPictureSize();//和預覽的尺寸不同,這是拍照後實際相片的尺寸,會比較大
		android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
		android.hardware.Camera.getCameraInfo(cameraId, info);//獲取選中的攝像頭資訊
		int camera_number = Camera.getNumberOfCameras();//獲取攝像頭數量
		if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {//分辨是否前置攝像頭
			textview.setText("There are " + camera_number + " camera."
					+ "This is the Front Camera!");
		} else {
			textview.setText("There are " + camera_number + " camera."
					+ "This is the Back Camera!");
		}
		lp.height = pre_size.width * 2;
		lp.width = pre_size.height * 2;
		return null;
	}


我們編寫SetAndStartPreview方法例項化camera並將預覽載入到surfaceview中

private Void SetAndStartPreview(SurfaceHolder holder) {
		try {
			mCamera.setPreviewDisplay(holder);
			mCamera.setDisplayOrientation(90);
			mCamera.startPreview();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

切換攝像頭的原理就將camera釋放掉再重新載入。

為button新增事件監聽:
change_Button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				mCamera.stopPreview();
				mCamera.release();
				if (cameraId == 0) {
					cameraId = 1;
				} else {
					cameraId = 0;
				}
				OpenCameraAndSetSurfaceviewSize(cameraId);
				// the surfaceview is ready after the first launch
				SetAndStartPreview(sh);
			}
		});
值得一提的是我們將camera和surface holder關聯的時候必須確保surfaceview已經建立好,否則camera獲取不到surfaceview的資訊

我們需要為surfaceholder新增addCallback(this);並在create中呼叫方法

	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		SetAndStartPreview(holder);
	}

原始碼在這裡⬇️

http://download.csdn.net/detail/edwardwayne/8491597