android自定义拍照界面SurfaceView+Camera

xiaoxiao2021-02-27  332

前言:

在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();

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

 

效果图:

 

转载请注明原文地址: https://www.6miu.com/read-5348.html

最新回复(0)