今天的这个例子是要利用android.hardware.Camera类实现类似Android系统自带相机的功能,可以动态预览摄像头拍到的画面,可以拍照并存到SD卡,支持自动对焦。暂时还没有实现录像功能。经真机测试,以下代码可以在关屏时正常拍照,但在Service中无法运行,即使亮着屏幕,原因未知。 布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="1">
<SurfaceView android:id="@+id/surfaceView1" android:layout_width="320dp" android:layout_height="220dp"/>
<LinearLayout android:layout_height="wrap_content" android:id="@+id/linearLayout1" android:layout_width="fill_parent">
<Button android:text="拍照" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
<ImageView android:layout_height="220dp" android:id="@+id/imageView1" android:layout_width="320dp"></ImageView>
</LinearLayout>
一个 SurfaceView用于实时显示摄像头拍摄到的画面,一个控制拍照的按钮,还有一个ImageView,拍到照片后会把拍到的图片显示在这里。 Java代码:
package com.pocketdigi.camera;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
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.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
public class CameraActivity extends Activity implements SurfaceHolder.Callback {
/** Called when the activity is first created. */
SurfaceHolder surfaceHolder;
SurfaceView surfaceView1;
Button button1;
ImageView imageView1;
Camera camera;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
button1=(Button)findViewById(R.id.button1);
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//设为横向显示。因为摄像头会自动翻转90度,所以如果不横向显示,看到的画面就是翻转的。
//本例中不横向
surfaceView1=(SurfaceView)findViewById(R.id.surfaceView1);
imageView1=(ImageView)findViewById(R.id.imageView1);
surfaceHolder=surfaceView1.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
button1.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
camera.autoFocus(afcb);
//自动对焦
}});
}
PictureCallback jpeg =new PictureCallback(){
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Bitmap bmp=BitmapFactory.decodeByteArray(data, 0, data.length);
//byte数组转换成Bitmap
imageView1.setImageBitmap(bmp);
//拍下图片显示在下面的ImageView里
FileOutputStream fop;
try {
fop=new FileOutputStream("/sdcard/dd.jpg");
//实例化FileOutputStream,参数是生成路径
bmp.compress(Bitmap.CompressFormat.JPEG, 100, fop);
//压缩bitmap写进outputStream 参数:输出格式 输出质量 目标OutputStream
//格式可以为jpg,png,jpg不能存储透明
fop.close();
System.out.println("拍成功");
//关闭流
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("FileNotFoundException");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("IOException");
}
camera.startPreview();
//需要手动重新startPreview,否则停在拍下的瞬间
}
};
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
camera=Camera.open();
try {
Camera.Parameters parameters=camera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
//每台机器可用的PreviewSize不同,可以parameters.getSupportedPreviewSizes();获取支持的size
parameters.setPreviewSize(320, 220);
camera.setParameters(parameters);
//设置参数
camera.setPreviewDisplay(surfaceHolder);
//摄像头画面显示在Surface上
camera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
System.out.println("surfaceDestroyed");
camera.stopPreview();
//关闭预览
camera.release();
//释放资源
}
AutoFocusCallback afcb= new AutoFocusCallback(){
@Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
if(success){
//对焦成功才拍照
camera.takePicture(null, null, jpeg);
}
}
};
}
在AndroidManifest.xml中要添加拍照及写入存储卡权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>