Navaron Bracke

fix deprecated getter use; fix leaking of display listener instances

@@ -26,6 +26,7 @@ import android.util.Size @@ -26,6 +26,7 @@ import android.util.Size
26 import android.hardware.display.DisplayManager 26 import android.hardware.display.DisplayManager
27 import android.view.WindowManager 27 import android.view.WindowManager
28 import android.content.Context 28 import android.content.Context
  29 +import android.os.Build
29 30
30 31
31 class MobileScanner( 32 class MobileScanner(
@@ -43,6 +44,7 @@ class MobileScanner( @@ -43,6 +44,7 @@ class MobileScanner(
43 private var scanner = BarcodeScanning.getClient() 44 private var scanner = BarcodeScanning.getClient()
44 private var lastScanned: List<String?>? = null 45 private var lastScanned: List<String?>? = null
45 private var scannerTimeout = false 46 private var scannerTimeout = false
  47 + private var displayListener: MobileScannerDisplayListener? = null
46 48
47 /// Configurable variables 49 /// Configurable variables
48 var scanWindow: List<Float>? = null 50 var scanWindow: List<Float>? = null
@@ -171,11 +173,22 @@ class MobileScanner( @@ -171,11 +173,22 @@ class MobileScanner(
171 } 173 }
172 174
173 // Return the best resolution for the actual device orientation. 175 // Return the best resolution for the actual device orientation.
174 - // By default camera set its resolution to width 480 and height 640 which is too low for ML KIT.  
175 - // If we return an higher resolution than device can handle, camera package take the most relevant one available.  
176 - // Resolution set must take care of device orientation to preserve aspect ratio.  
177 - private fun getResolution(windowManager: WindowManager, cameraResolution: Size): Size {  
178 - val rotation = windowManager.defaultDisplay.rotation 176 + //
  177 + // By default the resolution is 480x640, which is too low for ML Kit.
  178 + // If the given resolution is not supported by the display,
  179 + // the closest available resolution is used.
  180 + //
  181 + // The resolution should be adjusted for the display rotation, to preserve the aspect ratio.
  182 + @Suppress("deprecation")
  183 + private fun getResolution(cameraResolution: Size): Size {
  184 + val rotation = if (Build.VERSION.SDK_INT >= 30) {
  185 + activity.applicationContext.display!!.rotation
  186 + } else {
  187 + val windowManager = activity.applicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
  188 +
  189 + windowManager.defaultDisplay.rotation
  190 + }
  191 +
179 val widthMaxRes = cameraResolution.width 192 val widthMaxRes = cameraResolution.width
180 val heightMaxRes = cameraResolution.height 193 val heightMaxRes = cameraResolution.height
181 194
@@ -187,7 +200,6 @@ class MobileScanner( @@ -187,7 +200,6 @@ class MobileScanner(
187 return targetResolution 200 return targetResolution
188 } 201 }
189 202
190 -  
191 /** 203 /**
192 * Start barcode scanning by initializing the camera and barcode scanner. 204 * Start barcode scanning by initializing the camera and barcode scanner.
193 */ 205 */
@@ -253,19 +265,21 @@ class MobileScanner( @@ -253,19 +265,21 @@ class MobileScanner(
253 val analysisBuilder = ImageAnalysis.Builder() 265 val analysisBuilder = ImageAnalysis.Builder()
254 .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) 266 .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
255 val displayManager = activity.applicationContext.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager 267 val displayManager = activity.applicationContext.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
256 - val windowManager = activity.applicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager  
257 268
258 if (cameraResolution != null) { 269 if (cameraResolution != null) {
  270 + // TODO: migrate to ResolutionSelector with ResolutionStrategy when upgrading to camera 1.3.0
259 // Override initial resolution 271 // Override initial resolution
260 - analysisBuilder.setTargetResolution(getResolution(windowManager, cameraResolution))  
261 - // Listen future orientation change to apply the custom resolution  
262 - displayManager.registerDisplayListener(object : DisplayManager.DisplayListener {  
263 - override fun onDisplayAdded(displayId: Int) {}  
264 - override fun onDisplayRemoved(displayId: Int) {}  
265 - override fun onDisplayChanged(displayId: Int) {  
266 - analysisBuilder.setTargetResolution(getResolution(windowManager, cameraResolution)) 272 + analysisBuilder.setTargetResolution(getResolution(cameraResolution))
  273 +
  274 + if (displayListener == null) {
  275 + displayListener = MobileScannerDisplayListener {
  276 + analysisBuilder.setTargetResolution(getResolution(cameraResolution))
267 } 277 }
268 - }, null) 278 +
  279 + displayManager.registerDisplayListener(
  280 + displayListener, null,
  281 + )
  282 + }
269 } 283 }
270 284
271 val analysis = analysisBuilder.build().apply { setAnalyzer(executor, captureOutput) } 285 val analysis = analysisBuilder.build().apply { setAnalyzer(executor, captureOutput) }
@@ -316,6 +330,13 @@ class MobileScanner( @@ -316,6 +330,13 @@ class MobileScanner(
316 throw AlreadyStopped() 330 throw AlreadyStopped()
317 } 331 }
318 332
  333 + if (displayListener != null) {
  334 + val displayManager = activity.applicationContext.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
  335 +
  336 + displayManager.unregisterDisplayListener(displayListener)
  337 + displayListener = null
  338 + }
  339 +
319 val owner = activity as LifecycleOwner 340 val owner = activity as LifecycleOwner
320 camera?.cameraInfo?.torchState?.removeObservers(owner) 341 camera?.cameraInfo?.torchState?.removeObservers(owner)
321 cameraProvider?.unbindAll() 342 cameraProvider?.unbindAll()