Force higher resolution for analysis and run it on a background thread

This commit is contained in:
Alexander Bakker 2021-01-19 20:26:45 +01:00
parent 22c93bf5c6
commit 7be1a74cfd
5 changed files with 49 additions and 18 deletions

View file

@ -1,6 +1,9 @@
package com.beemdevelopment.aegis.helpers; package com.beemdevelopment.aegis.helpers;
import android.os.Handler;
import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.util.Size;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.camera.core.ImageAnalysis; import androidx.camera.core.ImageAnalysis;
@ -23,6 +26,7 @@ import static android.graphics.ImageFormat.YUV_444_888;
public class QrCodeAnalyzer implements ImageAnalysis.Analyzer { public class QrCodeAnalyzer implements ImageAnalysis.Analyzer {
private static final String TAG = QrCodeAnalyzer.class.getSimpleName(); private static final String TAG = QrCodeAnalyzer.class.getSimpleName();
public static final Size RESOLUTION = new Size(1200, 1600);
private final QrCodeAnalyzer.Listener _listener; private final QrCodeAnalyzer.Listener _listener;
@ -53,7 +57,7 @@ public class QrCodeAnalyzer implements ImageAnalysis.Analyzer {
try { try {
Result result = reader.decode(bitmap); Result result = reader.decode(bitmap);
if (_listener != null) { if (_listener != null) {
_listener.onQrCodeDetected(result); new Handler(Looper.getMainLooper()).post(() -> _listener.onQrCodeDetected(result));
} }
} catch (ChecksumException | FormatException | NotFoundException ignored) { } catch (ChecksumException | FormatException | NotFoundException ignored) {

View file

@ -53,6 +53,7 @@ public abstract class AegisActivity extends AppCompatActivity implements AegisAp
} }
@Override @Override
@CallSuper
protected void onDestroy() { protected void onDestroy() {
_app.unregisterLockListener(this); _app.unregisterLockListener(this);
super.onDestroy(); super.onDestroy();

View file

@ -342,6 +342,11 @@ public class Dialogs {
.setNeutralButton(R.string.details, (dialog1, which) -> { .setNeutralButton(R.string.details, (dialog1, which) -> {
textDetails.setVisibility(View.VISIBLE); textDetails.setVisibility(View.VISIBLE);
}) })
.setOnDismissListener(dialog12 -> {
if (listener != null) {
listener.onClick(dialog12, -1);
}
})
.create(); .create();
dialog.setOnShowListener(d -> { dialog.setOnShowListener(d -> {

View file

@ -29,6 +29,7 @@ import com.beemdevelopment.aegis.ViewMode;
import com.beemdevelopment.aegis.helpers.BitmapHelper; import com.beemdevelopment.aegis.helpers.BitmapHelper;
import com.beemdevelopment.aegis.helpers.FabScrollHelper; import com.beemdevelopment.aegis.helpers.FabScrollHelper;
import com.beemdevelopment.aegis.helpers.PermissionHelper; import com.beemdevelopment.aegis.helpers.PermissionHelper;
import com.beemdevelopment.aegis.helpers.QrCodeAnalyzer;
import com.beemdevelopment.aegis.otp.GoogleAuthInfo; import com.beemdevelopment.aegis.otp.GoogleAuthInfo;
import com.beemdevelopment.aegis.otp.GoogleAuthInfoException; import com.beemdevelopment.aegis.otp.GoogleAuthInfoException;
import com.beemdevelopment.aegis.ui.fragments.BackupsPreferencesFragment; import com.beemdevelopment.aegis.ui.fragments.BackupsPreferencesFragment;
@ -297,7 +298,7 @@ public class MainActivity extends AegisActivity implements EntryListView.Listene
try (InputStream inputStream = getContentResolver().openInputStream(inputFile)) { try (InputStream inputStream = getContentResolver().openInputStream(inputFile)) {
bitmap = BitmapFactory.decodeStream(inputStream, null, bmOptions); bitmap = BitmapFactory.decodeStream(inputStream, null, bmOptions);
bitmap = BitmapHelper.resize(bitmap, 640, 480); bitmap = BitmapHelper.resize(bitmap, QrCodeAnalyzer.RESOLUTION.getWidth(), QrCodeAnalyzer.RESOLUTION.getHeight());
} }
int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()]; int[] intArray = new int[bitmap.getWidth() * bitmap.getHeight()];

View file

@ -28,6 +28,8 @@ import com.google.zxing.Result;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Listener { public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Listener {
private ProcessCameraProvider _cameraProvider; private ProcessCameraProvider _cameraProvider;
@ -37,7 +39,9 @@ public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Lis
private int _currentLens; private int _currentLens;
private Menu _menu; private Menu _menu;
private ImageAnalysis _analysis;
private PreviewView _previewView; private PreviewView _previewView;
private ExecutorService _executor;
private int _batchId = 0; private int _batchId = 0;
private int _batchIndex = -1; private int _batchIndex = -1;
@ -51,6 +55,7 @@ public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Lis
_entries = new ArrayList<>(); _entries = new ArrayList<>();
_lenses = new ArrayList<>(); _lenses = new ArrayList<>();
_previewView = findViewById(R.id.preview_view); _previewView = findViewById(R.id.preview_view);
_executor = Executors.newSingleThreadExecutor();
_cameraProviderFuture = ProcessCameraProvider.getInstance(this); _cameraProviderFuture = ProcessCameraProvider.getInstance(this);
_cameraProviderFuture.addListener(() -> { _cameraProviderFuture.addListener(() -> {
@ -76,6 +81,12 @@ public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Lis
}, ContextCompat.getMainExecutor(this)); }, ContextCompat.getMainExecutor(this));
} }
@Override
protected void onDestroy() {
_executor.shutdownNow();
super.onDestroy();
}
@Override @Override
protected void onSetTheme() { protected void onSetTheme() {
setTheme(ThemeMap.FULLSCREEN); setTheme(ThemeMap.FULLSCREEN);
@ -91,7 +102,7 @@ public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Lis
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_camera) { if (item.getItemId() == R.id.action_camera) {
_cameraProvider.unbindAll(); unbindPreview(_cameraProvider);
_currentLens = _currentLens == CameraSelector.LENS_FACING_BACK ? CameraSelector.LENS_FACING_FRONT : CameraSelector.LENS_FACING_BACK; _currentLens = _currentLens == CameraSelector.LENS_FACING_BACK ? CameraSelector.LENS_FACING_FRONT : CameraSelector.LENS_FACING_BACK;
bindPreview(_cameraProvider); bindPreview(_cameraProvider);
updateCameraIcon(); updateCameraIcon();
@ -138,29 +149,38 @@ public class ScannerActivity extends AegisActivity implements QrCodeAnalyzer.Lis
.requireLensFacing(_currentLens) .requireLensFacing(_currentLens)
.build(); .build();
ImageAnalysis analysis = new ImageAnalysis.Builder() _analysis = new ImageAnalysis.Builder()
.setTargetResolution(QrCodeAnalyzer.RESOLUTION)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build(); .build();
analysis.setAnalyzer(ContextCompat.getMainExecutor(this), new QrCodeAnalyzer(this)); _analysis.setAnalyzer(_executor, new QrCodeAnalyzer(this));
cameraProvider.bindToLifecycle(this, selector, preview, analysis); cameraProvider.bindToLifecycle(this, selector, preview, _analysis);
}
private void unbindPreview(@NonNull ProcessCameraProvider cameraProvider) {
_analysis = null;
cameraProvider.unbindAll();
} }
@Override @Override
public void onQrCodeDetected(Result result) { public void onQrCodeDetected(Result result) {
try { if (_analysis != null) {
Uri uri = Uri.parse(result.getText().trim()); try {
if (uri.getScheme() != null && uri.getScheme().equals(GoogleAuthInfo.SCHEME_EXPORT)) { Uri uri = Uri.parse(result.getText().trim());
handleExportUri(uri); if (uri.getScheme() != null && uri.getScheme().equals(GoogleAuthInfo.SCHEME_EXPORT)) {
} else { handleExportUri(uri);
handleUri(uri); } else {
handleUri(uri);
}
} catch (GoogleAuthInfoException e) {
e.printStackTrace();
unbindPreview(_cameraProvider);
Dialogs.showErrorDialog(this,
e.isPhoneFactor() ? R.string.read_qr_error_phonefactor : R.string.read_qr_error,
e, ((dialog, which) -> bindPreview(_cameraProvider)));
} }
} catch (GoogleAuthInfoException e) {
e.printStackTrace();
Dialogs.showErrorDialog(this,
e.isPhoneFactor() ? R.string.read_qr_error_phonefactor : R.string.read_qr_error,
e, ((dialog, which) -> bindPreview(_cameraProvider)));
_cameraProvider.unbindAll();
} }
} }