0%

Android 摄像头组件 Camera类的使用 自动对焦 拍照

今天的这个例子是要利用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"/>