Android自定义相机之Camera1
来源:互联网 发布:婴儿床的好处 知乎 编辑:程序博客网 时间:2024/06/15 21:26
一、概述
本章节主要讲述使用android.hardware.Camera类来实现自定义相机的流程,虽然在api21中该类已被废弃,有了一套新的CameraDevice方法,但是为了向下兼容我们还是可以学习一下Camera1的使用。
如有错误或优化之处,欢迎留言指导。
二、具体实现
首先介绍下如何判断是否支持照相机功能,代码如下:
private boolean checkCamera(Context context) { // 可修改参数来判断设备是否支持ble等其他功能 if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { return true; // 支持Camera功能 } else { return false; }}
获取一个Camera对象
private Camera getCamera() { Camera camera = null; try { camera = Camera.open(); } catch (Exception e) { Log.e(TAG, "getCamera: Camera.open failed!"); } return camera;}
我们通过SurfaceView来预览照相机画面,需要获取SurfaceHolder并添加回调
mPreView = (SurfaceView) findViewById(R.id.preview);mHolder = mPreView.getHolder();mHolder.addCallback(this); // 实现SurfaceHolder.Callback接口mPreView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mCamera != null) { // 照相机自动对焦功能 mCamera.autoFocus(null); } }});
绑定Camera和SurfaceHolder,然后开始预览画面
private void setStartPreview(Camera camera, SurfaceHolder holder) { try { camera.setPreviewDisplay(holder); // 绑定Camera和SurfaceHolder camera.setDisplayOrientation(90); // 旋转90度才是正常画面 camera.startPreview(); } catch (IOException e) { Log.e(TAG, "setStartPreview: setPreviewDisplay error"); }}
在使用完相机后需要释放相机资源,同时我们要注意把相机和活动的生命周期绑定,在onResume中获取相机并预览,在onPause中释放相机资源,防止其他应用调用相机时出错
private void releaseCamera() { if (mCamera != null) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; }}
SurfaceHolder.Callback接口有create,change,destroy三个方法,我们在create中初始化,在change中预览画面,在destroy前释放相机资源
@Override public void surfaceCreated(SurfaceHolder holder) { if (mCamera != null && mHolder != null) { setStartPreview(mCamera, mHolder); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (mCamera != null) { mCamera.stopPreview(); if (mHolder != null) { setStartPreview(mCamera, mHolder); } } } @Override public void surfaceDestroyed(SurfaceHolder holder) { releaseCamera(); }
最后就是点击拍照并获取图片,这里我们可以设置Camera.Parameters属性作用于我们要拍摄的照片,调用tackPicture方法进行拍照
Camera.Parameters parameters = mCamera.getParameters();parameters.setPictureFormat(ImageFormat.JPEG); // 相片保存的格式parameters.setPictureSize(800, 400); // 相片保存的尺寸,因为是横屏所以长>高parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // 自动对焦mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { // 拍照 mCamera.takePicture(null, null, mPictureCallback); } }});
takePicture的第一个参数是快门的回调,后面两个都是图像数据的回调,通常我们只需要实现第三个存储照片的回调就可以了
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { // 存储的路径及文件名 mFilePath = mFilePath + "/" + System.currentTimeMillis() + ".png"; File tempFile = new File(mFilePath); try { if (tempFile != null) { FileOutputStream fos = new FileOutputStream(tempFile); fos.write(data); fos.close(); Intent intent = new Intent(CameraActivity.this, PictureActivity.class); // 传给下一个显示照片的activity intent.putExtra("picPath", tempFile.getAbsolutePath()); startActivity(intent); finish(); } } catch (FileNotFoundException e) { Log.e(TAG, "onPictureTaken: " + e.getMessage()); } catch (IOException e) { Log.e(TAG, "onPictureTaken: " + e.getMessage() ); } }};
存储完照片后,我们可以从传递的路径获取到图片并显示
mImageView = (ImageView) findViewById(R.id.iv_picture);mPath = getIntent().getStringExtra("picPath");try { FileInputStream fis = new FileInputStream(new File(mPath)); Bitmap bitmap = BitmapFactory.decodeStream(fis); // 因为画面预览时是旋转后显示的,所以保存的图片也需要旋转90度 Matrix matrix = new Matrix(); matrix.setRotate(90); // 创建一个新的Bitmap bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); mImageView.setImageBitmap(bitmap);} catch (FileNotFoundException e) { Log.e(TAG, "onCreate: FileInputStream error");}
PS:自定义时请勿忘记申明权限
<uses-feature android:name="android.hardware.Camera" android:required="true" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.RECORD_AUDIO" />
三、后言
本章节实现步骤就介绍到这边,有错误欢迎指出,源码会在后续的综合demo中放出。下一章节准备学习记录一下Camera2的使用。
1 0
- Android自定义相机之Camera1
- camera1
- Android 自定义相机
- android自定义相机
- Android自定义相机
- android 自定义相机
- android 自定义相机
- android 自定义相机
- android自定义相机
- android自定义相机功能
- Android-自定义相机
- 自定义相机Camera-android
- android 自定义相机
- Android自定义相机
- Android自定义相机--2
- Android自定义相机
- Android自定义相机
- Android Camera2 自定义相机
- 使用C#压缩解压文件
- 在版本问题上解决 org.hibernate.MappingException: Unknown entit xxx
- 最终排名 (sdut oj)
- RT-Thread - 笔记1:使用STM32F0 官方BSP跑起来
- 1062. Talent and Virtue (25)
- Android自定义相机之Camera1
- [BZOJ3218][UOJ#77]A+B Problem(可持久化线段树+最小割)
- numpy矩阵属性知识小结
- Git 本地创建分支并提交远程分支
- Android开发之旅
- 前端问题(7)
- WEB中前台JS控制打印PDF文件
- 基于SSH实现免密码登陆
- 无条件百万级数据分页方案