Android开发教程之调用摄像头功能的方法详解
本文实例讲述了Android调用摄像头功能的方法。分享给大家供大家参考,具体如下:
我们要调用摄像头的拍照功能,显然
第一步必须加入调用摄像头硬件的权限,拍完照后我们要将图片保存在SD卡中,必须加入SD卡读写权限,所以第一步,我们应该在Android清单文件中加入以下代码
摄像头权限:
<uses-permissionandroid:name="android.permission.CAMERA"/>
SD卡读写权限:
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
第二步,要将摄像头捕获的图像实时地显示在手机上。
我们是用SurfaceView这个视图组件来实现的,因此在main.xml中加入下列代码
<SurfaceView 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); bitmap.compress(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将拍照得到的数据传入方法,我们便可以对拍照得到的数据进行进一步处理了。
至此,简单的拍照功能介绍完毕!
packagecn.camera.rxm; importjava.io.File; importjava.io.FileOutputStream; importjava.io.IOException; importjava.util.Calendar; importjava.util.Locale; importorg.apache.commons.logging.Log; importandroid.text.format.DateFormat; importandroid.util.*; importandroid.app.Activity; importandroid.content.Context; importandroid.graphics.Bitmap; importandroid.graphics.Bitmap.CompressFormat; importandroid.graphics.BitmapFactory; importandroid.graphics.PixelFormat; importandroid.hardware.Camera; importandroid.hardware.Camera.PictureCallback; importandroid.os.Bundle; importandroid.os.Environment; importandroid.view.LayoutInflater; importandroid.view.Menu; importandroid.view.MenuItem; importandroid.view.SurfaceHolder; importandroid.view.SurfaceView; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; //importandroid.widget.Toast; publicclassMycamActivityextendsActivity{ privatePreviewmPreview; privateCameramCamera; BitmapCameraBitmap; SurfaceHoldermHolder; privatestaticfinalintOPTION_SNAPSHOT=0; privatestaticfinalintOPTION_STOPCAMERA=1; privateViewviewStart; @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); LayoutInflaterflater=this.getLayoutInflater(); viewStart=flater.inflate(R.layout.main,null); setContentView(viewStart); Buttonbtn1=(Button)findViewById(R.id.button1); btn1.setOnClickListener( newOnClickListener(){ publicvoidonClick(Viewv){ mPreview=newPreview(getBaseContext()); setContentView(mPreview); }; } ); } publicbooleanonCreateOptionsMenu(Menumenu){ // menu.add(0,OPTION_SNAPSHOT,0,R.string.take); // menu.add(0,OPTION_STOPCAMERA,1,R.string.back); // returntrue;//super.onCreateOptionsMenu(menu); } publicbooleanonOptionsItemSelected(MenuItemitem){ // intitemId=item.getItemId(); // switch(itemId){ caseOPTION_SNAPSHOT: //拍摄照片 mCamera.takePicture(null,null,jpegCallback); try{ Thread.sleep(4000); }catch(InterruptedExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } mCamera.startPreview(); break; caseOPTION_STOPCAMERA: mPreview=null; setContentView(viewStart); break; } returntrue; } privatePictureCallbackjpegCallback=newPictureCallback(){ // publicvoidonPictureTaken(byte[]data,Cameracamera){ try{ Stringname=newDateFormat().format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA))+".jpg"; FileOutputStreamfileout=newFileOutputStream("/mnt/sdcard/sdcard/DCIM/"+name); System.out.println(name); fileout.write(data,0,data.length); fileout.flush(); fileout.close(); }catch(IOExceptione){ //TODO:handleexception System.out.println(e); } } }; classPreviewextendsSurfaceViewimplementsSurfaceHolder.Callback { Preview(Contextcontext) { super(context); mHolder=getHolder(); mHolder.addCallback(this); mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } publicvoidsurfaceCreated(SurfaceHolderholder) { mCamera=Camera.open(); try { mCamera.setPreviewDisplay(holder); } catch(IOExceptionexception) { mCamera.release(); mCamera=null; } } publicvoidsurfaceDestroyed(SurfaceHolderholder) { mCamera.stopPreview(); mCamera.release(); } @Override publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intw,inth){ //TODOAuto-generatedmethodstub Camera.Parametersparameters=mCamera.getParameters(); parameters.setPictureFormat(PixelFormat.JPEG); parameters.setPreviewSize(1024,1024); mCamera.setParameters(parameters); mCamera.setDisplayOrientation(90); mCamera.startPreview(); } } }
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android文件操作技巧汇总》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》、《Android视图View技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。