android:
layout_width="fill_parent"
android:
layout_height="fill_parent"
android:
id="@+id/surfaceview"
/>
第三步,设置窗口的显示方式
首先获得当前窗口Windowwindow=getWindow();//得到窗口
接着设置没有标题requestWindowFeature(Window.FEATURE_NO_TITLE);//没有标题
接着设置全屏window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏
当然,我们在拍照过程中,屏幕必须一致处于高亮状态,因此接着加入下面代码
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//设置高亮
至此,我们将窗口的显示方式规定死了,然后才能设置窗口上显示的组件(顺序非常重要)
setContentView(R.layout.main);
第四步,设置SurficeView显示控件的属性
找到surficeView
surfaceView=(SurfaceView)findViewById(R.id.surfaceview);
设置它的像素为800x600
surfaceView.getHolder().setFixedSize(800,480);
//下面设置surfaceView不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
第五步,就是为surficeView加入回调方法(callBack)
surfaceView.getHolder().addCallback(newSurfaceCallback());
上面的回调类是我们自己定义的,代码如下
privateclassSurfaceCallbackimplementsSurfaceHolder.Callback{
@Override
publicvoidsurfaceCreated(SurfaceHolderholder){
try{
camera=Camera.open();//打开硬件摄像头,这里导包得时候一定要注意是android.hardware.Camera
WindowManagerwm=(WindowManager)getSystemService(Context.WINDOW_SERVICE);//得到窗口管理器
Displaydisplay=wm.getDefaultDisplay();//得到当前屏幕
Camera.Parametersparameters=camera.getParameters();//得到摄像头的参数
parameters.setPreviewSize(display.getWidth(),display.getHeight());//设置预览照片的大小
parameters.setPreviewFrameRate(3);//设置每秒3帧
parameters.setPictureFormat(PixelFormat.JPEG);//设置照片的格式
parameters.setJpegQuality(85);//设置照片的质量
parameters.setPictureSize(display.getHeight(),display.getWidth());//设置照片的大小,默认是和屏幕一样大
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceView.getHolder());//通过SurfaceView显示取景画面
camera.startPreview();//开始预览
isPreview=true;//设置是否预览参数为真
}catch(IOExceptione){
Log.e(TAG,e.toString());
}
}
@Override
publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,
intheight){
//TODOAuto-generatedmethodstub
}
@Override
publicvoidsurfaceDestroyed(SurfaceHolderholder){
if(camera!
=null){
if(isPreview){//如果正在预览
camera.stopPreview();
camera.release();
}
}
}
}
第六步,我们必须对按键事件进行监听,如是拍照还是聚焦,代码如下
publicbooleanonKeyDown(intkeyCode,KeyEventevent){//处理按键事件
if(camera!
=null&&event.getRepeatCount()==0)//代表只按了一下
{
switch(keyCode){
caseKeyEvent.KEYCODE_BACK:
//如果是搜索键
camera.autoFocus(null);//自动对焦
break;
caseKeyEvent.KEYCODE_DPAD_CENTER:
//如果是中间键
camera.takePicture(null,null,newTakePictureCallback());//将拍到的照片给第三个对象中,这里的TakePictureCallback()是自己定义的,在下面的代码中
break;
}
}
returntrue;//阻止事件往下传递,否则按搜索键会变成系统默认的
}
------------------------------------------------------------------------------------------
privatefinalclassTakePictureCallbackimplementsPictureCallback{
publicvoidonPictureTaken(byte[]data,Cameracamera){
try{
Bitmapbitmap=BitmapFactory.decodeByteArray(data,0,data.length);
Filefile=newFile(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");
FileOutputStreamoutputStream=newFileOutputStream(file);
press(CompressFormat.JPEG,100,outputStream);
outputStream.close();
camera.stopPreview();
camera.startPreview();//处理完数据之后可以预览
}catch(Exceptione){
Log.e(TAG,e.toString());
}
}
}
注意,代码中有两个回调类,一个是SurfaceCallback(),另外一个是TakePictureCallback(),初学者可能一时难以理解,通俗地讲,前者是用来监视surficeView这个暂时存放图片数据的显示控件的,根据它的显示情况调用不同的方法,包括surfaceCreated(),surfaceChanged(),surfaceDestroyed(),也就不难理解为什么会有这三个回调方法了(注意,在surfaceDestroyed()方法中必须释放摄像头,详细代码参见上方)。
TakePictureCallback()是为了监视是否拍照而设计的接口,期中也仅有一个方法,camera将拍照得到的数据传入方法,我们便可以对拍照得到的数据进行进一步处理了。
至此,简单的拍照功能介绍完毕!