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
- android开发摄像头开发,在自己的SurfaceView里预览,并且解决摄像头预览变形问题--懒人笔记02
- Android学习【1】解决android摄像头预览的变形问题
- Android摄像头开发:实时摄像头视频预览帧的编码问题(二)
- Android摄像头开发:实时摄像头视频预览帧的编码问题
- Android摄像头开发:实时摄像头视频预览帧的编码问题(二)
- Android摄像头开发:实时摄像头视频预览帧的编码问题(二)
- android camera 摄像头预览画面变形
- Android开发 摄像头SurfaceView预览 背景带矩形框 实现(原理:双surfaceview,顶层画矩形框,底层预览视频)
- Android开发 摄像头SurfaceView预览 背景带矩形框 实现(原理:双surfaceview,顶层画矩形框,底层预览视频)
- Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback
- 大华摄像头java开发之预览
- android通过camera和surfaceview选择摄像头并即时预览
- Android相机(摄像头)圆形预览窗口,圆形SurfaceView
- Android摄像头非全屏预览,怎么保证图像不变形
- v310 摄像头调试笔记---QQ视频对方发现颜色不对, 有红块, 并且本地预览闪烁的问题
- Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用
- Android开发:实时处理摄像头预览帧视频------浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用
- Android开发:实时处理摄像头预览帧视频--浅析PreviewCallback,onPreviewFrame,AsyncTask的综合应用
- NIO与传统IO的区别 NIO Socket例子 实例
- 《javascript设计模式与开发实践》阅读笔记(三)
- intellij的tomcat工作目录问题
- 跨域
- 打开 Eclipse 报错信息Failed to load the JNI shared library jvm.dll
- android开发摄像头开发,在自己的SurfaceView里预览,并且解决摄像头预览变形问题--懒人笔记02
- JMeter录制脚本方法
- Android中提高后台服务进程优先级的方法
- Performance Optimization of UITableView
- yield(C# 参考)
- AngularJS入门(7)-Angular过滤器
- spring mvc定时器的使用
- hadoop-2.7.3源码编译
- js提交数组对象备份