欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android开发教程之调用摄像头功能的方法详解

程序员文章站 2024-03-04 20:18:00
本文实例讲述了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);//没有标题

接着设置全屏

复制代码 代码如下:
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(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程序设计有所帮助。