android开发摄像头开发,在自己的SurfaceView里预览,并且解决摄像头预览变形问题--懒人笔记02

来源:互联网 发布:ubuntu登录密码忘记了 编辑:程序博客网 时间:2024/06/05 05:17

本来想只贴设置预览尺寸的部分了,后来想想就直接写个最简单的完整的demo吧

先在mainfeast中加入权限

<uses-feature android:name="android.hardware.camera" />    <uses-feature android:name="android.hardware.camera.autofocus" />    <uses-permission android:name="android.permission.CAMERA" />    <uses-permission android:name="android.permission.FLASHLIGHT" />


然后是anctivity_main文件中的代码

<pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <SurfaceView        android:id="@+id/main_surface_view"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <Button        android:id="@+id/main_button"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_gravity="bottom"        android:layout_margin="10dp"        android:text="拍照" /></FrameLayout>

先贴这两段代码的原因就是这两个文件是不用分步骤的写,而且一看就懂,不用做什么说明,当然你也可以用自己喜欢的布局,都一样的

接下来看MainActivity中的代码,

首先要做的事情就是把摄像里的东西显示到SurfaceView中去,不管显示成什么样子,先看到它有反应再说

第一个版本

</pre><pre>

package com.camerademo;import android.graphics.PixelFormat;import android.hardware.Camera;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.widget.Button;import android.widget.Toast;public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {    private SurfaceView surfaceView;//预览摄像头    private SurfaceHolder surfaceHolder;    private Button button;//拍照按钮    private Camera camera;//摄像头    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initData();        initListener();    }    //初始化View的方法,其实少的话都放到    private void initView() {        surfaceView = (SurfaceView) findViewById(R.id.main_surface_view);        button = (Button) findViewById(R.id.main_button);    }    private void initData() {        surfaceHolder = surfaceView.getHolder();        surfaceHolder.addCallback(this);    }    private void initListener() {        surfaceView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MainActivity.this, "surfaceView", Toast.LENGTH_SHORT).show();            }        });        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MainActivity.this, "button", Toast.LENGTH_SHORT).show();            }        });    }    private void initCamera() {        camera.startPreview();    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        try {            camera = Camera.open();            camera.setPreviewDisplay(surfaceHolder);        } catch (Exception e) {            if (null != camera) {                camera.release();                camera = null;            }            e.printStackTrace();            Toast.makeText(MainActivity.this, "启动摄像头失败,请开启摄像头权限", Toast.LENGTH_SHORT).show();        }    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        initCamera();    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        if (null != camera) {            camera.stopPreview();            camera.release();            camera = null;        }    }}



这个版本我们主要做的事情

1、为我们的程序添加摄像头相关权限

2、写一个简单的布局

3、找到layout中所有的View,并为View设置测试用的监听

4、实现一个SurfaceHolder.CallBack,赋给SurfaceHolder,并且在OnSurfaceCreated里获取Camera实例,将SurfaceHolder赋给camera实例,在onSurfaceChange里面显示预览,在onSurfaceDestroy里面停止预览并且释放掉camera实例(这里可能有点绕,多过几遍代码就好了)

程序写完以后当然是迫不及待的运行一下,果不其然,界面上是有反应的,但是跟我们想象中的好像还有些不一样,界面显示出来的东西好像被旋转了,旋转屏幕观察下(现象自己观察咯)

这个处理方法有很多,可以直接将这个activity在mainfeast中设置成横屏,为了尽量多的用到API,我选择让这个activity默认竖屏

默认竖屏的代码,在mainfeast中,下边代码红色的部分让activity竖屏

<activity android:name=".MainActivity"            <span style="color:#ff0000;">android:screenOrientation="portrait"</span>            >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>
竖屏以后屏幕中的预览还是旋转了90度呢,我们在MainActivity中的initCamera方法中加一些代码,红色的部分为新加的代码

private void initCamera() {        camera.startPreview();//开始预览        camera.setDisplayOrientation(90);//将预览旋转90度    }
好,加了上边几行代码后我们再运行一下吧,发现图像是转过来了哈,不过貌似不是所有的手机看上去都正常,不出意外的话应该是有些手机的预览图像是会有变形的,android开发处处是坑哈,下边我们接着处理变形问题
继续在MainActivity中的initCamera方法中加代码

private void initCamera() {        Camera.Parameters parameters = camera.getParameters();//获取camera的parameter实例        List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();//获取所有支持的camera尺寸        Camera.Size optionSize = getOptimalPreviewSize(sizeList, surfaceView.getWidth(), surfaceView.getHeight());//获取一个最为适配的camera.size        parameters.setPreviewSize(optionSize.width,optionSize.height);//把camera.size赋值到parameters        camera.setParameters(parameters);//把parameters设置给camera        camera.startPreview();//开始预览        camera.setDisplayOrientation(90);//将预览旋转90度    }
咦,楼主你是不是在坑我,根本就没有getOptimalPreviewSize这个方法啊,别着急嘛,下边我给你贴出来,这个放我我抄的别人的,不是我写的啊,不过好用
getOptimalPreviewSize方法

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {        final double ASPECT_TOLERANCE = 0.1;        double targetRatio = (double) w / h;        if (sizes == null) return null;        Size optimalSize = null;        double minDiff = Double.MAX_VALUE;        int targetHeight = h;        // Try to find an size match aspect ratio and size        for (Size size : sizes) {            double ratio = (double) size.width / size.height;            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;            if (Math.abs(size.height - targetHeight) < minDiff) {                optimalSize = size;                minDiff = Math.abs(size.height - targetHeight);            }        }        // Cannot find the one match the aspect ratio, ignore the requirement        if (optimalSize == null) {            minDiff = Double.MAX_VALUE;            for (Size size : sizes) {                if (Math.abs(size.height - targetHeight) < minDiff) {                    optimalSize = size;                    minDiff = Math.abs(size.height - targetHeight);                }            }        }        return optimalSize;    }
运行一下程序,好啦,变形问题和旋转问题解决了,下边加点击屏幕自动对焦,直接上代码吧,也没什么好说的
package com.camerademo;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.PixelFormat;import android.hardware.Camera;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;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 android.widget.Toast;import java.util.List;public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {    private SurfaceView surfaceView;//预览摄像头    private SurfaceHolder surfaceHolder;    private Button button;//拍照按钮    private Camera camera;    <span style="color:#ff0000;">private Camera.AutoFocusCallback myAutoFocusCallback1 = null;//只对焦不拍照    public static final int only_auto_focus = 110;    int issuccessfocus = 0;</span>    <span style="color:#ff0000;">private Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg) {            // TODO Auto-generated method stub            super.handleMessage(msg);            switch (msg.what) {                case only_auto_focus:                    if (camera != null)                        camera.autoFocus(myAutoFocusCallback1);                    break;            }        }    };</span>    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initView();        initData();        initListener();    }    private void initView() {        surfaceView = (SurfaceView) findViewById(R.id.main_surface_view);        button = (Button) findViewById(R.id.main_button);    }    private void initData() {        surfaceHolder = surfaceView.getHolder();        surfaceHolder.addCallback(this);        <span style="color:#ff0000;">myAutoFocusCallback1 = new Camera.AutoFocusCallback() {            public void onAutoFocus(boolean success, Camera camera) {                // TODO Auto-generated method stub                if (success)//success表示对焦成功                {                    issuccessfocus++;                    if (issuccessfocus <= 1)                        mHandler.sendEmptyMessage(only_auto_focus);                    Log.i("qtt", "myAutoFocusCallback1: success..." + issuccessfocus);                } else {                    //if (issuccessfocus == 0) {                    mHandler.sendEmptyMessage(only_auto_focus);                    //}                    Log.i("qtt", "myAutoFocusCallback1: 失败...");                }            }        };</span>    }    private void initListener() {        surfaceView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                if (camera != null) {                    if (camera != null)                        camera.autoFocus(myAutoFocusCallback1);                }            }        });        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Toast.makeText(MainActivity.this, "button", Toast.LENGTH_SHORT).show();            }        });    }    private void initCamera() {        Camera.Parameters parameters = camera.getParameters();//获取camera的parameter实例        List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();//获取所有支持的camera尺寸        Camera.Size optionSize = getOptimalPreviewSize(sizeList, surfaceView.getWidth(), surfaceView.getHeight());//获取一个最为适配的屏幕尺寸        parameters.setPreviewSize(optionSize.width, optionSize.height);//把只存设置给parameters        camera.setParameters(parameters);//把parameters设置给camera上        camera.startPreview();//开始预览        camera.setDisplayOrientation(90);//将预览旋转90度    }    @Override    public void surfaceCreated(SurfaceHolder holder) {        try {            camera = Camera.open();            camera.setPreviewDisplay(surfaceHolder);        } catch (Exception e) {            if (null != camera) {                camera.release();                camera = null;            }            e.printStackTrace();            Toast.makeText(MainActivity.this, "启动摄像头失败,请开启摄像头权限", Toast.LENGTH_SHORT).show();        }    }    @Override    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {        initCamera();    }    @Override    public void surfaceDestroyed(SurfaceHolder holder) {        if (null != camera) {            camera.setPreviewCallback(null);            camera.stopPreview();            camera.release();            camera = null;        }    }    private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {        final double ASPECT_TOLERANCE = 0.1;        double targetRatio = (double) w / h;        if (sizes == null) return null;        Camera.Size optimalSize = null;        double minDiff = Double.MAX_VALUE;        int targetHeight = h;        // Try to find an size match aspect ratio and size        for (Camera.Size size : sizes) {            double ratio = (double) size.width / size.height;            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;            if (Math.abs(size.height - targetHeight) < minDiff) {                optimalSize = size;                minDiff = Math.abs(size.height - targetHeight);            }        }        // Cannot find the one match the aspect ratio, ignore the requirement        if (optimalSize == null) {            minDiff = Double.MAX_VALUE;            for (Camera.Size size : sizes) {                if (Math.abs(size.height - targetHeight) < minDiff) {                    optimalSize = size;                    minDiff = Math.abs(size.height - targetHeight);                }            }        }        return optimalSize;    }}

就到这里吧,拍照的话与自动对焦的套路差不过,用到了camera.tackpicture方法,这篇就到这里吧




1 0
原创粉丝点击