Android 自定义Camera全屏拍照,支持前后摄像头
来源:互联网 发布:java导入自己的package 编辑:程序博客网 时间:2024/06/05 13:31
最近项目中一直在调用系统相机拍照,而产品总是要求拍照页面向iOS看齐,真是很头疼啊。但问题还是存在,有必要搞一个自定义的啦。在网上搜索了一段时间后,发现还真不是那么好实现的,实践之后,总结一些要点如下:
1.camera的parameters设置总是会提示出setParamters failed的异常
2.预览和图片的尺寸设置
3.预览图片变形
4.自动聚焦
5.保存的图片旋转角度
以上是我遇到的难点,并将之一一解决后的总结。
第1个问题,setPreviewFrameRate和setPreviewSize不能放在一起使用,否则set的时候必然报错,这个也是在查看了源代码后发现的。
第2个问题,每个手机都有自己支持的尺寸集合,并不是设置一个固定的宽高就可以的,所以要想设置尺寸,一定是先获取手机支持的尺寸,而且排序也不一样,有的从大到小,有的从小到大。没办法,开源嘛。
第3个问题就是surfaceview的尺寸大小,设置的不对的话,会导致预览变形,这个要和预览尺寸配合着设置
第4个问题比较容易解决一点,网上有很多种设置方式,但是最好用的就是使用重力加速度类型的传感器来实现,这个效果是最好的,在配合上触屏操作时也加上自动聚焦功能,就能保证自动聚焦这个功能完美的实现了。
第5个问题就是拍照会转动手机在各种角度拍照,那么获取的图片显示的时候有要求的需要根据角度重新生成bitmap,然后再显示啦。这个使用Matrix类就能实现,但是难点在于如何获取到正确的旋转角度。通常都会使用getWindowManager().getDefaultDisplay().getRotation();这个方法,但是当我将这个相机Activity设置成portrait时,这个方法是无效的,因此必须使用OrientationEventListener这个监听器,其实这个也是利用传感器实现的方向监听。
好了,以上总是我遇到的一些问题,以及一些总结,下面直接贴出代码,就不上传工程啦。所有的代码都写在一个activity里面了,还没有做架构抽象,感兴趣的小伙伴可以抽象一下,反馈给我,呵呵。
CameraManager.java
import android.content.Context;import android.graphics.PixelFormat;import android.graphics.Point;import android.graphics.Rect;import android.hardware.Camera;import android.media.AudioManager;import android.media.MediaPlayer;import android.net.Uri;import android.view.SurfaceHolder;import android.widget.Toast;import java.io.IOException;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;/** * Created by zouguibao on 2017/11/23. */public class CameraManger { private static CameraManger instance; private Camera camera; private MediaPlayer mShootSound; public static final int TYPE_PREVIEW = 0; public static final int TYPE_PICTURE = 1; public static final int ALLOW_PIC_LEN = 2000; //最大允许的照片尺寸的长度 宽或者高 private int cameraPosition; private CameraManger() { } public static CameraManger getInstance() { if (instance == null) { instance = new CameraManger(); } return instance; } /** * 打开摄像头 * * @param holder * @param autoFocusCallback * @param degree */ public void openCamera(SurfaceHolder holder, Camera.AutoFocusCallback autoFocusCallback, int degree) { try { //初始化摄像头 cameraPosition = Camera.CameraInfo.CAMERA_FACING_BACK; // 打开摄像头 camera = Camera.open(cameraPosition); // 设置用于显示拍照影像的SurfaceHolder对象 camera.setPreviewDisplay(holder); camera.setDisplayOrientation(degree); camera.autoFocus(autoFocusCallback); } catch (Exception e) {// e.printStackTrace(); camera.release(); camera = null; } } /** * 设置参数 */ public void setCameraParameters(int screenWidth, int screenHeight) { try { if (camera != null) { Camera.Parameters parameters = camera.getParameters();//获取各项参数 Camera.Size previewSize = findFitPreResolution(parameters); parameters.setPreviewSize(previewSize.width, previewSize.height);// 设置预览大小 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); parameters.setPictureFormat(PixelFormat.JPEG);//设置图片格式 //不能与setPreviewSize一起使用,否则setParamters会报错// parameters.setPreviewFrameRate(5);//设置每秒显示4帧 parameters.setJpegQuality(80);// 设置照片质量 Camera.Size pictureSize = null; if (equalRate(screenWidth, screenHeight, 1.33f)) { pictureSize = findFitPicResolution(parameters, (float) 4 / 3); } else { pictureSize = findFitPicResolution(parameters, (float) 16 / 9); } parameters.setPictureSize(pictureSize.width, pictureSize.height);// 设置保存的图片尺寸 camera.setParameters(parameters); camera.startPreview(); } } catch (Exception e) { e.printStackTrace(); } } private boolean equalRate(int width, int height, float rate) { float r = (float) width / (float) height; if (Math.abs(r - rate) <= 0.2) { return true; } else { return false; } } /** * 摄像头切换 * * @param holder * @param autoFocusCallback * @param degree */ public void turnCamera(SurfaceHolder holder, Camera.AutoFocusCallback autoFocusCallback, int degree, int screenWidth, int screenHeight) { //切换前后摄像头 //现在是后置,变更为前置 if (camera != null && cameraPosition == Camera.CameraInfo.CAMERA_FACING_BACK) { camera.stopPreview();//停掉原来摄像头的预览 camera.release();//释放资源 camera = null;//取消原来摄像头 camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);//打开当前选中的摄像头 try { camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面 camera.setDisplayOrientation(degree); camera.autoFocus(autoFocusCallback); setCameraParameters(screenWidth, screenHeight); } catch (IOException e) { e.printStackTrace(); } camera.startPreview();//开始预览 cameraPosition = Camera.CameraInfo.CAMERA_FACING_FRONT; DataUtils.isBackCamera = false; } else if (cameraPosition == Camera.CameraInfo.CAMERA_FACING_FRONT) { //代表摄像头的方位,CAMERA_FACING_FRONT前置 // CAMERA_FACING_BACK后置 //现在是前置, 变更为后置 camera.stopPreview();//停掉原来摄像头的预览 camera.release();//释放资源 camera = null;//取消原来摄像头 camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);//打开当前选中的摄像头 try { camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面 camera.setDisplayOrientation(degree); camera.autoFocus(autoFocusCallback); setCameraParameters(screenWidth, screenHeight); } catch (IOException e) { e.printStackTrace(); } camera.startPreview();//开始预览 cameraPosition = Camera.CameraInfo.CAMERA_FACING_BACK; DataUtils.isBackCamera = true; } } public void setCameraZoom(int scale) { Camera.Parameters parameters = camera.getParameters(); int zoom = parameters.getZoom() + scale; if (zoom < 0) zoom = 0; if (zoom > parameters.getMaxZoom()) zoom = parameters.getMaxZoom(); parameters.setZoom(zoom); camera.setParameters(parameters); } public boolean setCameraFocusAreas(Point point) { if (camera == null) { return false; } Camera.Parameters parameters = null; try { parameters = camera.getParameters(); } catch (Exception e) { e.printStackTrace(); return false; } //不支持设置自定义聚焦,则使用自动聚焦,返回 if (parameters.getMaxNumFocusAreas() <= 0) { return false; } List<Camera.Area> areas = new ArrayList<Camera.Area>(); int left = point.x - 300; int top = point.y - 300; int right = point.x + 300; int bottom = point.y + 300; left = left < -1000 ? -1000 : left; top = top < -1000 ? -1000 : top; right = right > 1000 ? 1000 : right; bottom = bottom > 1000 ? 1000 : bottom; areas.add(new Camera.Area(new Rect(left, top, right, bottom), 100)); parameters.setFocusAreas(areas); try { //本人使用的小米手机在设置聚焦区域的时候经常会出异常,看日志发现是框架层的字符串转int的时候出错了, //目测是小米修改了框架层代码导致,在此try掉,对实际聚焦效果没影响 camera.setParameters(parameters); } catch (Exception e) {// e.printStackTrace(); return false; } return true; } public void setCameraAutoFocus(Camera.AutoFocusCallback autoFocusCallback) { try { if (camera != null) camera.autoFocus(autoFocusCallback); } catch (Exception e) { e.printStackTrace(); } } /** * 拍照 * * @param context * @param pictureCallback */ public void takePicture(final Context context, Camera.PictureCallback pictureCallback) { if (camera != null) { //拍照 try{ camera.takePicture(new Camera.ShutterCallback() { @Override public void onShutter() { try { AudioManager meng = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); int volume = meng.getStreamVolume(AudioManager.STREAM_NOTIFICATION); if (volume != 0) { if (mShootSound == null) { mShootSound = MediaPlayer.create(context, Uri.parse("file:///system/media/audio/ui/camera_click.ogg")); } if (mShootSound != null) { mShootSound.start(); } } } catch (Exception e) { } } }, null, pictureCallback); }catch (Exception e){ Toast.makeText(context,"拍照出现异常,请退出重新进入拍照",Toast.LENGTH_SHORT).show(); } } } public void closeShutterSound() { if (mShootSound != null) { mShootSound.release(); } } /** * 重拍 */ public void startPreview() { if (camera != null) { camera.startPreview(); } } /** * 停止拍摄 */ public void stopPreview() { camera.stopPreview(); } /** * 销毁摄像头 */ public void destroyCamera() { if (camera != null) { //当surfaceview关闭时,关闭预览并释放资源 camera.stopPreview(); camera.release();//释放相机 camera = null; } } /** * 返回最小的预览尺寸 * * @param cameraInst * @param type * @return */ private Camera.Size findMinResolution(Camera cameraInst, int type) throws Exception { Camera.Parameters cameraParameters = cameraInst.getParameters(); List<Camera.Size> supportedPicResolutions = type == TYPE_PREVIEW ? cameraParameters.getSupportedPreviewSizes() : cameraParameters.getSupportedPictureSizes(); // 至少会返回一个值 if (supportedPicResolutions == null) { return null; } Camera.Size resultSize = supportedPicResolutions.get(0); for (Camera.Size size : supportedPicResolutions) { if (size.width < resultSize.width) { resultSize = size; } } return resultSize; } /** * 找到合适的尺寸 * * @param cameraParameters * @param maxDistortion 最大允许的宽高比 * @return * @type 尺寸类型 0:preview 1:picture */ public Camera.Size findBestResolution(Camera.Parameters cameraParameters, double maxDistortion, int type) throws Exception { List<Camera.Size> supportedPicResolutions = type == TYPE_PREVIEW ? cameraParameters.getSupportedPreviewSizes() : cameraParameters.getSupportedPictureSizes(); // 至少会返回一个值// StringBuilder picResolutionSb = new StringBuilder();// for (Camera.Size supportedPicResolution : supportedPicResolutions) {// picResolutionSb.append(supportedPicResolution.width).append('x')// .append(supportedPicResolution.height).append(" ");// }//// Log.d(TAG, "Supported picture resolutions: " + picResolutionSb);//// Camera.Size defaultPictureResolution = cameraParameters.getPictureSize();// Log.d(TAG, "default picture resolution " + defaultPictureResolution.width + "x"// + defaultPictureResolution.height); // 排序 List<Camera.Size> sortedSupportedPicResolutions = new ArrayList<Camera.Size>( supportedPicResolutions); Collections.sort(sortedSupportedPicResolutions, new Comparator<Camera.Size>() { @Override public int compare(Camera.Size a, Camera.Size b) { int aRatio = a.width / a.height; int bRatio = b.width / a.height; if (Math.abs(aRatio - 1) <= Math.abs(bRatio - 1)) { return -1; } else { return 1; } } }); //返回最合适的 return sortedSupportedPicResolutions.get(sortedSupportedPicResolutions.size() - 1); } /** * 返回合适的照片尺寸参数 * * @param cameraParameters * @param bl * @return */ private Camera.Size findFitPicResolution(Camera.Parameters cameraParameters, float bl) throws Exception { List<Camera.Size> supportedPicResolutions = cameraParameters.getSupportedPictureSizes(); Camera.Size resultSize = null; for (Camera.Size size : supportedPicResolutions) { if ((float) size.width / size.height == bl && size.width <= ALLOW_PIC_LEN && size.height <= ALLOW_PIC_LEN) { if (resultSize == null) { resultSize = size; } else if (size.width > resultSize.width) { resultSize = size; } } } if (resultSize == null) { return supportedPicResolutions.get(0); } return resultSize; } /** * 返回合适的预览尺寸参数 * * @param cameraParameters * @return */ private Camera.Size findFitPreResolution(Camera.Parameters cameraParameters) throws Exception { List<Camera.Size> supportedPicResolutions = cameraParameters.getSupportedPreviewSizes(); Camera.Size resultSize = null; for (Camera.Size size : supportedPicResolutions) { if (size.width <= ALLOW_PIC_LEN) { if (resultSize == null) { resultSize = size; } else if (size.width > resultSize.width) { resultSize = size; } } } if (resultSize == null) { return supportedPicResolutions.get(0); } return resultSize; }}
SensorManger.java
import android.content.Context;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;/** * Created by zouguibao on 2017/11/23. */public class SensorManger implements SensorEventListener{ public static SensorManger intance; private boolean autoFocus; private OnAccelSensorListener accelSensorListener; private SensorManager sensorManager;//使用传感器实现连续自动调整焦点 private Sensor mAccelSensor;//重力感应 private boolean mInvalidate = false; private boolean mInitialized = false; private float mLastX = 0; private float mLastY = 0; private float mLastZ = 0; private SensorManger(){ } public static SensorManger getIntance(){ if(intance == null){ intance = new SensorManger(); } return intance; } public void initSensorManager(Context context){ sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); mAccelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } public void registerListener(){ sensorManager.registerListener(this, mAccelSensor, SensorManager.SENSOR_DELAY_UI); } public void unRegisterListener(){ sensorManager.unregisterListener(this); } public void lockFocus(){ autoFocus = false; } public void unLockFocus(){ autoFocus = true; } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { if (mInvalidate == true) {// mView.invalidate(); mInvalidate = false; } float x = event.values[0]; float y = event.values[1]; float z = event.values[2]; if (!mInitialized) { mLastX = x; mLastY = y; mLastZ = z; mInitialized = true; } float deltaX = Math.abs(mLastX - x); float deltaY = Math.abs(mLastY - y); float deltaZ = Math.abs(mLastZ - z); if (deltaX > .5 && autoFocus) { autoFocus = false; if(accelSensorListener != null){ accelSensorListener.onAccelSensor(); } } if (deltaY > .5 && autoFocus) { autoFocus = false; if(accelSensorListener != null){ accelSensorListener.onAccelSensor(); } } if (deltaZ > .5 && autoFocus) { //AUTOFOCUS (while it is not autofocusing) */ autoFocus = false; if(accelSensorListener != null){ accelSensorListener.onAccelSensor(); } } mLastX = x; mLastY = y; mLastZ = z; } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } public void setAccelSensorListener(OnAccelSensorListener accelSensorListener) { this.accelSensorListener = accelSensorListener; } public interface OnAccelSensorListener{ void onAccelSensor(); }}
CustomCameraActivity.java
import android.app.Activity;import android.graphics.Point;import android.hardware.Camera;import android.os.Bundle;import android.os.Handler;import android.support.annotation.Nullable;import android.util.DisplayMetrics;import android.view.Display;import android.view.MotionEvent;import android.view.OrientationEventListener;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.ImageButton;import android.widget.RelativeLayout;import com.creditease.runningman.R;/** * Created by guibaozou on 2017/8/17. */public class CustomCameraActivity extends Activity implements View.OnClickListener, Camera.AutoFocusCallback, Camera.PictureCallback ,SensorManger.OnAccelSensorListener{ private SurfaceView surfaceView; private ImageButton swapCameraBtn; private ImageButton takePhotoBtn; private ImageButton backBtn; private ImageButton surePhotoBtn; private ImageButton reTakeBtn; private FocusView focusView; private RelativeLayout rootLayout; private OrientationEventListener orientationEventListener; private int screenWidth; private int screenHeight; private String screenRate; private SurfaceHolder holder; private Handler mHandler = new Handler(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 全屏显示 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.custom_camera); surfaceView = (SurfaceView) findViewById(R.id.surfaceView); swapCameraBtn = (ImageButton) findViewById(R.id.cameraSwap); takePhotoBtn = (ImageButton) findViewById(R.id.takePhoto); backBtn = (ImageButton) findViewById(R.id.backBtn); surePhotoBtn = (ImageButton) findViewById(R.id.surePhoto); reTakeBtn = (ImageButton) findViewById(R.id.reTakePhoto); rootLayout = (RelativeLayout) findViewById(R.id.root_layout); RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(160, 160); focusView = new FocusView(this); focusView.setLayoutParams(layoutParams); holder = surfaceView.getHolder(); holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// holder.setFixedSize(176, 144);//设置分辨率 holder.setKeepScreenOn(true);//屏幕长亮 holder.addCallback(new SurfaceCallBack());////为SurfaceView的句柄添加一个回调函数 swapCameraBtn.setOnClickListener(this); takePhotoBtn.setOnClickListener(this); backBtn.setOnClickListener(this); surePhotoBtn.setOnClickListener(this); reTakeBtn.setOnClickListener(this); WindowManager windowManager = getWindowManager(); Display display = windowManager.getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); //获取屏幕的宽和高 display.getMetrics(metrics); screenWidth = metrics.widthPixels; screenHeight = metrics.heightPixels; SensorManger.getIntance().initSensorManager(this); SensorManger.getIntance().setAccelSensorListener(this); screenRate = getSurfaceViewSize(screenWidth, screenHeight); setSurfaceViewSize(screenRate); orientationEventListener = new OrientationEventListener(this) { @Override public void onOrientationChanged(int orientation) { if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) { return; //手机平放时,检测不到有效的角度 } //只检测是否有四个角度的改变 if (orientation > 350 || orientation < 10) { //0度 orientation = 90; } else if (orientation > 80 && orientation < 100) { //90度 orientation = 0; } else if (orientation > 170 && orientation < 190) { //180度 orientation = 270; } else if (orientation > 260 && orientation < 280) { //270度 orientation = 180; } else { orientation = 0; } DataUtils.degree = orientation; } }; } private float startDis; private boolean isTouch; /** * 记录是拖拉照片模式还是放大缩小照片模式 */ private static final int MODE_INIT = 0; /** * 放大缩小照片模式 */ private static final int MODE_ZOOM = 1; private int mode = MODE_INIT;// 初始状态 private Point point; @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: mode = MODE_INIT; break; case MotionEvent.ACTION_POINTER_DOWN: if (event.getPointerCount() < 2) return super.onTouchEvent(event); mode = MODE_ZOOM; startDis = spacing(event); break; case MotionEvent.ACTION_MOVE: if (mode == MODE_ZOOM) { if (event.getPointerCount() < 2) return super.onTouchEvent(event); float endDis = spacing(event); int scale = (int) ((endDis - startDis) / 10f); if (scale >= 1 || scale <= -1) { CameraManger.getInstance().setCameraZoom(scale); startDis = endDis; } } break; case MotionEvent.ACTION_UP: if (mode == MODE_INIT) { point = new Point((int) event.getX(), (int) event.getY()); SensorManger.getIntance().lockFocus(); isTouch = CameraManger.getInstance().setCameraFocusAreas(point); if (isTouch) { CameraManger.getInstance().setCameraAutoFocus(CustomCameraActivity.this); } } break; } return super.onTouchEvent(event); } /** * 两点的距离 */ private float spacing(MotionEvent event) { if (event == null) { return 0; } float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); } // 提供一个静态方法,用于根据手机方向获得相机预览画面旋转的角度 private int getPreviewDegree(Activity activity) { // 获得手机的方向 int rotation = getWindowManager().getDefaultDisplay().getRotation(); int degree = 0; // 根据手机的方向计算相机预览画面应该选择的角度 switch (rotation) { case Surface.ROTATION_0: degree = 90; break; case Surface.ROTATION_90: degree = 0; break; case Surface.ROTATION_180: degree = 270; break; case Surface.ROTATION_270: degree = 180; break; } return degree; } public String getSurfaceViewSize(int width, int height) { if (equalRate(width, height, 1.33f)) { return "4:3"; } else { return "16:9"; } } public boolean equalRate(int width, int height, float rate) { float r = (float) width / (float) height; if (Math.abs(r - rate) <= 0.2) { return true; } else { return false; } } /** * 根据分辨率设置预览SurfaceView的大小以防止变形 * * @param surfaceSize */ private void setSurfaceViewSize(String surfaceSize) { ViewGroup.LayoutParams params = surfaceView.getLayoutParams(); if (surfaceSize.equals("16:9")) { params.height = ViewGroup.LayoutParams.MATCH_PARENT; } else if (surfaceSize.equals("4:3")) { params.height = 4 * screenWidth / 3; } surfaceView.setLayoutParams(params); } @Override protected void onResume() { super.onResume(); if (orientationEventListener.canDetectOrientation()) { orientationEventListener.enable(); } SensorManger.getIntance().registerListener(); } @Override protected void onPause() { super.onPause(); orientationEventListener.disable(); SensorManger.getIntance().unRegisterListener(); } @Override protected void onDestroy() { super.onDestroy(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.backBtn: destroyCamera(); finish(); break; case R.id.takePhoto: //锁定焦点 SensorManger.getIntance().lockFocus(); //拍照 CameraManger.getInstance().takePicture(CustomCameraActivity.this, CustomCameraActivity.this); break; case R.id.reTakePhoto: CameraManger.getInstance().startPreview(); takePhotoBtn.setVisibility(View.VISIBLE); surePhotoBtn.setVisibility(View.GONE); backBtn.setVisibility(View.VISIBLE); reTakeBtn.setVisibility(View.GONE); SensorManger.getIntance().unLockFocus(); break; case R.id.surePhoto: destroyCamera(); setResult(RESULT_OK); CameraManger.getInstance().closeShutterSound(); finish(); break; case R.id.cameraSwap: CameraManger.getInstance().turnCamera(holder, CustomCameraActivity.this, getPreviewDegree(CustomCameraActivity.this),screenWidth,screenHeight); break; default: break; } } /** * 自定聚焦监听器的方法 * * @param success * @param camera */ @Override public void onAutoFocus(boolean success, Camera camera) { if (success) { SensorManger.getIntance().unLockFocus(); rootLayout.removeView(focusView); RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) focusView.getLayoutParams(); if (!isTouch) { params.addRule(RelativeLayout.CENTER_IN_PARENT); } else { isTouch = false; if (point != null) { params.leftMargin = point.x - 30; params.topMargin = point.y - 30; } else { params.addRule(RelativeLayout.CENTER_IN_PARENT); } } rootLayout.addView(focusView, params); mHandler.postDelayed(new Runnable() { @Override public void run() { rootLayout.removeView(focusView); } }, 1000); } } @Override public void onPictureTaken(byte[] data, Camera camera) { CameraManger.getInstance().stopPreview(); //将拍摄到的照片给自定义的对象 DataUtils.tempImageData = data; takePhotoBtn.setVisibility(View.GONE); surePhotoBtn.setVisibility(View.VISIBLE); backBtn.setVisibility(View.GONE); reTakeBtn.setVisibility(View.VISIBLE); SensorManger.getIntance().unLockFocus(); } @Override public void onAccelSensor() { CameraManger.getInstance().setCameraAutoFocus(this); } private final class SurfaceCallBack implements SurfaceHolder.Callback { @Override public void surfaceCreated(SurfaceHolder holder) { CameraManger.getInstance().openCamera(holder,CustomCameraActivity.this,getPreviewDegree(CustomCameraActivity.this)); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { CameraManger.getInstance().setCameraParameters(screenWidth,screenHeight); } @Override public void surfaceDestroyed(SurfaceHolder holder) { destroyCamera(); } } private void destroyCamera() { CameraManger.getInstance().destroyCamera(); holder.getSurface().release(); surfaceView = null; }}
xml:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" /> <ImageButton android:id="@+id/cameraSwap" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/camera_swap" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:background="@android:color/transparent" /> <ImageButton android:id="@+id/takePhoto" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/take_photo" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="@android:color/transparent" /> <ImageButton android:id="@+id/reTakePhoto" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/re_take" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:visibility="gone" android:layout_marginLeft="10dp" android:background="@android:color/transparent" /> <ImageButton android:id="@+id/backBtn" android:layout_width="40dp" android:layout_height="40dp" android:src="@drawable/arrow_down_pressed" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="25dp" android:layout_marginLeft="10dp" android:background="@android:color/transparent" /> <ImageButton android:id="@+id/surePhoto" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/camera_sure" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:visibility="gone" android:background="@android:color/transparent" /></RelativeLayout>
辅助类DataUtils:
public class DataUtils { public static byte[] tempImageData; public static int degree; public static boolean isBackCamera = true;}
辅助类FocusView:
import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;/** * Created by zouguibao on 2017/11/16. */public class FocusView extends View { private int w; private int h; private Paint paint; public FocusView(Context context) { super(context); init(); } public FocusView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public FocusView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.GREEN); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.w = w; this.h = h; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawLine(0,0,this.w,0,paint); canvas.drawLine(0,0,0,this.h,paint); canvas.drawLine(this.w,0,this.w,this.h,paint); canvas.drawLine(0,this.h,this.w,this.h,paint); }}
每次拍完照片想要获取到竖屏的照片则如以下方式旋转即可:
Bitmap bm0 = BitmapFactory.decodeByteArray(DataUtils.tempImageData,0,DataUtils.tempImageData.length);Matrix m = new Matrix();int rotate = 0;//不论拍照时是在哪个方向上拍摄的,得到的都是竖直版的正向的图片,这是后置摄像头的if(DataUtils.isBackCamera){ if(DataUtils.degree == 90){ rotate = 90; }else if(DataUtils.degree == 0){ rotate = 90; }else if(DataUtils.degree == 180){ rotate = -90; }else if(DataUtils.degree == 270){ rotate = -90; }}else{
//前置摄像头的 if(DataUtils.degree == 90){ rotate = 270; }else if(DataUtils.degree == 0){ rotate = 270; }else if(DataUtils.degree == 180){ rotate = 90; }else if(DataUtils.degree == 270){ rotate = 90; }}m.setRotate(rotate,(float) bm0.getWidth() / 2, (float) bm0.getHeight() / 2);final Bitmap bm = Bitmap.createBitmap(bm0, 0, 0, bm0.getWidth(), bm0.getHeight(), m, true);
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" /><uses-feature android:name="android.hardware.camera.autofocus" android:required="true" />
以上就是全部内容了。其中借鉴了一些其他人的代码,再此感谢,参考如下:
https://github.com/huweigoodboy/SweetCamera
- Android 自定义Camera全屏拍照,支持前后摄像头
- 【Android】自定义相机的实现(支持连续拍照、前后摄像头切换、连续对焦)
- Android surfaceview 自定义相机 拍照(闪光灯、前后摄像头)
- Android自定义相机,切换前后摄像头,照相机拍照
- Android surfaceview 自定义相机 拍照(闪光灯、前后摄像头)
- Android 实例讲解自定义Camera拍照和预览以及前后置摄像头切换
- Android实例讲解自定义Camera拍照和预览以及前后置摄像头切换
- 调用摄像头拍照 camera
- 【笔记】Android5.0前后的Camera和Camera2 预览、拍照、摄像头切换
- Android Camera+SurfaceView实现自定义拍照
- android自定义拍照界面SurfaceView+Camera
- Camera的前后摄像头调换
- Android开发:Camera初探——控制摄像头拍照
- 自定义照相机实现前后切换摄像头以及拍照预览各种问题解决
- 安卓直播界面开发,自定义照相机拍照,前后摄像头切换教程加源码!
- Android系统Camera参数设置&&Android之Camera拍照 && Android之Camera预览过程中插拔摄像头节点后移
- 关于Android使用Camera自定义拍照出现模糊不清的解决方案
- android下自定义Camera进行录像和拍照
- 实验吧笔记-IPC$管道攻击与防御方法
- Java 利用Xstream注解生成和解析xml
- Hive Metastore 和hive-server2配置
- NOIP2017普及复赛 (~~题解)
- 单片机编程规范,模块化编程
- Android 自定义Camera全屏拍照,支持前后摄像头
- 内联框架跳转页面
- spark学习-32-SparkEnv的构造步骤
- MyBatis框架
- PythonStock(12):使用python,pandas进行股票分析
- Java学习——StringBuffer和StringBuilder类
- HDU1970 John(经典尼姆博奕)
- JS时间格式化
- 16秋计算机JAVA第五节课作业