Android开发教程之调用摄像头功能的方法详解
本文实例讲述了android调用摄像头功能的方法。分享给大家供大家参考,具体如下:
我们要调用摄像头的拍照功能,显然
第一步必须加入调用摄像头硬件的权限,拍完照后我们要将图片保存在sd卡中,必须加入sd卡读写权限,所以第一步,我们应该在android清单文件中加入以下代码
摄像头权限:
<uses-permission android:name="android.permission.camera"/>
sd卡读写权限:
<uses-permission android:name="android.permission.mount_unmount_filesystems" /> <uses-permission android:name="android.permission.write_external_storage"/>
第二步,要将摄像头捕获的图像实时地显示在手机上。
我们是用surfaceview这个视图组件来实现的,因此在main.xml中加入下列代码
<surfaceview android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/surfaceview" />
第三步,设置窗口的显示方式
首先获得当前窗口
window window = getwindow();//得到窗口
接着设置没有标题
requestwindowfeature(window.feature_no_title);//没有标题
接着设置全屏
当然,我们在拍照过程中,屏幕必须一致处于高亮状态,因此接着加入下面代码
至此,我们将窗口的显示方式规定死了,然后才能设置窗口上显示的组件(顺序非常重要)
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(new surfacecallback());
上面的回调类是我们自己定义的,代码如下
private class surfacecallback implements surfaceholder.callback{ @override public void surfacecreated(surfaceholder holder) { try { camera = camera.open();//打开硬件摄像头,这里导包得时候一定要注意是android.hardware.camera windowmanager wm = (windowmanager) getsystemservice(context.window_service);//得到窗口管理器 display display = wm.getdefaultdisplay();//得到当前屏幕 camera.parameters parameters = 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 (ioexception e) { log.e(tag, e.tostring()); } } @override public void surfacechanged(surfaceholder holder, int format, int width, int height) { // todo auto-generated method stub } @override public void surfacedestroyed(surfaceholder holder) { if(camera!=null){ if(ispreview){//如果正在预览 camera.stoppreview(); camera.release(); } } } }
第六步,我们必须对按键事件进行监听,如是拍照还是聚焦,代码如下
public boolean onkeydown(int keycode, keyevent event) {//处理按键事件 if(camera!=null&&event.getrepeatcount()==0)//代表只按了一下 { switch(keycode){ case keyevent.keycode_back://如果是搜索键 camera.autofocus(null);//自动对焦 break; case keyevent.keycode_dpad_center://如果是中间键 camera.takepicture(null, null, new takepicturecallback());//将拍到的照片给第三个对象中,这里的takepicturecallback()是自己定义的,在下面的代码中 break; } } return true;//阻止事件往下传递,否则按搜索键会变成系统默认的 }
private final class takepicturecallback implements picturecallback{ public void onpicturetaken(byte[] data, camera camera) { try { bitmap bitmap = bitmapfactory.decodebytearray(data, 0, data.length); file file = new file(environment.getexternalstoragedirectory(),system.currenttimemillis()+".jpg"); fileoutputstream outputstream = new fileoutputstream(file); bitmap.compress(compressformat.jpeg, 100, outputstream); outputstream.close(); camera.stoppreview(); camera.startpreview();//处理完数据之后可以预览 } catch (exception e) { log.e(tag, e.tostring()); } } }
注意,代码中有两个回调类,一个是surfacecallback(),另外一个是takepicturecallback(),初学者可能一时难以理解,通俗地讲,前者是用来监视surficeview这个暂时存放图片数据的显示控件的,根据它的显示情况调用不同的方法,包括surfacecreated(),surfacechanged(),surfacedestroyed(),也就不难理解为什么会有这三个回调方法了(注意,在surfacedestroyed()方法中必须释放摄像头,详细代码参见上方)。takepicturecallback()是为了监视是否拍照而设计的接口,期中也仅有一个方法,camera将拍照得到的数据传入方法,我们便可以对拍照得到的数据进行进一步处理了。
至此,简单的拍照功能介绍完毕!
package cn.camera.rxm; import java.io.file; import java.io.fileoutputstream; import java.io.ioexception; import java.util.calendar; import java.util.locale; import org.apache.commons.logging.log; import android.text.format.dateformat; import android.util.*; import android.app.activity; import android.content.context; import android.graphics.bitmap; import android.graphics.bitmap.compressformat; import android.graphics.bitmapfactory; import android.graphics.pixelformat; import android.hardware.camera; import android.hardware.camera.picturecallback; import android.os.bundle; import android.os.environment; import android.view.layoutinflater; import android.view.menu; import android.view.menuitem; import android.view.surfaceholder; import android.view.surfaceview; import android.view.view; import android.view.view.onclicklistener; import android.widget.button; //import android.widget.toast; public class mycamactivity extends activity { private preview mpreview; private camera mcamera; bitmap camerabitmap; surfaceholder mholder; private static final int option_snapshot = 0; private static final int option_stopcamera = 1; private view viewstart; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); layoutinflater flater = this.getlayoutinflater(); viewstart = flater.inflate(r.layout.main, null); setcontentview(viewstart); button btn1 = (button)findviewbyid(r.id.button1); btn1.setonclicklistener( new onclicklistener(){ public void onclick(view v){ mpreview = new preview(getbasecontext()); setcontentview(mpreview); }; } ); } public boolean oncreateoptionsmenu(menu menu){ // menu.add(0, option_snapshot, 0, r.string.take); // menu.add(0, option_stopcamera, 1, r.string.back); // return true;//super.oncreateoptionsmenu(menu); } public boolean onoptionsitemselected(menuitem item) { // int itemid = item.getitemid(); // switch(itemid){ case option_snapshot: //拍摄照片 mcamera.takepicture(null, null, jpegcallback); try { thread.sleep(4000); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } mcamera.startpreview(); break; case option_stopcamera: mpreview = null; setcontentview(viewstart); break; } return true; } private picturecallback jpegcallback = new picturecallback(){ // public void onpicturetaken(byte[] data, camera camera) { try { string name = new dateformat().format("yyyymmdd_hhmmss", calendar.getinstance(locale.china)) + ".jpg"; fileoutputstream fileout = new fileoutputstream("/mnt/sdcard/sdcard/dcim/"+ name); system.out.println(name); fileout.write(data,0,data.length); fileout.flush(); fileout.close(); } catch (ioexception e) { // todo: handle exception system.out.println(e); } } }; class preview extends surfaceview implements surfaceholder.callback { preview(context context) { super(context); mholder=getholder(); mholder.addcallback(this); mholder.settype(surfaceholder.surface_type_push_buffers); } public void surfacecreated(surfaceholder holder) { mcamera=camera.open(); try { mcamera.setpreviewdisplay(holder); } catch(ioexception exception) { mcamera.release(); mcamera=null; } } public void surfacedestroyed(surfaceholder holder) { mcamera.stoppreview(); mcamera.release(); } @override public void surfacechanged(surfaceholder holder, int format, int w, int h) { // todo auto-generated method stub camera.parameters parameters=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程序设计有所帮助。