左岸团队: 申洪健 肖凯
摘要
Google于2007年11月5日宣布的基于Linux平台的android系统-----首个为移动终端打造的真正开放和完整的移动软件。Android出身豪门,并以其完美的开放性获得了众多开发人员的青睐。在多媒体应用非常普及的今天,很多应用软件需要完成对手机内置相机的调用来实现软件的功能,在我们的左岸易记个人记账软件的储蓄罐模块中也需要实现调用手机内置摄像头的功能,本文正是在我们开发软件的基础上,对于android开发平台上对相机调用的一些认识和见解。内容主要有相机的调用、预览设置、图片设置及传输,并附上源码以供参考。
关键词 android camera
正文
android平台由操作系统、中间件、用户界面和应用软件组成。它采用软件堆层的架构,主要分为三部分。底层以Linux内核工作为基础,由C语言开发,只提供基本功能;中间层包括函数库Library和虚拟机Virtual Machine,由C++开发。最上层是各种应用软件,包括通话程序,短信程序等,应用软件则由各公司自行开发,以Java作为编写程序的一部分。
android提供了操作摄像头的API,可以通过两种做法来使用:
通过Intent直接调用系统提供的照相机功能,复用它的拍照Activity,这是最简单和最方便的办法,因为你不需要考虑手机的兼容性问题,比如预览拍照图片大小等;
Intent intent = new Intent();
Intent.setAction(“android.media.action.STILL_IMAGE_CAMERA”);
startActivity(intent);
默认情况下,如果在intent中不做设置,也就是不写这部分:
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri
.fromFile(new File(Environment
.getExternalStorageDirectory(), "camera.jpg")));
那么当从照相机Activity返回的时候,会带一个名为data的Bitmap对象。是照片的缩略图(这也是为什么有些照片会比较小的原因)。
如果写上面的代码,则不会返回名为data的对象。但是会按照指定的路径保存原始图片。
直接调用摄像头的API,自己编写类似取景框的Activity,这样灵活度更大,缺点是你需要考虑比较底层的东西。要知道android有多个版本,摄像头的分辨率也不一样,需要先获取当前相机的分辨率组合,然后再编写各种屏幕分辨率组合的布局。
以下是具体的代码解析:
import java.io.IOException;
import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
public class CameraPreview extends Activity
{
private Preview preview;
private ImageView ivFocus;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
preview = new Preview(this);
setContentView(preview);
ivFocus = new ImageView(this);
}
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
preview.takePicture();
return super.onTouchEvent(event);
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
{
preview.takePicture();
}
return super.onKeyDown(keyCode, event);
}
class Preview extends SurfaceView implements SurfaceHolder.Callback
{
private SurfaceHolder holder;
private Camera camera;
// 创建一个PictureCallback对象,并实现其中的onPictureTaken方法
private PictureCallback pictureCallback = new PictureCallback()
{
// 该方法用于处理拍摄后的照片数据
@Override
public void onPictureTaken(byte[] data, Camera camera)
{
// data就是照片数据
getIntent().putExtra("bytes", data);
//resultCode 设为20
setResult(20, getIntent());
// 停止照片拍摄
camera.stopPreview();
camera = null;
// 关闭当前的Activity
finish();
}
};
public Preview(Context context)
{
super(context);
holder = this.getHolder();
// 指定用于捕捉拍照事件的SurfaceHolder.Callback对象
holder.addCallback(this);
// 设置SurfaceHolder对象的类型
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
// 开始拍照时调用该方法
public void surfaceCreated(SurfaceHolder holder)
{
camera = Camera.open();
try
{
camera.setPreviewDisplay(holder);
}
catch (IOException exception)
{
// 释放手机摄像头
camera.release();
camera = null;
}
}
// 停止拍照时调用该方法
public void surfaceDestroyed(SurfaceHolder holder)
{
// 释放手机摄像头
camera.stopPreview();
camera.release();
camera = null;
}
// 拍照状态变化时调用该方法
public void surfaceChanged(final SurfaceHolder holder, int format, int w, int h)
{
try
{
Camera.Parameters parameters = camera.getParameters();
// 设置照片格式
parameters.setPictureFormat(PixelFormat.JPEG);
// 根据屏幕方向设置预浏尺寸
//if (getWindowManager().getDefaultDisplay().getOrientation() == 0)
// parameters.setPreviewSize(h, w);
//else
parameters.setPreviewSize(w, h);
// 设置拍摄照片的实际分辨率,在本例中的分辨率是1024*768
//parameters.setPictureSize(1024, 768);
// 设置保存的图像大小
camera.setParameters(parameters);
// 开始拍照
camera.startPreview();
// 准备用于表示对焦状态的图像(对焦符号)
ivFocus.setImageResource(R.drawable.icon);
LayoutParams layoutParams = new LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
ivFocus.setScaleType(ScaleType.CENTER);
addContentView(ivFocus, layoutParams);
ivFocus.setVisibility(VISIBLE);
// 自动对焦
camera.autoFocus(new AutoFocusCallback()
{
public void onAutoFocus(boolean success, Camera camera)
{
if (success)
{
&nbs