android自定义拍照界面SurfaceView+Camera

前言:

在android开发中intent启动系统默认相机就能解决打不分的需求。但是对于一些有特殊要求的app,我们就需要自己实现一个拍照页面了。

其中重要知识点:

SurfaceView:用来显示拍照前预览的图像,使用方法让Activity继承SurfaceHolder.Callback接口,并实现他的三个方法(surfaceCreated,surfaceCreated和surfaceDestroyed)。

Camera:Camera对象用来获取显示的图像,其中camera.takePicture()是拍照方法,他的参数中PictureCallback()的回掉函数中的byte[] data是返回的图片数据

 

public classMainActivity extends Activityimplements SurfaceHolder.Callback{

 

布局文件:

<?xml version="1.0"encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <SurfaceView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/surfaceview"/>
    <Button
        android:id="@+id/aaa"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="100dp"
        android:layout_marginStart="100dp"
        android:text="拍照"/>
    <Button
        android:id="@+id/bbb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="聚焦"
        android:layout_alignParentBottom="true"
        android:layout_toRightOf="@+id/aaa"
        android:layout_toEndOf="@+id/aaa"/>

</RelativeLayout>

 

java代码文件:

packagecom.example.administrator.xiaofang_jinan;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class MainActivityextends Activity implementsSurfaceHolder.Callback{
    private staticContext context =null;
    private SurfaceViewsurfaceview;
    private SurfaceHoldersurfaceholder;
    private Cameracamera =null;
    @Override
    protected voidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context= this;

        surfaceview= (SurfaceView)findViewById(R.id.surfaceview);
        surfaceholder= surfaceview.getHolder();
        surfaceholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceholder.addCallback(MainActivity.this);
       
        init();
    }

    private voidinit() {
        //拍照
        Button button= (Button) findViewById(R.id.aaa);
        button.setOnClickListener(newView.OnClickListener() {
            @Override
            public voidonClick(View v) {
                camera.takePicture(newCamera.ShutterCallback() {
                    @Override
                    public voidonShutter() {
                    }
                }, newCamera.PictureCallback() {
                    @Override
                    public voidonPictureTaken(byte[] data,Camera camera) {
                    }
                }, newCamera.PictureCallback() {
                    @Override
                    public voidonPictureTaken(byte[] data,Camera camera) {
                        String path = Environment.getExternalStorageDirectory() +"/test.jpg";
                        try {
                            data2file(data,path);
                        }catch (Exception e) {
                            Log.d("aabccdd","进入catch");
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
        //聚焦
        Button bbb= (Button) findViewById(R.id.bbb);
        bbb.setOnClickListener(newView.OnClickListener() {
            @Override
            public voidonClick(View v) {
                //自动聚焦
                camera.autoFocus(null);
            }
        });
    }

    @Override
    public voidsurfaceCreated(SurfaceHolder holder) {
        //获取camera对象
        camera= Camera.open();
        try {
            //获取camera参数(参数集合)
            Camera.Parameters parameters =camera.getParameters();
            //判断手机横向或纵向(手机竖着时图像是反的,需要旋转图像)
            if(this.getResources().getConfiguration().orientation
                    != Configuration.ORIENTATION_LANDSCAPE) {
                parameters.set("orientation","portrait");
                camera.setDisplayOrientation(90);
                parameters.setRotation(90);
            }else {
                parameters.set("orientation","landscape");
                camera.setDisplayOrientation(0);
                parameters.setRotation(0);
            }
            //获取图片分辨率(拍照的图片的分辨率是需要设置的,而且不能随便设置,不同的摄像头支持的分辨率不同,随便设置会报错)
            Camera.Size psize=parameters(camera);
            if(psize!=null)
            //设置照片的分辨率(不设置照片可能会模糊)
            parameters.setPictureSize(psize.width,psize.height);
            //将参数设置给camera对象
            camera.setParameters(parameters);
            //设置预览监听
            camera.setPreviewDisplay(holder);
            //启动摄像头预览
            camera.startPreview();
        }catch (IOException e) {
            e.printStackTrace();
            camera.release();
        }
    }

    @Override
    public voidsurfaceChanged(SurfaceHolder holder, intformat, intwidth, intheight) {
    }

    @Override
    public voidsurfaceDestroyed(SurfaceHolder holder) {
        if(camera!= null) {
            //停止浏览
            camera.stopPreview();
            camera.release();
        }
    }

    /**
     *  将数据保存为文件
     * @paramw
     *@param fileName
     *@throws Exception
     */
    private voiddata2file(byte[] w,String fileName) throws Exception {//将二进制数据转换为文件的函数
        FileOutputStream out =null;
        try {
            out =newFileOutputStream(fileName);
            out.write(w);
            out.close();
        }catch (Exception e) {
            Log.d("aabccdd","进入catch222");
            if (out !=null)
                out.close();
            throw e;
        }
    }

    /**
     * 获取要保存的图片的分辨率(这里在相机支持的分辨率中,找了个最大的)(分辨率一般都是宽>高)
     * @paramcamera
     *@return
     */
    publicCamera.Size parameters(Camera camera) {
        //照片支持的分辨率列表
        List<Camera.Size> pictureSizes = camera.getParameters().getSupportedPictureSizes();
        //预览画面的分辨率列表
        //List<Camera.Size> previewSizes = camera.getParameters().getSupportedPreviewSizes();
        Camera.Size psize;
        Camera.Size maxpsize=null;
        for (inti = 0;i < pictureSizes.size();i++) {
            psize = pictureSizes.get(i);
            Log.i("pictureSize","aaaaa"+psize.width+" x "+psize.height);
            if(maxpsize==null||maxpsize.width<psize.width){
                maxpsize=psize;
            }
        }
//        for (int i = 0; i < previewSizes.size(); i++) {
//            psize = previewSizes.get(i);
//            Log.i("previewSize","bbbbb"+psize.width+" x "+psize.height);
//        }
        returnmaxpsize;
    }

}

遇到的问题:

在开发时发现预览时画面是清楚的,但是拍照保存后,照片迷糊不清,就像被高度压缩了似得。

在网上查了查觉得应该是因为图片分辨率问题,于是手动设置了几个分辨率,也通过windowmessge获取屏幕分辨率,但是一到camera.setParameters(parameters);就会报异常。

最后找到原因,是因为自己设置的分辨率,相机不一定支持。

解决方法:

List<Camera.Size> pictureSizes = camera.getParameters().getSupportedPictureSizes();

获取相机支持像素列表,从中选一个,就不报错了。运行拍照,保存的图片是清除的。

 

效果图:

效果图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值