package org.awesomeapp.messenger.ui.qr; import static android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT; import static android.view.SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS; import java.io.IOException; import java.util.List; import android.content.Context; import android.hardware.Camera; import android.hardware.Camera.AutoFocusCallback; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import org.awesomeapp.messenger.ImApp; @SuppressWarnings("deprecation") public class CameraView extends SurfaceView implements SurfaceHolder.Callback, AutoFocusCallback { private static String TAG = CameraView.class.getPackage().getName(); private Camera camera = null; private PreviewConsumer previewConsumer = null; private Size desiredSize = null; private int displayOrientation = 0; private boolean surfaceExists = false; public CameraView(Context context) { super(context); setKeepScreenOn(true); } void start(Camera newCamera, PreviewConsumer previewConsumer, int rotationDegrees, boolean macro) { camera = newCamera; this.previewConsumer = previewConsumer; setDisplayOrientation(rotationDegrees); SurfaceHolder holder = getHolder(); holder.addCallback(this); holder.setType(SURFACE_TYPE_PUSH_BUFFERS); // Required on Android < 3.0 if(surfaceExists) startPreview(holder); new Thread () { public void run () { while (camera != null) { try { Thread.sleep(2000); } catch (Exception e){} try { camera.autoFocus(CameraView.this); } catch (Exception e) { Log.w(ImApp.LOG_TAG,"qr code scanning not working: " + e.toString()); } } } }.start(); } void stop() { stopPreview(); getHolder().removeCallback(this); camera = null; } private void startPreview(SurfaceHolder holder) { try { Parameters params = camera.getParameters(); if (params.getSupportedFocusModes().contains( Camera.Parameters.FOCUS_MODE_AUTO)) { params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } camera.setParameters(params); camera.setPreviewDisplay(holder); camera.startPreview(); previewConsumer.start(camera); } catch(IOException e) { Log.e(TAG, "Error starting camera preview", e); } } private void stopPreview() { try { previewConsumer.stop(); if (camera != null) { camera.stopPreview(); } } catch(Exception e) { Log.e(TAG, "Error stopping camera preview", e); } } private void setDisplayOrientation(int rotationDegrees) { int orientation; CameraInfo info = new CameraInfo(); Camera.getCameraInfo(0, info); if(info.facing == CAMERA_FACING_FRONT) { orientation = (info.orientation + rotationDegrees) % 360; orientation = (360 - orientation) % 360; } else { orientation = (info.orientation - rotationDegrees + 360) % 360; } camera.setDisplayOrientation(orientation); displayOrientation = orientation; } public void surfaceCreated(SurfaceHolder holder) { surfaceExists = true; startPreview(holder); } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { stopPreview(); if (camera != null) { boolean rotatePreview = displayOrientation % 180 == 90; Parameters params = camera.getParameters(); List<Size> sizes = params.getSupportedPreviewSizes(); Size bestSize = null; int bestError = 0; for (Size size : sizes) { int width = rotatePreview ? size.height : size.width; int height = rotatePreview ? size.width : size.height; int widthError = Math.abs(width - w); int heightError = Math.abs(height - h); int error = Math.max(widthError, heightError); if (bestSize == null || error < bestError) { bestSize = size; bestError = error; } } params.setPreviewSize(bestSize.width, bestSize.height); camera.setParameters(params); desiredSize = bestSize; startPreview(holder); } } public void surfaceDestroyed(SurfaceHolder holder) { surfaceExists = false; } public void onAutoFocus(boolean success, Camera camera) { Log.d(TAG, "Auto focus: " + success); } @Override protected void onMeasure(int width, int height) { if(desiredSize == null) super.onMeasure(width, height); else if(displayOrientation % 180 == 90) setMeasuredDimension(desiredSize.height, desiredSize.width); else setMeasuredDimension(desiredSize.width, desiredSize.height); } }