先说说我的测试机器:nexus s。以下的结果都是通过nexus s上测试通过。
还是先上代码:
package com.TestCamera1;import java.io.BufferedOutputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.List;import android.app.Activity;import android.content.Context;import android.content.pm.ActivityInfo;import android.content.res.Configuration;import android.graphics.Bitmap;import android.graphics.Bitmap.CompressFormat;import android.graphics.BitmapFactory;import android.graphics.ImageFormat;import android.graphics.Matrix;import android.graphics.PixelFormat;import android.graphics.Rect;import android.graphics.YuvImage;import android.hardware.Camera;import android.hardware.Camera.AutoFocusCallback;import android.hardware.Camera.CameraInfo;import android.hardware.Camera.PictureCallback;import android.hardware.Camera.PreviewCallback;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.Display;import android.view.KeyEvent;import android.view.Surface;import android.view.SurfaceHolder;import android.view.View;import android.view.SurfaceHolder.Callback;import android.view.View.OnClickListener;import android.view.SurfaceView;import android.view.Window;import android.view.WindowManager;import android.widget.Button;public class TestCamera1Activity extends Activity { /** Called when the activity is first created. */ private SurfaceHolder surfaceHolder; private Camera camera; private int cameraId; private SurfaceView surfaceView; private Button btn; private boolean flag; private Camera.PreviewCallback previewCallBack; private AutoFocusCallback cb = new AutoFocusCallback() {//自动对焦实现 public void onAutoFocus(boolean success, Camera camera) { if (success) { camera.setOneShotPreviewCallback(pcb); } else { Log.i("autofocus:", "fail"); } } }; private PreviewCallback pcb=new PreviewCallback(){ public void onPreviewFrame(byte[] data,Camera arg1){ if(data!=null){ String picDirStr = Environment.getExternalStorageDirectory() + "/"; File picDir = new File(picDirStr); if (!picDir.exists()) { picDir.mkdir(); } String picName = picDirStr + System.currentTimeMillis() + "auto.jpg"; File myCaptureFile = new File(picName); Camera.Parameters parameters=camera.getParameters(); int imageFormat=parameters.getPreviewFormat(); if(imageFormat==ImageFormat.NV21){ Bitmap image=null; int w=parameters.getPreviewSize().width; int h=parameters.getPreviewSize().height; Rect rect=new Rect(0,0,w,h); YuvImage img=new YuvImage(data,ImageFormat.NV21,w,h,null); try { BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile)); img.compressToJpeg(rect, 100, bos); bos.flush(); bos.close(); camera.startPreview();// 重新打开预览图,进行下一次的拍照准备,必须等到onPictureCallback函数调用才能调用 Log.i("autopic", "ok!"); } catch (Exception e) { Log.i("autopic", e.toString()); } } }else{ Log.i("data:", "null"); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); btn = (Button) findViewById(R.id.button1); surfaceView = (SurfaceView) findViewById(R.id.preview_view); surfaceHolder = surfaceView.getHolder(); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.getHolder().addCallback(new SurfaceViewCallback()); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub camera.autoFocus(cb);// 自动对焦 } }); } private final class SurfaceViewCallback implements SurfaceHolder.Callback { public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub Camera.Parameters parameters = camera.getParameters(); // 选择合适的预览尺寸 List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes(); Camera.Size cameraSize = (Camera.Size) sizeList.get(1); parameters.setPreviewSize(cameraSize.width, cameraSize.height); parameters.setPreviewFrameRate(5); parameters.setPictureFormat(PixelFormat.JPEG); parameters.set("jpeg-quality", 100); int rotation = TestCamera1Activity.this.getWindowManager() .getDefaultDisplay().getRotation(); Log.e("default", rotation + ""); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { camera.setDisplayOrientation(90); flag = true; Log.i("por", "1"); } if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { parameters.set("orientation", "landscape"); parameters.set("rotation", 0); flag = false; Log.i("orientation", "1"); } camera.setParameters(parameters); try { camera.setPreviewDisplay(surfaceHolder); } catch (IOException e) { System.out.println(e.getMessage()); } camera.startPreview(); } public void surfaceCreated(SurfaceHolder arg0) { // TODO Auto-generated method stub camera = Camera.open(); } public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub if (camera != null) { camera.stopPreview(); } camera.release(); camera = null; } }}
自动对焦比较简单,只需要调用camera.autoFocus(cb)。然后调用自动对焦的回调函数private AutoFocusCallback cb = new AutoFocusCallback() {},当然你也可以不构造这个函数即是camera.autoFocus(null),前提是你保证你的手机支持自动对焦。然后就是照相了,可以调用camera.setOneShotPreviewCallback或者camera.setPreviewCallback,他们的区别就是前者记录对焦时候预览图的一帧,而后者就不停地调用,即你可以得到很多对焦过程中得到的预览图。
需要注意的是预览图的格式是NV21,而BitmapFactory不支持这种格式的解码。所以需要转换。
如果你想不断的对照就需要一个Timer不断出发autoFocus函数了。
最后我想说说takepicture和preview。他们都可以照相,那么他们有什么区别呢?所谓的照相我觉得就是得到data,把这个data输出成照片就完成照相功能了,那么他们都能完成这个功能,所以在这点上他们没有太大差别。只是preview可以得到一幅对焦后的图片,比takepicture清晰。你当然可以autofocus之后再takepicture,那么得到的图片就跟preview一样了。
附上android camera(3)的demo:android camera.rar
下集说的是利用zxing对条形码和二维码进行解码,其实这个是我的原本目的。因为zxing解码需要照相机我才去恶补一下camera的知识。
忘了警告:android camera系列的文章是由一个刚接触android不到一个月的菜鸟所写,所以必然存在很多错误,请大家指出