]> Pileus Git - ~andy/freeotp/commitdiff
Support camera hardware oreintation offsets
authorNathaniel McCallum <npmccallum@redhat.com>
Wed, 11 Dec 2013 15:30:48 +0000 (10:30 -0500)
committerNathaniel McCallum <npmccallum@redhat.com>
Wed, 11 Dec 2013 15:30:48 +0000 (10:30 -0500)
AndroidManifest.xml
src/org/fedorahosted/freeotp/CameraDialogFragment.java
src/org/fedorahosted/freeotp/MainActivity.java

index b514f4d5758b7cacbecea0230fd7ff94697245dc..7d9ecc5676f689411e3d7223aa70d14a604c1551 100644 (file)
@@ -21,7 +21,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="org.fedorahosted.freeotp"
-    android:versionCode="8"
+    android:versionCode="9"
     android:versionName="1.3" >
 
     <uses-sdk
index c3c23dd028cbcaad8c48c02d6bb2f85aae49d022..f81fe8e351dd6835f21742eb1df123343384830f 100644 (file)
@@ -24,48 +24,85 @@ 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.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 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 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
+               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 back facing camera, open the manual dialog
+               if (mCameraId < 0) {
                        new ManualDialogFragment().show(getFragmentManager(),
                                        ManualDialogFragment.FRAGMENT_TAG);
+                       dismiss();
+                       return;
                }
+
+               mDecodeAsyncTask.execute();
        }
 
        @Override
-       public void onDestroyView() {
-               if (mDecodeAsyncTask != null)
-                       mDecodeAsyncTask.cancel(true);
+       public void onDestroy() {
+               super.onDestroy();
+               mDecodeAsyncTask.cancel(true);
+       }
 
-               super.onDestroyView();
+       @Override
+       protected void onViewInflated(View view) {
+               SurfaceView sv = (SurfaceView) view.findViewById(R.id.camera_surfaceview);
+               sv.getHolder().addCallback(this);
+       }
+
+       @Override
+       public void onClick(DialogInterface dialog, int which) {
+               if (which != AlertDialog.BUTTON_NEUTRAL)
+                       return;
+
+               new ManualDialogFragment().show(getFragmentManager(),
+                               ManualDialogFragment.FRAGMENT_TAG);
        }
 
        @Override
@@ -73,57 +110,59 @@ 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();
        }
 
        @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();
-                       List<String> 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);
-                       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<String> 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);
+               mCamera.setParameters(params);
        }
 
        @Override
index efcdae338836113c76752b86b90ac87474ceefb1..0a65fc4e8cb040b3de43afa60156004888127757 100644 (file)
@@ -40,10 +40,7 @@ import org.fedorahosted.freeotp.Token.TokenUriInvalidException;
 import org.fedorahosted.freeotp.adapters.TokenAdapter;
 
 import android.app.Activity;
-import android.content.pm.PackageManager;
 import android.database.DataSetObserver;
-import android.hardware.Camera;
-import android.hardware.Camera.CameraInfo;
 import android.os.Bundle;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -96,26 +93,8 @@ public class MainActivity extends Activity implements OnMenuItemClickListener {
        public boolean onMenuItemClick(MenuItem item) {
                switch (item.getItemId()) {
                case R.id.action_add:
-                       // Look for a back-facing camera.
-                       boolean backCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
-
-                       // If the above method doesn't return a camera, try to work around it.
-                       // Some buggy implementations return false above even when there is a camera.
-                       for (int i = Camera.getNumberOfCameras() - 1; i >= 0 && !backCamera; i--) {
-                               CameraInfo ci = new CameraInfo();
-                               Camera.getCameraInfo(i, ci);
-                               backCamera = ci.facing == CameraInfo.CAMERA_FACING_BACK;
-                       }
-
-                       // If the device has a camera available, try to scan for QR code
-                       if (backCamera) {
-                               new CameraDialogFragment().show(getFragmentManager(),
-                                               CameraDialogFragment.FRAGMENT_TAG);
-                       } else {
-                               new ManualDialogFragment().show(getFragmentManager(),
-                                               ManualDialogFragment.FRAGMENT_TAG);
-                       }
-
+                       new CameraDialogFragment().show(getFragmentManager(),
+                                       CameraDialogFragment.FRAGMENT_TAG);
                        return true;
 
                case R.id.action_about: