X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=src%2Forg%2Ffedorahosted%2Ffreeotp%2FCameraDialogFragment.java;h=80c6c9bc6eb24ee0fac4bdba6838017a0ba7dfca;hb=a80af12864b08b59ef6592ed3463ee7f1000a0ab;hp=f4c7760a91f8746dc9a2693ef45f5602a3a4638a;hpb=7c623216cb4072ead174d48f1bd5ce55e78433e4;p=~andy%2Ffreeotp diff --git a/src/org/fedorahosted/freeotp/CameraDialogFragment.java b/src/org/fedorahosted/freeotp/CameraDialogFragment.java index f4c7760..80c6c9b 100644 --- a/src/org/fedorahosted/freeotp/CameraDialogFragment.java +++ b/src/org/fedorahosted/freeotp/CameraDialogFragment.java @@ -20,49 +20,93 @@ package org.fedorahosted.freeotp; +import java.util.List; + +import android.annotation.TargetApi; import android.app.AlertDialog; -import android.content.Context; +import android.app.Dialog; import android.content.DialogInterface; import android.hardware.Camera; +import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; -import android.view.WindowManager; import android.widget.TextView; -public class CameraDialogFragment extends BaseAlertDialogFragment implements SurfaceHolder.Callback { +public class CameraDialogFragment extends BaseAlertDialogFragment + implements SurfaceHolder.Callback, Camera.AutoFocusCallback { public static final String FRAGMENT_TAG = "fragment_camera"; - private DecodeAsyncTask mDecodeAsyncTask; + private final CameraInfo mCameraInfo = new CameraInfo(); + private final DecodeAsyncTask mDecodeAsyncTask; + private final int mCameraId; + private Handler mHandler; private Camera mCamera; public CameraDialogFragment() { super(R.string.scan_qr_code, R.layout.camera, android.R.string.cancel, R.string.manual_entry, 0); - } - @Override - protected void onViewInflated(View view) { - SurfaceView sv = (SurfaceView) view.findViewById(R.id.camera_surfaceview); - sv.getHolder().addCallback(this); + // Find a back-facing camera, otherwise use the first camera. + int cameraId; + for (cameraId = Camera.getNumberOfCameras() - 1; cameraId > 0; cameraId--) { + Camera.getCameraInfo(cameraId, mCameraInfo); + if (mCameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) + break; + } + mCameraId = cameraId; + + // Create the decoder thread + mDecodeAsyncTask = new DecodeAsyncTask() { + @Override + protected void onPostExecute(String result) { + super.onPostExecute(result); + if (result != null) + ((MainActivity) getActivity()).tokenURIReceived(result); + dismiss(); + } + }; } @Override - public void onClick(DialogInterface dialog, int which) { - if (which == AlertDialog.BUTTON_NEUTRAL) { + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // If we have no cameras, open the manual dialog + if (mCameraId < 0) { new ManualDialogFragment().show(getFragmentManager(), ManualDialogFragment.FRAGMENT_TAG); + dismiss(); + return; } + + mDecodeAsyncTask.execute(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mDecodeAsyncTask.cancel(true); + } + + @Override + protected void onViewInflated(View view) { + SurfaceView sv = (SurfaceView) view.findViewById(R.id.camera_surfaceview); + sv.getHolder().addCallback(this); } @Override - public void onDestroyView() { - if (mDecodeAsyncTask != null) - mDecodeAsyncTask.cancel(true); + public void onClick(DialogInterface dialog, int which) { + if (which != AlertDialog.BUTTON_NEUTRAL) + return; - super.onDestroyView(); + new ManualDialogFragment().show(getFragmentManager(), + ManualDialogFragment.FRAGMENT_TAG); } @Override @@ -70,50 +114,70 @@ public class CameraDialogFragment extends BaseAlertDialogFragment implements Sur if (mCamera == null) return; - WindowManager wm = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE); - switch (wm.getDefaultDisplay().getRotation()) { + int rotation = 0; + switch (getActivity().getWindowManager().getDefaultDisplay().getRotation()) { case Surface.ROTATION_0: - mCamera.setDisplayOrientation(90); + rotation = 0; + break; + case Surface.ROTATION_90: + rotation = 90; + break; + case Surface.ROTATION_180: + rotation = 180; break; case Surface.ROTATION_270: - mCamera.setDisplayOrientation(180); + rotation = 270; break; } + mCamera.setDisplayOrientation((mCameraInfo.orientation - rotation + 360) % 360); mCamera.startPreview(); + + if (mHandler != null) + mHandler.sendEmptyMessageDelayed(0, 100); } @Override + @TargetApi(14) public void surfaceCreated(SurfaceHolder holder) { + surfaceDestroyed(holder); + try { - mCamera = Camera.open(); + // Open the camera + mCamera = Camera.open(mCameraId); mCamera.setPreviewDisplay(holder); - - // Create the decoder thread - mDecodeAsyncTask = new DecodeAsyncTask() { - @Override - protected void onPostExecute(String result) { - super.onPostExecute(result); - if (result != null) - ((MainActivity) getActivity()).tokenURIReceived(result); - mDecodeAsyncTask = null; - dismiss(); - } - }; - mDecodeAsyncTask.execute(); mCamera.setPreviewCallback(mDecodeAsyncTask); - - // Set auto-focus mode - Parameters params = mCamera.getParameters(); - params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); - mCamera.setParameters(params); } catch (Exception e) { - SurfaceView sv = (SurfaceView) getDialog().findViewById(R.id.camera_surfaceview); + e.printStackTrace(); + surfaceDestroyed(holder); + + // Show error message + Dialog d = getDialog(); + SurfaceView sv = (SurfaceView) d.findViewById(R.id.camera_surfaceview); + TextView tv = (TextView) d.findViewById(R.id.camera_textview); sv.setVisibility(View.INVISIBLE); - TextView tv = (TextView) getDialog().findViewById(R.id.camera_textview); tv.setVisibility(View.VISIBLE); - e.printStackTrace(); + return; } + + // Set auto-focus mode + Parameters params = mCamera.getParameters(); + List modes = params.getSupportedFocusModes(); + if (modes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) + params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); + else if (modes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + params.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + else if (modes.contains(Parameters.FOCUS_MODE_AUTO)) { + params.setFocusMode(Parameters.FOCUS_MODE_AUTO); + mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + mCamera.autoFocus(CameraDialogFragment.this); + } + }; + } + mCamera.setParameters(params); } @Override @@ -121,9 +185,21 @@ public class CameraDialogFragment extends BaseAlertDialogFragment implements Sur if (mCamera == null) return; + if (mHandler != null) { + mCamera.cancelAutoFocus(); + mHandler.removeMessages(0); + mHandler = null; + } + mCamera.stopPreview(); mCamera.setPreviewCallback(null); mCamera.release(); mCamera = null; } + + @Override + public void onAutoFocus(boolean success, Camera camera) { + if (mHandler != null) + mHandler.sendEmptyMessageDelayed(0, 1000); + } }