除了手机录制音/视频外,手机拍照也已经不是什么新鲜事了,Android相应地提供了手机拍照功能API。要使用Android系统进行拍照,使用到的类有很多。具体介绍如下。
□ SurfaceView:该类是一个视图组件,实现了照片的预览功能。
□ SurfaceHolder:一个抽象接口,是SurfaceView的支持类,一般通过SurfaceView的getHolder()方法获得。允许你控制界面的尺寸和格式、编辑界面的像素,以及监控界面尺寸的改变。
□ SurfaceHolder.Callback:SurfaceHolder的一个内部接口,可以实现该接口获取界面改变的信息。该接口中有三个方法,surfaceCreated()方法在界面创建时被调用,一般在该方法中打开照相机并设置预览。surfaceChanged()方法在界面尺寸改变时被调用,一般在该方法中设置相机的参数(大小、格式等)。surfaceDestroyed()方法在界面被销毁时调用,在该方法中清除相机实例,释放资源。
□ Camera:相机类,实现拍照功能。
□ Camera.PictureCallback:Camera的一个内部接口,处理照片准备好后的回调。
通过上面类的介绍,可以实现一个拍照程序了。下面是程序的实现步骤。
(1)创建一个Android工程“Camera”,在该工程的“com.example”包中,创建一个MainActivity类,在该类的顶部声明SurfaceView、SurfaceHolder和Camera对象,代码如代码清单1所示。
代码清单1 MainActivity类中声明对象
package com.example;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends Activity {
//声明拍照界面组件SurfaceView
private SurfaceView surfaceView;
//声明界面控制组件SurfaceHolder
private SurfaceHolder surfaceHolder;
//声明照相机
private Camera camera;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置当前Activity界面布局
setContentView(R.layout.main);
}
}
(2)在该工程res\layout\目录下的布局文件main.xml中添加SurfaceView视图组件。代码如代码清单2所示。
代码清单2 main.xml中添加SurfaceView视图组件
<?xml version=”1.0” encoding=”utf-8”?>
<SurfaceView xmlns:android=”//schemas.android.com/apk/res/android”
android:id=”@+id/preview”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>
</SurfaceView>
(3)在onCreate()方法中获得SurfaceView和SurfaceHolder实例对象。代码如代码清单3所示。
代码清单3 onCreate()获取SurfaceView、SurfaceHolder实例对象
//实例化拍照界面组件
surfaceView = (SurfaceView) findViewById(R.id.preview);
//从SurfaceView中获得SurfaceHolder
surfaceHolder=surfaceView.getHolder();
(4)实现SurfaceHolder.Callback回调接口,实现该接口中的3个方法。代码如代码清单4所示。
代码清单4 实现SurfaceHolder.Callback回调接口
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//停止预览
camera.stopPreview();
//释放相机资源
camera.release();
camera=null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//打开相机
camera = Camera.open();
try{
//设置预览
camera.setPreviewDisplay(holder);
}catch(IOException e){
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
//获得相机参数
Camera.Parameters parameters = camera.getParameters();
//设置相片大小
parameters.setPictureSize(width, height);
//设置照片格式
parameters.setPictureFormat(PixelFormat.JPEG);
//开始预览
camera.startPreview();
}
};
(5)为SurfaceHolder添加回调,并设置其类型。代码如代码清单5所示。
代码清单5 为SurfaceHolder添加回调
surfaceHolder.addCallback(surfaceCallback);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
(6)创建一个保存照片任务类,该类的主要功能是将从硬件获得的字节流保存到设备中。代码如代码清单6所示。
代码清单6 创建保存照片任务类
public class SavePictureTask extends AsyncTask<byte[], String, String> {
@Override
protected String doInBackground(byte[]... params) {
// TODO Auto-generated method stub
//创建文件
File picture = new File(Environment.getExternalStorageDirectory(),
"picture.jpg");
//如果文件存在,删除现存文件
if(picture.exists())
picture.delete();
try{
//获取文件输出流
FileOutputStream fos = new
FileOutputStream(picture.getParent());
//写到该文件
fos.write(params[0]);
//关闭文件流
fos.close();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
(7)实现Camera.PictureCallBack回调方法,执行保存照片任务。代码如代码清单7所示。
代码清单7 实现Camera.PictureCallBack回调方法
//照片回调
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
(8)创建保存照片方法。代码如代码清单8所示。
代码清单8 创建保存照片方法
public void onPictureTaken(byte[] data, Camera camera) {
new SavePictureTask().execute(data);
camera.startPreview();
}
};
(9)相应按键事件,当拍照键或搜索键被按下时进行拍照。代码如代码清单9所示。
代码清单9 相应按键事件
//相应按键事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_CAMERA||
keyCode==KeyEvent.KEYCODE_SEARCH){
takePic();
return true;
}
return super.onKeyDown(keyCode, event);
}