你的位置:首页 > 操作系统

[操作系统]Android 创建自己的Camera App


在sdk中找到/sdk/docs/guide/topics/media/camera.html#custom-camera,里面有详细的api参考

在清单文件中添加相应的权限:

    <uses-permission android:name="android.permission.CAMERA" />  <uses-feature android:name="android.hardware.camera" />  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  <uses-permission android:name="android.permission.RECORD_AUDIO" />  

按照官方文档,分为下面几步:

  • Detect and Access Camera - Create code to check for the existence of cameras and request access.
  • Create a Preview Class - Create a camera preview class that extends SurfaceView and implements theSurfaceHolder interface. This class previews the live images from the camera.
  • Build a Preview Layout - Once you have the camera preview class, create a view layout that incorporates the preview and the user interface controls you want.
  • Setup Listeners for Capture - Connect listeners for your interface controls to start image or video capture in response to user actions, such as pressing a button.
  • Capture and Save Files - Setup the code for capturing pictures or videos and saving the output.
  • Release the Camera - After using the camera, your application must properly release it for use by other applications.

接下来分别实现:

1、检查设备是否有照相机

  /** 检查设备是否存在照相机 */  private boolean checkCameraHardware(Context context) {    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){      // this device has a camera      return true;    } else {      // no camera on this device      return false;    }  }  

2、得到一个照相机

 /** 一种安全的方式获取Cameer对象的实例. */  public static Camera getCameraInstance(){    Camera c = null;    try {      c = Camera.open(); // attempt to get a Camera instance    }    catch (Exception e){      // Camera is not available (in use or does not exist)    }    return c; // returns null if camera is unavailable  }

3、新建一个名为CameraPreview的类

package com.wuyudong.mycamera;import java.io.IOException;import android.content.Context;import android.hardware.Camera;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;/** A basic Camera preview class */public class CameraPreview extends SurfaceView implements    SurfaceHolder.Callback {  private static final String TAG = "CameraPreview";  private SurfaceHolder mHolder;  private Camera mCamera;  public CameraPreview(Context context, Camera camera) {    super(context);    mCamera = camera;    // Install a SurfaceHolder.Callback so we get notified when the    // underlying surface is created and destroyed.    mHolder = getHolder();    mHolder.addCallback(this);    // deprecated setting, but required on Android versions prior to 3.0    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  }  public void surfaceCreated(SurfaceHolder holder) {    // The Surface has been created, now tell the camera where to draw the    // preview.    try {      mCamera.setPreviewDisplay(holder);      mCamera.startPreview();    } catch (IOException e) {      Log.d(TAG, "Error setting camera preview: " + e.getMessage());    }  }  public void surfaceDestroyed(SurfaceHolder holder) {    // empty. Take care of releasing the Camera preview in your activity.  }  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {    // If your preview can change or rotate, take care of those events here.    // Make sure to stop the preview before resizing or reformatting it.    if (mHolder.getSurface() == null) {      // preview surface does not exist      return;    }    // stop preview before making changes    try {      mCamera.stopPreview();    } catch (Exception e) {      // ignore: tried to stop a non-existent preview    }    // set preview size and make any resize, rotate or    // reformatting changes here    // start preview with new settings    try {      mCamera.setPreviewDisplay(mHolder);      mCamera.startPreview();    } catch (Exception e) {      Log.d(TAG, "Error starting camera preview: " + e.getMessage());    }  }}

4、设置一个预览功能的layout,将原来布局文件中的内容替换成下面的代码

<??><LinearLayout ="http://schemas.android.com/apk/res/android"  android:orientation="horizontal"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  > <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:text="Capture"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_gravity="center"  /></LinearLayout>

5、在清单文件中加入 android:screenOrientation="landscape" 调整相机为横向拍摄

6、在MainActivity中添加

public class MainActivity extends Activity {  private Camera mCamera;  private CameraPreview mPreview;  @Override  public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.main);    // Create an instance of Camera    mCamera = getCameraInstance();    // Create our Preview view and set it as the content of our activity.    mPreview = new CameraPreview(this, mCamera);    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);    preview.addView(mPreview);  }}

7、实现拍摄按钮的功能

(1)添加拍照回调方法

  private PictureCallback mPicture = new PictureCallback() {    @Override    public void onPictureTaken(byte[] data, Camera camera) {      File pictureFile = new File("/sdcard/" + System.currentTimeMillis()+".jpg");      try {        FileOutputStream fos = new FileOutputStream(pictureFile);        fos.write(data);        fos.close();      } catch (IOException e) {        Log.d("TAG", "Error accessing file: " + e.getMessage());      }    }  };

给拍照按钮添加注册事件:

    // Add a listener to the Capture button    Button captureButton = (Button) findViewById(R.id.button_capture);    captureButton.setOnClickListener(      new View.OnClickListener() {        @Override        public void onClick(View v) {          // get an image from the camera          mCamera.takePicture(null, null, mPicture);        }      }    );

完整的代码如下:

package com.wuyudong.mycamera;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.sql.Date;import android.os.Bundle;import android.app.Activity;import android.content.Context;import android.content.pm.PackageManager;import android.hardware.Camera;import android.hardware.Camera.AutoFocusCallback;import android.hardware.Camera.PictureCallback;import android.util.Log;import android.view.Menu;import android.view.View;import android.widget.Button;import android.widget.FrameLayout;public class MainActivity extends Activity {  private Camera mCamera;  private CameraPreview mPreview;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    // 创建一个 Camera 的实例    mCamera = getCameraInstance();    // 创建一个预览界面    mPreview = new CameraPreview(this, mCamera);    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);    preview.addView(mPreview);        // Add a listener to the Capture button    Button captureButton = (Button) findViewById(R.id.button_capture);    captureButton.setOnClickListener(      new View.OnClickListener() {        @Override        public void onClick(View v) {          mCamera.autoFocus(new AutoFocusCallback() { // 对焦                        @Override            public void onAutoFocus(boolean success, Camera camera) {              // get an image from the camera              mCamera.takePicture(null, null, mPicture);                          }          });                  }      }    );  }  /** 检查设备是否存在照相机 */  private boolean checkCameraHardware(Context context) {    if (context.getPackageManager().hasSystemFeature(        PackageManager.FEATURE_CAMERA)) {      // this device has a camera      return true;    } else {      // no camera on this device      return false;    }  }  /** 一种安全的方式获取Cameer对象的实例. */  public static Camera getCameraInstance() {    Camera c = null;    try {      c = Camera.open(); // attempt to get a Camera instance    } catch (Exception e) {      // Camera is not available (in use or does not exist)    }    return c; // returns null if camera is unavailable  }    private PictureCallback mPicture = new PictureCallback() {    @Override    public void onPictureTaken(byte[] data, Camera camera) {      File pictureFile = new File("/sdcard/" + System.currentTimeMillis()+".jpg");      try {        FileOutputStream fos = new FileOutputStream(pictureFile);        fos.write(data);        fos.close();      } catch (IOException e) {        Log.d("TAG", "Error accessing file: " + e.getMessage());      }    }  };    protected void onDestory() {    if(mCamera != null) {  //释放资源      mCamera.release();      mCamera = null;    }  }}