Commit f5e3835b authored by Ehsan Kia's avatar Ehsan Kia Committed by Commit Bot

[QRCode] Display error message when a camera failure happens.

Screenshot:
https://screenshot.googleplex.com/7ZyeNAwxjxC.png

Bug: 1052026
Change-Id: Ie0e5f58b03e1fdc21d2c6dafc1c6990636b2ebc4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2054564
Commit-Queue: Ehsan Kia <ehsankia@google.com>
Reviewed-by: default avatarGayane Petrosyan <gayane@chromium.org>
Cr-Commit-Position: refs/heads/master@{#741222}
parent 0e55e776
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/permission_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/qrcode_camera_error_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawablePadding="8dp"
android:drawableStart="@drawable/ic_error"
android:gravity="center_vertical"
android:maxWidth="250dp"
android:textAppearance="@style/TextAppearance.ErrorCaption" />
</LinearLayout>
......@@ -20,7 +20,8 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
private static final String THREAD_NAME = "CameraHandlerThread";
private final Context mContext;
private final Camera.PreviewCallback mCameraCallback;
private final Camera.PreviewCallback mPreviewCallback;
private final Camera.ErrorCallback mErrorCallback;
private int mCameraId;
private Camera mCamera;
......@@ -29,12 +30,15 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
/**
* The CameraPreview constructor.
* @param context The context to use for user permissions.
* @param cameraCallback The callback to processing camera preview.
* @param previewCallback The callback to processing camera preview.
* @param errorCallback The callback when an error happens using the camera.
*/
public CameraPreview(Context context, Camera.PreviewCallback cameraCallback) {
public CameraPreview(Context context, Camera.PreviewCallback previewCallback,
Camera.ErrorCallback errorCallback) {
super(context);
mContext = context;
mCameraCallback = cameraCallback;
mPreviewCallback = previewCallback;
mErrorCallback = errorCallback;
}
/** Obtains a camera and starts the preview. */
......@@ -89,7 +93,8 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
try {
mCamera.setPreviewDisplay(getHolder());
mCamera.setDisplayOrientation(getCameraOrientation());
mCamera.setOneShotPreviewCallback(mCameraCallback);
mCamera.setOneShotPreviewCallback(mPreviewCallback);
mCamera.setErrorCallback(mErrorCallback);
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
......@@ -97,7 +102,7 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
mCamera.startPreview();
} catch (Exception e) {
// TODO(gayane): Should show error message to users, when error strings are approved.
mErrorCallback.onError(Camera.CAMERA_ERROR_UNKNOWN, mCamera);
}
}
......@@ -110,6 +115,7 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
}
mCamera.setOneShotPreviewCallback(null);
mCamera.setErrorCallback(null);
try {
mCamera.stopPreview();
} catch (RuntimeException e) {
......@@ -117,7 +123,7 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
}
}
/** Calculates camera's orientation based on displaye's orientation and camera. */
/** Calculates camera's orientation based on display's orientation and camera. */
private int getCameraOrientation() {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(mCameraId, info);
......@@ -168,12 +174,12 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
* Returns an instance of the Camera for the give id. Returns null if camera is used or doesn't
* exist.
*/
private static Camera getCameraInstance(int cameraId) {
private Camera getCameraInstance(int cameraId) {
Camera camera = null;
try {
camera = Camera.open(cameraId);
} catch (RuntimeException e) {
// TODO(gayane): Should show error message to users, when error strings are approved.
mErrorCallback.onError(Camera.CAMERA_ERROR_UNKNOWN, null);
}
return camera;
}
......
......@@ -5,12 +5,15 @@
package org.chromium.chrome.browser.share.qrcode.scan_tab;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.PreviewCallback;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.TextView;
import org.chromium.ui.widget.ButtonCompat;
......@@ -22,13 +25,14 @@ class QrCodeScanView {
private final Context mContext;
private final FrameLayout mView;
private final PreviewCallback mCameraCallback;
private final PreviewCallback mCameraPreviewCallback;
private boolean mHasCameraPermission;
private boolean mCanPromptForPermission;
private boolean mIsOnForeground;
private CameraPreview mCameraPreview;
private View mPermissionsView;
private View mCameraErrorView;
/**
* The QrCodeScanView constructor.
......@@ -39,11 +43,12 @@ class QrCodeScanView {
public QrCodeScanView(Context context, PreviewCallback cameraCallback,
PermissionPrompter permissionPrompter) {
mContext = context;
mCameraCallback = cameraCallback;
mCameraPreviewCallback = cameraCallback;
mView = new FrameLayout(context);
mView.setLayoutParams(
new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mPermissionsView = createPermissionView(context, permissionPrompter);
mCameraErrorView = createCameraErrorView(context);
}
public View getView() {
......@@ -66,6 +71,26 @@ class QrCodeScanView {
return permissionView;
}
private View createCameraErrorView(Context context) {
return (View) LayoutInflater.from(context).inflate(
org.chromium.chrome.browser.share.qrcode.R.layout.qrcode_camera_error_layout, null,
false);
}
private final ErrorCallback mCameraErrorCallback = new ErrorCallback() {
@Override
public void onError(int error, Camera camera) {
if (mCameraPreview != null) {
mCameraPreview.stopCamera();
mCameraPreview = null;
}
// TODO(ehsankia): Adjust error message given error code.
String errorString = mContext.getResources().getString(
org.chromium.chrome.R.string.qr_code_in_use_camera_error);
displayCameraErrorDialog(errorString);
}
};
/**
* Sets camera if possible.
*
......@@ -121,7 +146,8 @@ class QrCodeScanView {
}
if (mHasCameraPermission) {
mCameraPreview = new CameraPreview(mContext, mCameraCallback);
mCameraPreview =
new CameraPreview(mContext, mCameraPreviewCallback, mCameraErrorCallback);
mView.addView(mCameraPreview);
mView.addView(new CameraPreviewOverlay(mContext));
......@@ -150,4 +176,14 @@ class QrCodeScanView {
mView.removeAllViews();
mView.addView(mPermissionsView);
}
/** Displays the camera error dialog. */
private void displayCameraErrorDialog(String errorString) {
TextView cameraErrorTextView = (TextView) mCameraErrorView.findViewById(
org.chromium.chrome.browser.share.qrcode.R.id.qrcode_camera_error_text);
cameraErrorTextView.setText(errorString);
mView.removeAllViews();
mView.addView(mCameraErrorView);
}
}
......@@ -4006,6 +4006,22 @@ The site does NOT gain access to the camera. The camera images are only visible
Continue
</message>
<message name="IDS_QR_CODE_NO_CAMERA_ERROR" desc="Error text shown when no camera is found.">
To scan a QR code, use a device with a camera.
</message>
<message name="IDS_QR_CODE_DISABLED_CAMERA_ERROR" desc="Error text shown when the camera is disabled by the device policy manager.">
The organization that manages your device has turned off your camera.
</message>
<message name="IDS_QR_CODE_IN_USE_CAMERA_ERROR" desc="Error text shown when the camera is in use by other apps.">
Can't open your camera. Restart your device and try again.
</message>
<message name="IDS_QR_CODE_HARDWARE_CAMERA_ERROR" desc="Error text shown when the camera cannot start due to a hardware error.">
Can't open your camera. Something went wrong.
</message>
<!-- Chime DFM module strings -->
<message name="IDS_CHIME_MODULE_TITLE" desc="Text shown when the chime module is referenced in install start, success, failure UI (e.g. in IDS_MODULE_INSTALL_START_TEXT, which will expand to 'Installing Google Notifications Platform for Chrome…').">
Google Notifications Platform
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment