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

[操作系统]自定义相机(一)


在5.0之前的版本中自定义相机是按如下步骤:

一,做一个自定义相机的步骤

1.找到并获取相机的权限

检测相机的存在,并获取权限

检测是否有相机设备代码

if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){    // 有相机设备    return true;  } else {    // 没有相机设备    return false;  }

检测相机是否可用代码

Camera c = null;  try {    c = Camera.open(); // 得到一个相机的实例  }  catch (Exception e){    // 相机不存在或正在被使用  }

2.建一个预览视图类

该类应为SurfaceView的子类

      作为一个自定义的视图类

        其主要业务是在在不同的事件内,通过传入的Camera实例控制预览视图(Preview)

        具体API的演示代码如下:

/** A basic Camera preview class */public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {  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) {    // 如果你的视图可以改变或旋转,需关注这个事件    // 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());    }  }}

3.建一个预览布局

布局相对比较简单,之后显示相机预览图的SurfaceView将通过代码加在FrameLayout中

<??><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>

在与之对应的Activity中主要代码如下:

public class CameraActivity extends Activity {  private Camera mCamera;  private CameraPreview mPreview;  @Override  public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.main);    // 创建Camera的实例    mCamera = Camera.open();    //为Activity添加Preview视图SurfaceView    mPreview = new CameraPreview(this, mCamera);    FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);    preview.addView(mPreview);  }}

 

4.监听拍照动作

按钮监听动作,然后就开始聚焦

具体代码实现就是和普通监听一样,聚焦则可以使用camera.autoFocus(autoFocusCallBack);

autoFocusCallBack是AutoFocusCallback的实例,主要用来回调对焦完成后的操作。

    比如通过Camera.takePicture(shutter,PictureCallback,PictureCallback)捕获图片

5.捕获图片并保存

通过Camera.takePicture(shutter,PictureCallback,PictureCallback)捕获图片后,需要对图片进行保存

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

以上是官方API中的Demo,通过onPictureTaken方法获取捕获到的图片数据,可供参考

6.释放相机资源

在之前的surfaceDestroyed中可以通过camera.release释放相机资源以免影响其他应用的使用

以下是自己写的demo,图简单,省了很多,结构也很乱,不过基本的照相功能已实现

package com.rw.demo;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;import android.graphics.ImageFormat;import android.hardware.Camera;import android.hardware.Camera.AutoFocusCallback;import android.hardware.Camera.PictureCallback;import android.hardware.Camera.ShutterCallback;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import android.view.View;import android.view.Window;import android.view.WindowManager;public class CameraDemo extends Activity {  private SurfaceView cameraSurface;  private SurfaceHolder myHolder;  private boolean isPreview=false;  Camera camera;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    requestWindowFeature(Window.FEATURE_NO_TITLE);    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);        setContentView(R.layout.camera_layout);        getView();        //添加回调函数    myHolder=cameraSurface.getHolder();    myHolder.addCallback(new Callback() {            @Override      public void surfaceDestroyed(SurfaceHolder holder) {              }            @Override      public void surfaceCreated(SurfaceHolder holder) {        try {          CameraDemo.this.initCamera(holder);        } catch (IOException e) {          // TODO Auto-generated catch block          e.printStackTrace();        }      }            @Override      public void surfaceChanged(SurfaceHolder holder, int format, int width,          int height) {              }    });  }  /**   * 初始化相机   * @param holder   * @throws IOException   */  @SuppressWarnings("deprecation")  protected void initCamera(SurfaceHolder holder) throws IOException {          if(!isPreview)        camera=Camera.open(1);      camera.setDisplayOrientation(90);    if(camera!=null && !isPreview){            camera.setPreviewDisplay(holder);            camera.startPreview();      isPreview=true;    }  }  /**   * 获取视图控件   */  private void getView() {    cameraSurface=(SurfaceView) findViewById(R.id.camera_surface_id);  }  /**   * 捕获图片   * @param v   */  public void takePhoto(View v){    if(camera!=null){      Log.i("CameraDemo","开始照相了!");      camera.autoFocus(autoFocusCallBack);    }  }  //完成自动聚焦后的回调方法  AutoFocusCallback autoFocusCallBack =new AutoFocusCallback() {        @Override    public void onAutoFocus(boolean success, Camera camera) {      if(success){        camera.takePicture(new ShutterCallback() {                    @Override          public void onShutter() {                      }        }, new PictureCallback(){          @Override          public void onPictureTaken(byte[] data, Camera camera) {                      }                  }, jpeg);      }    }  };  //捕获到图片后的回调方法  PictureCallback jpeg=new PictureCallback() {        @Override    public void onPictureTaken(byte[] data, Camera camera) {      //根据拍照的数据创建位图      final Bitmap bm=BitmapFactory.decodeByteArray(data,0, data.length);            File file=new File(Environment.getExternalStorageDirectory(),"testPicture.jpg");            FileOutputStream outStream =null;            try {        outStream=new FileOutputStream(file);        bm.compress(CompressFormat.JPEG, 100, outStream);        outStream.close();      } catch (FileNotFoundException e) {        // TODO Auto-generated catch block        e.printStackTrace();      } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();      }      camera.stopPreview();      camera.startPreview();      isPreview=true;          }  };  //释放将相机资源  @Override  protected void onDestroy() {    super.onDestroy();    if(camera!=null){      camera.release();    }  }  @Override  protected void onPause() {    // TODO Auto-generated method stub    super.onPause();  }      }