完成一个拍照功能需要完成两个部分,一个是预览(preview),一个是拍照。

1.预览功能

我们使用SurfaceView在屏幕上渲染出一片区域,然后将摄像头捕捉到的画面显示在该区域内。Surface的设置有以下5个步骤:
1. 创建一个SurfaceView
2. 获得操作对象
3. 获得SurfaceHolder对象
4. 实现SurfaceHolder.CallBack接口,并传递给SurfaceHolder
5. 设置SurfaceHolder类型

(1)在xml文件中创建SurfaceView

<SurfaceView 
            android:id="@+id/surfaceView1"
            android:layout_width="320px"
            android:layout_height="240px"/>

(2)获得对象SurfaceView sv=(SurfaceView) findViewById(R.id.surfaceView1);
(3)holder=sv.getHolder(); //获得holder对象
(4)回调接口

public void surfaceChanged(SurfaceHolder arg0,int arg1,int arg2,int arg3)
    {

        if(camera!=null){
        camera.release();
        }
    }
    public void surfaceCreated(SurfaceHolder arg0)
    {

    }
    public void surfaceDestroyed(SurfaceHolder arg0)
    {
        if(camera!=null){
            camera.release();
            camera=null;
        }
    }

之后使用holder.addCallback(this); 便实现了将参数传递给了SurfaceHolder
(5)设置类型

2.配置Camera预览参数

有以下5个步骤:
1. 获得Camera对象
2. 获得相机参数
3. 设置预览大小
4. 绑定SurfaceView
5. 开始预览

3.拍摄功能

Camera.takePicture(ShutterCalback shutter,PictureCallback raw,
PictureCallback jpeg),可以只实现第三个回调函数实现拍照功能。
实现PictureCallback jpeg接口:
在该接口中要实现方法:
public void onPictureTaken(byte[] data, Camera camera)
第一个参数是照片原始数据,用位图表示
Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length);
之后可以保存为文件了
bm.compress(CompressFormat format, int quality, OutputStream stream);


实现简易相机

首先要在注册文件中获得相应权限:

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

实现代码:

public class MainActivity extends Activity implements SurfaceHolder.Callback {//实现callback接口
    SurfaceView sv;
    SurfaceHolder holder;
    Button preview_btn;
    Button take_btn;
    ImageView iv;
    Camera camera;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    //  setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//横向屏幕
        initView();
        preview_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO 自动生成的方法存根
                preview();//开始预览
                //camera.autoFocus(afc);//可实现自动对焦功能
            }
        });

        take_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO 自动生成的方法存根
                takePicture();
            }
        });

    }

private AutoFocusCallback afc=new Camera.AutoFocusCallback() {//自动对焦的接口,对焦完毕则拍照

        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            // TODO 自动生成的方法存根

            if(success)
            {
                takePicture();
            //  camera.cancelAutoFocus();
            }
        }
    };
    private void initView() {
        // TODO 自动生成的方法存根
        sv=(SurfaceView) findViewById(R.id.surfaceView1);
        iv=(ImageView)findViewById(R.id.imageView1);
        preview_btn=(Button)findViewById(R.id.button1);
        take_btn=(Button)findViewById(R.id.button2);
        holder=sv.getHolder(); //获得holder对象
        holder.addCallback(this); //添加回调函数接口
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型
    }

//预览函数
    protected void preview() {
        // TODO 自动生成的方法存根
        camera=Camera.open();//打开相机,获得相机对象
        try
        {
            Camera.Parameters param=camera.getParameters();//获得支持的一些参数

            //获得支持的预览大小,设置不支持的大小会出现异常
            List<Camera.Size> preSizes=param.getSupportedPreviewSizes();
            for(Camera.Size s:preSizes){
                Log.i("SupportedPreviewSize:", s.height+"X"+s.width);
            }//可以在日志中看到支持的预览大小,从而根据数值设置正确的预览大小
            //设置支持的照片大小,设置不支持的大小会出现异常
            List<Camera.Size> picSizes=param.getSupportedPictureSizes();
            for(Camera.Size s:picSizes){
                Log.i("SupportedPictureSize:", s.height+"X"+s.width);
            }//可以在日志中看到支持的预览大小
            param.setPreviewSize(320, 240);  //设置预览大小
            param.setPictureFormat(PixelFormat.JPEG);//设置照片格式
            param.setPictureSize(800, 480);//设置照片大小
            param.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            camera.setParameters(param);//参数传递给相机对象
            camera.setPreviewDisplay(holder);//相机预览显示在SurfaceView上
            camera.startPreview();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }

    protected void takePicture() {

        // TODO 自动生成的方法存根
        if(camera!=null)
        camera.takePicture(null, null, jpeg);
    }

    //jpg格式的照片处理接口,作为一个参数传递给takePicture()函数
    PictureCallback jpeg = new PictureCallback() {
        //第一个参数是照片的字节数组数据,强转为位图类型
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO 自动生成的方法存根
            Bitmap bm=BitmapFactory.decodeByteArray(data, 0, data.length);
            String path="/sdcard/camera.jpg";
            File file=new File(path);
            try
            {
                FileOutputStream fos=new FileOutputStream(file);
                BufferedOutputStream bos=new BufferedOutputStream(fos);//流对象
                bm.compress(Bitmap.CompressFormat.JPEG, 80, bos);//保存图片
                bos.flush();
                bos.close();//关闭流
                iv.setImageBitmap(bm);//显示照片
                camera.stopPreview();
                camera.release();
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
    };

    //SurfaceHolder的3个回调接口
    public void surfaceChanged(SurfaceHolder arg0,int arg1,int arg2,int arg3)
    {

        if(camera!=null){
        camera.release();
        }
    }
    public void surfaceCreated(SurfaceHolder arg0)
    {

    }
    public void surfaceDestroyed(SurfaceHolder arg0)
    {
        if(camera!=null){
            camera.release();
            camera=null;
        }
    }
}

特别注意:Activity要实现SurfaceHolder.callback的回调接口。
另外,照片预览的大小设置必须设置正确,不同机型可能会有差异,在日志中查看正确值。
自动对焦功能,可在preview后自动对焦,并拍照。但此处运用的效果不是很好。