14.3.2 实现自己的拍照Activity(1)
本节的例子代码所在的工程目录是src\ch14\ch14_camera
拍照的核心类是android.hardware.Camera,通过Camera类的静态方法open可以获得Camera对象,并通过Camera类的startPreview方法开始拍照,最后通过Camera类的takePicture方法结束拍照,并在相应的事件中处理照片数据。
上述的过程只是拍照过程的简化。在拍照之前,还需要做如下的准备工作。
指定用于显示拍照过程影像的容器,通常是SurfaceHolder对象。由于影像需要在SurfaceView对象中显示,因此可以使用SurfaceView类的getHolder方法获得SurfaceHolder对象。
在拍照过程中涉及到一些状态的变化。这些状态包括开始拍照(对应surfaceCreated事件方法);拍照状态变化(例如图像格式或方向,对应surfaceChanged事件方法);结束拍照(对应surfaceDestroyed事件方法)。这3个事件方法都是在SurfaceHolder.Callback接口中定义的,因此,需要使用SurfaceHolder接口的addCallback方法指定SurfaceHolder.Callback对象,以便捕捉这3个事件。
拍完照后需要处理照片数据。处理这些数据的工作需要在PictureCallback接口的onPictureTaken方法中完成。当调用Camera类的takePicture方法后,onPictureTaken事件方法被调用。
如果需要自动对焦,需要调用Camera类的autoFocus方法。该方法需要一个AutoFocusCallback类型的参数值。AutoFocusCallback是一个接口,在该接口中定义了一个onAutoFocus方法,当摄像头正在对焦或对焦成功都会调用该方法。
为了使拍照功能更容易使用,本节的例子将拍照功能封装在了Preview类中,代码如下:
- class Preview extends SurfaceView implements SurfaceHolder.Callback
- {
- private SurfaceHolder holder;
- private Camera camera;
- // 创建一个PictureCallback对象,并实现其中的onPictureTaken方法
- private PictureCallback pictureCallback = new PictureCallback()
- {
- // 该方法用于处理拍摄后的照片数据
- @Override
- public void onPictureTaken(byte[] data, Camera camera)
- {
- // data参数值就是照片数据,将这些数据以 key-value形式保存,以便其他调用该Activity的程序可
- // 以获得照片数据
- getIntent().putExtra("bytes", data);
- setResult(20, getIntent());
- // 停止照片拍摄
- camera.stopPreview();
- camera = null;
- // 关闭当前的Activity
- finish();
- }
- };
- // Preview类的构造方法
- public Preview(Context context)
- {
- super(context);
- // 获得SurfaceHolder对象
- holder = getHolder();
- // 指定用于捕捉拍照事件的SurfaceHolder.Callback对象
- holder.addCallback(this);
- // 设置SurfaceHolder对象的类型
- holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- }
- // 开始拍照时调用该方法
- public void surfaceCreated(SurfaceHolder holder)
- {
- // 获得Camera对象
- camera = Camera.open();
- try
- {
- // 设置用于显示拍照影像的SurfaceHolder对象
- camera.setPreviewDisplay(holder);
- }
- catch (IOException exception)
- {
- // 释放手机摄像头
- camera.release();
- camera = null;
- }
- }
- // 停止拍照时调用该方法
- public void surfaceDestroyed(SurfaceHolder holder)
- {
- // 释放手机摄像头
- camera.release();
- }
- // 拍照状态变化时调用该方法
- public void surfaceChanged(final SurfaceHolder holder, int format, int w, int h)
- {
- try
- {
- Camera.Parameters parameters = camera.getParameters();
- // 设置照片格式
- parameters.setPictureFormat(PixelFormat.JPEG);
- // 根据屏幕方向设置预览尺寸
- if (getWindowManager().getDefaultDisplay().getOrientation() == 0)
- parameters.setPreviewSize(h, w);
- else
- parameters.setPreviewSize(w, h);
- // 设置拍摄照片的实际分辨率,本例中的分辨率是1024×768
- parameters.setPictureSize(1024, 768);
- // 设置保存的图像大小
- camera.setParameters(parameters);
- // 开始拍照
- camera.startPreview();
- // 准备用于表示对焦状态的图像(类似图14.8所示的对焦符号)
- ivFocus.setImageResource(R.drawable.focus1);
- LayoutParams layoutParams = new LayoutParams(
- LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
- ivFocus.setScaleType(ScaleType.CENTER);
- addContentView(ivFocus, layoutParams);
- ivFocus.setVisibility(VISIBLE);
- // 自动对焦
- camera.autoFocus(new AutoFocusCallback()
- {
- @Override
- public void onAutoFocus(boolean success, Camera camera)
- {
- if (success)
- {
- // success为true表示对焦成功,改 变对焦状态图像(一个绿色的png图像)
- ivFocus.setImageResource(R.drawable.focus2);
- }
- }
- });
- }
- catch (Exception e)
- {
- }
- }
- // 停止拍照,并将拍摄的照片传入PictureCallback接口的onPictureTaken方法
- public void takePicture()
- {
- if (camera != null)
- {
- camera.takePicture(null, null, pictureCallback);
- }
- }
- }