android自定义拍照界面SurfaceView+Camera

来源:互联网 发布:威武猫店铺淘宝客软件 编辑:程序博客网 时间:2024/05/16 16:04

前言:

在android开发中intent启动系统默认相机就能解决打不分的需求。但是对于一些有特殊要求的app,我们就需要自己实现一个拍照页面了。
其中重要知识点:
SurfaceView:用来显示拍照前预览的图像,使用方法让Activity继承SurfaceHolder.Callback接口,并实现他的三个方法(surfaceCreated,surfaceCreated和surfaceDestroyed)。
Camera:Camera对象用来获取显示的图像,其中camera.takePicture()是拍照方法,他的参数中PictureCallback()的回掉函数中的byte[] data是返回的图片数据

public classMainActivityextends ActivityimplementsSurfaceHolder.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
MainActivityextendsActivity implementsSurfaceHolder.Callback{
   
private staticContextcontext =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();
       
}
    }

   
/**
     *  将数据保存为文件
     *
@param
w
    
*@paramfileName
    
*@throwsException
     */
   
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;
       
}
    }

   
/**
     * 获取要保存的图片的分辨率(这里在相机支持的分辨率中,找了个最大的)(分辨率一般都是宽>高)
     *
@param
camera
    
*@return
    
*/
   
publicCamera.Sizeparameters(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();
获取相机支持像素列表,从中选一个,就不报错了。运行拍照,保存的图片是清除的。

效果图:


0 0