mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 21:15:48 +00:00
Fix QR processing resolution and allow front camera use for device linking.
This commit is contained in:
committed by
Alex Hart
parent
3d14c05114
commit
ea9bf0ccd5
@@ -67,7 +67,7 @@ class QrProcessor {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(QrProcessor::class.java)
|
||||
|
||||
/** For debugging only */
|
||||
var listener: ((LuminanceSource) -> Unit)? = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,11 @@ class QrScannerView @JvmOverloads constructor(
|
||||
})
|
||||
}
|
||||
|
||||
fun toggleCamera() {
|
||||
Log.d(TAG, "Toggling camera")
|
||||
scannerView?.toggleCamera()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(QrScannerView::class.java)
|
||||
}
|
||||
|
||||
@@ -7,4 +7,5 @@ import androidx.lifecycle.LifecycleOwner
|
||||
*/
|
||||
interface ScannerView {
|
||||
fun start(lifecycleOwner: LifecycleOwner)
|
||||
fun toggleCamera()
|
||||
}
|
||||
|
||||
@@ -18,8 +18,27 @@ internal class ScannerView19 constructor(
|
||||
private val scanListener: ScanListener
|
||||
) : FrameLayout(context), ScannerView {
|
||||
|
||||
private var lifecycleOwner: LifecycleOwner? = null
|
||||
private var scanningThread: ScanningThread? = null
|
||||
private val cameraView: QrCameraView
|
||||
private lateinit var cameraView: QrCameraView
|
||||
|
||||
private val lifecycleObserver = object : DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
val scanningThread = ScanningThread()
|
||||
scanningThread.setScanListener(scanListener)
|
||||
cameraView.onResume()
|
||||
cameraView.setPreviewCallback(scanningThread)
|
||||
scanningThread.start()
|
||||
|
||||
this@ScannerView19.scanningThread = scanningThread
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
cameraView.onPause()
|
||||
scanningThread?.stopScanning()
|
||||
scanningThread = null
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
cameraView = QrCameraView(context)
|
||||
@@ -28,22 +47,16 @@ internal class ScannerView19 constructor(
|
||||
}
|
||||
|
||||
override fun start(lifecycleOwner: LifecycleOwner) {
|
||||
lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onResume(owner: LifecycleOwner) {
|
||||
val scanningThread = ScanningThread()
|
||||
scanningThread.setScanListener(scanListener)
|
||||
cameraView.onResume()
|
||||
cameraView.setPreviewCallback(scanningThread)
|
||||
scanningThread.start()
|
||||
this.lifecycleOwner?.lifecycle?.removeObserver(lifecycleObserver)
|
||||
this.lifecycleOwner = lifecycleOwner
|
||||
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
|
||||
}
|
||||
|
||||
this@ScannerView19.scanningThread = scanningThread
|
||||
}
|
||||
|
||||
override fun onPause(owner: LifecycleOwner) {
|
||||
cameraView.onPause()
|
||||
scanningThread?.stopScanning()
|
||||
scanningThread = null
|
||||
}
|
||||
})
|
||||
override fun toggleCamera() {
|
||||
cameraView.toggleCamera()
|
||||
lifecycleOwner?.let {
|
||||
lifecycleObserver.onPause(it)
|
||||
lifecycleObserver.onResume(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package org.signal.qr
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.util.Size
|
||||
import android.widget.FrameLayout
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.camera.core.AspectRatio
|
||||
import androidx.camera.core.Camera
|
||||
import androidx.camera.core.CameraSelector
|
||||
import androidx.camera.core.ImageAnalysis
|
||||
@@ -28,19 +28,42 @@ internal class ScannerView21 constructor(
|
||||
private val listener: ScanListener
|
||||
) : FrameLayout(context), ScannerView {
|
||||
|
||||
private var lifecyleOwner: LifecycleOwner? = null
|
||||
private val analyzerExecutor = Executors.newSingleThreadExecutor()
|
||||
private var cameraProvider: ProcessCameraProvider? = null
|
||||
private var cameraSelector: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
||||
private var camera: Camera? = null
|
||||
private var previewView: PreviewView
|
||||
private val qrProcessor = QrProcessor()
|
||||
|
||||
private val lifecycleObserver: DefaultLifecycleObserver = object : DefaultLifecycleObserver {
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
cameraProvider = null
|
||||
camera = null
|
||||
analyzerExecutor.shutdown()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
previewView = PreviewView(context)
|
||||
previewView.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
||||
addView(previewView)
|
||||
}
|
||||
|
||||
override fun toggleCamera() {
|
||||
cameraSelector = if (cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
|
||||
CameraSelector.DEFAULT_FRONT_CAMERA
|
||||
} else {
|
||||
CameraSelector.DEFAULT_BACK_CAMERA
|
||||
}
|
||||
|
||||
lifecyleOwner?.let { start(it) }
|
||||
}
|
||||
|
||||
override fun start(lifecycleOwner: LifecycleOwner) {
|
||||
this.lifecyleOwner?.lifecycle?.removeObserver(lifecycleObserver)
|
||||
this.lifecyleOwner = lifecycleOwner
|
||||
|
||||
previewView.post {
|
||||
Log.i(TAG, "Starting")
|
||||
ProcessCameraProvider.getInstance(context).apply {
|
||||
@@ -54,13 +77,7 @@ internal class ScannerView21 constructor(
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
|
||||
override fun onDestroy(owner: LifecycleOwner) {
|
||||
cameraProvider = null
|
||||
camera = null
|
||||
analyzerExecutor.shutdown()
|
||||
}
|
||||
})
|
||||
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
|
||||
}
|
||||
|
||||
private fun onCameraProvider(lifecycle: LifecycleOwner, cameraProvider: ProcessCameraProvider?) {
|
||||
@@ -71,10 +88,14 @@ internal class ScannerView21 constructor(
|
||||
|
||||
Log.i(TAG, "Initializing use cases")
|
||||
|
||||
val preview = Preview.Builder().build()
|
||||
val resolution = Size(480, 640)
|
||||
|
||||
val preview = Preview.Builder()
|
||||
.setTargetResolution(resolution)
|
||||
.build()
|
||||
|
||||
val imageAnalysis = ImageAnalysis.Builder()
|
||||
.setTargetAspectRatio(AspectRatio.RATIO_4_3)
|
||||
.setTargetResolution(resolution)
|
||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
|
||||
.build()
|
||||
|
||||
@@ -88,10 +109,13 @@ internal class ScannerView21 constructor(
|
||||
}
|
||||
|
||||
cameraProvider.unbindAll()
|
||||
camera = cameraProvider.bindToLifecycle(lifecycle, CameraSelector.DEFAULT_BACK_CAMERA, preview, imageAnalysis)
|
||||
camera = cameraProvider.bindToLifecycle(lifecycle, cameraSelector, preview, imageAnalysis)
|
||||
|
||||
preview.setSurfaceProvider(previewView.surfaceProvider)
|
||||
|
||||
Log.d(TAG, "Preview: ${preview.resolutionInfo}")
|
||||
Log.d(TAG, "Analysis: ${imageAnalysis.resolutionInfo}")
|
||||
|
||||
this.cameraProvider = cameraProvider
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public class QrCameraView extends ViewGroup {
|
||||
private final OnOrientationChange onOrientationChange;
|
||||
|
||||
private volatile Optional<Camera> camera = Optional.empty();
|
||||
private final int cameraId = CameraInfo.CAMERA_FACING_BACK;
|
||||
private volatile int cameraId = CameraInfo.CAMERA_FACING_BACK;
|
||||
private volatile int displayOrientation = -1;
|
||||
|
||||
private @NonNull State state = State.PAUSED;
|
||||
@@ -161,6 +161,14 @@ public class QrCameraView extends ViewGroup {
|
||||
return state != State.PAUSED;
|
||||
}
|
||||
|
||||
public void toggleCamera() {
|
||||
if (cameraId == CameraInfo.CAMERA_FACING_BACK) {
|
||||
cameraId = CameraInfo.CAMERA_FACING_FRONT;
|
||||
} else {
|
||||
cameraId = CameraInfo.CAMERA_FACING_BACK;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
|
||||
Reference in New Issue
Block a user