Julian Steenbakker
Committed by GitHub

Merge pull request #1393 from juliansteenbakker/hotfix/hot-reload

fix: hot reload
@@ -440,12 +440,14 @@ class MobileScanner( @@ -440,12 +440,14 @@ class MobileScanner(
440 /** 440 /**
441 * Pause barcode scanning. 441 * Pause barcode scanning.
442 */ 442 */
443 - fun pause() { 443 + fun pause(force: Boolean = false) {
  444 + if (!force) {
444 if (isPaused) { 445 if (isPaused) {
445 throw AlreadyPaused() 446 throw AlreadyPaused()
446 } else if (isStopped()) { 447 } else if (isStopped()) {
447 throw AlreadyStopped() 448 throw AlreadyStopped()
448 } 449 }
  450 + }
449 451
450 pauseCamera() 452 pauseCamera()
451 } 453 }
@@ -453,10 +455,12 @@ class MobileScanner( @@ -453,10 +455,12 @@ class MobileScanner(
453 /** 455 /**
454 * Stop barcode scanning. 456 * Stop barcode scanning.
455 */ 457 */
456 - fun stop() { 458 + fun stop(force: Boolean = false) {
  459 + if (!force) {
457 if (!isPaused && isStopped()) { 460 if (!isPaused && isStopped()) {
458 throw AlreadyStopped() 461 throw AlreadyStopped()
459 } 462 }
  463 + }
460 464
461 releaseCamera() 465 releaseCamera()
462 } 466 }
@@ -118,8 +118,8 @@ class MobileScannerHandler( @@ -118,8 +118,8 @@ class MobileScannerHandler(
118 } 118 }
119 }) 119 })
120 "start" -> start(call, result) 120 "start" -> start(call, result)
121 - "pause" -> pause(result)  
122 - "stop" -> stop(result) 121 + "pause" -> pause(call, result)
  122 + "stop" -> stop(call, result)
123 "toggleTorch" -> toggleTorch(result) 123 "toggleTorch" -> toggleTorch(result)
124 "analyzeImage" -> analyzeImage(call, result) 124 "analyzeImage" -> analyzeImage(call, result)
125 "setScale" -> setScale(call, result) 125 "setScale" -> setScale(call, result)
@@ -214,9 +214,10 @@ class MobileScannerHandler( @@ -214,9 +214,10 @@ class MobileScannerHandler(
214 ) 214 )
215 } 215 }
216 216
217 - private fun pause(result: MethodChannel.Result) { 217 + private fun pause(call: MethodCall, result: MethodChannel.Result) {
  218 + val force: Boolean = call.argument<Boolean>("force") ?: false
218 try { 219 try {
219 - mobileScanner!!.pause() 220 + mobileScanner!!.pause(force)
220 result.success(null) 221 result.success(null)
221 } catch (e: Exception) { 222 } catch (e: Exception) {
222 when (e) { 223 when (e) {
@@ -226,9 +227,10 @@ class MobileScannerHandler( @@ -226,9 +227,10 @@ class MobileScannerHandler(
226 } 227 }
227 } 228 }
228 229
229 - private fun stop(result: MethodChannel.Result) { 230 + private fun stop(call: MethodCall, result: MethodChannel.Result) {
  231 + val force: Boolean = call.argument<Boolean>("force") ?: false
230 try { 232 try {
231 - mobileScanner!!.stop() 233 + mobileScanner!!.stop(force)
232 result.success(null) 234 result.success(null)
233 } catch (e: AlreadyStopped) { 235 } catch (e: AlreadyStopped) {
234 result.success(null) 236 result.success(null)
@@ -59,6 +59,7 @@ @@ -59,6 +59,7 @@
59 ignoresPersistentStateOnLaunch = "NO" 59 ignoresPersistentStateOnLaunch = "NO"
60 debugDocumentVersioning = "YES" 60 debugDocumentVersioning = "YES"
61 debugServiceExtension = "internal" 61 debugServiceExtension = "internal"
  62 + enableGPUValidationMode = "1"
62 allowLocationSimulation = "YES"> 63 allowLocationSimulation = "YES">
63 <BuildableProductRunnable 64 <BuildableProductRunnable
64 runnableDebuggingMode = "0"> 65 runnableDebuggingMode = "0">
@@ -303,18 +303,20 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega @@ -303,18 +303,20 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
303 } 303 }
304 304
305 /// Pause scanning for barcodes 305 /// Pause scanning for barcodes
306 - func pause() throws { 306 + func pause(force: Bool = false) throws {
  307 + if (!force) {
307 if (paused) { 308 if (paused) {
308 throw MobileScannerError.alreadyPaused 309 throw MobileScannerError.alreadyPaused
309 } else if (stopped) { 310 } else if (stopped) {
310 throw MobileScannerError.alreadyStopped 311 throw MobileScannerError.alreadyStopped
311 } 312 }
  313 + }
312 releaseCamera() 314 releaseCamera()
313 } 315 }
314 316
315 /// Stop scanning for barcodes 317 /// Stop scanning for barcodes
316 - func stop() throws {  
317 - if (!paused && stopped) { 318 + func stop(force: Bool = false) throws {
  319 + if (!paused && stopped && !force) {
318 throw MobileScannerError.alreadyStopped 320 throw MobileScannerError.alreadyStopped
319 } 321 }
320 releaseCamera() 322 releaseCamera()
@@ -343,7 +345,9 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega @@ -343,7 +345,9 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega
343 } 345 }
344 346
345 private func releaseTexture() { 347 private func releaseTexture() {
  348 + if (textureId != nil) {
346 registry?.unregisterTexture(textureId) 349 registry?.unregisterTexture(textureId)
  350 + }
347 textureId = nil 351 textureId = nil
348 scanner = nil 352 scanner = nil
349 } 353 }
@@ -106,9 +106,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { @@ -106,9 +106,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin {
106 case "start": 106 case "start":
107 start(call, result) 107 start(call, result)
108 case "pause": 108 case "pause":
109 - pause(result) 109 + pause(call, result)
110 case "stop": 110 case "stop":
111 - stop(result) 111 + stop(call, result)
112 case "toggleTorch": 112 case "toggleTorch":
113 toggleTorch(result) 113 toggleTorch(result)
114 case "analyzeImage": 114 case "analyzeImage":
@@ -170,17 +170,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { @@ -170,17 +170,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin {
170 } 170 }
171 171
172 /// Stops the mobileScanner without closing the texture. 172 /// Stops the mobileScanner without closing the texture.
173 - private func pause(_ result: @escaping FlutterResult) { 173 + private func pause(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  174 + let force = (call.arguments as? Bool) ?? false
174 do { 175 do {
175 - try mobileScanner.pause() 176 + try mobileScanner.pause(force: force)
176 } catch {} 177 } catch {}
177 result(nil) 178 result(nil)
178 } 179 }
179 180
180 /// Stops the mobileScanner and closes the texture. 181 /// Stops the mobileScanner and closes the texture.
181 - private func stop(_ result: @escaping FlutterResult) { 182 + private func stop(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  183 + let force = (call.arguments as? Bool) ?? false
182 do { 184 do {
183 - try mobileScanner.stop() 185 + try mobileScanner.stop(force: force)
184 } catch {} 186 } catch {}
185 result(nil) 187 result(nil)
186 } 188 }
@@ -292,26 +292,26 @@ class MethodChannelMobileScanner extends MobileScannerPlatform { @@ -292,26 +292,26 @@ class MethodChannelMobileScanner extends MobileScannerPlatform {
292 } 292 }
293 293
294 @override 294 @override
295 - Future<void> stop() async {  
296 - if (_textureId == null) { 295 + Future<void> stop({bool force = false}) async {
  296 + if (_textureId == null && !force) {
297 return; 297 return;
298 } 298 }
299 299
300 _textureId = null; 300 _textureId = null;
301 _pausing = false; 301 _pausing = false;
302 302
303 - await methodChannel.invokeMethod<void>('stop'); 303 + await methodChannel.invokeMethod<void>('stop', {'force': force});
304 } 304 }
305 305
306 @override 306 @override
307 - Future<void> pause() async { 307 + Future<void> pause({bool force = false}) async {
308 if (_pausing) { 308 if (_pausing) {
309 return; 309 return;
310 } 310 }
311 311
312 _pausing = true; 312 _pausing = true;
313 313
314 - await methodChannel.invokeMethod<void>('pause'); 314 + await methodChannel.invokeMethod<void>('pause', {'force': force});
315 } 315 }
316 316
317 @override 317 @override
1 import 'dart:async'; 1 import 'dart:async';
2 2
  3 +import 'package:flutter/foundation.dart';
3 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
  5 +import 'package:mobile_scanner/src/method_channel/mobile_scanner_method_channel.dart';
4 import 'package:mobile_scanner/src/mobile_scanner_controller.dart'; 6 import 'package:mobile_scanner/src/mobile_scanner_controller.dart';
5 import 'package:mobile_scanner/src/mobile_scanner_exception.dart'; 7 import 'package:mobile_scanner/src/mobile_scanner_exception.dart';
6 import 'package:mobile_scanner/src/mobile_scanner_platform_interface.dart'; 8 import 'package:mobile_scanner/src/mobile_scanner_platform_interface.dart';
@@ -257,19 +259,22 @@ class _MobileScannerState extends State<MobileScanner> @@ -257,19 +259,22 @@ class _MobileScannerState extends State<MobileScanner>
257 StreamSubscription? _subscription; 259 StreamSubscription? _subscription;
258 260
259 Future<void> initMobileScanner() async { 261 Future<void> initMobileScanner() async {
260 - // TODO: This will be fixed in another PR  
261 // If debug mode is enabled, stop the controller first before starting it. 262 // If debug mode is enabled, stop the controller first before starting it.
262 // If a hot-restart is initiated, the controller won't be stopped, and because 263 // If a hot-restart is initiated, the controller won't be stopped, and because
263 // there is no way of knowing if a hot-restart has happened, we must assume 264 // there is no way of knowing if a hot-restart has happened, we must assume
264 - // every start is a hot-restart.  
265 - // if (kDebugMode) {  
266 - // try {  
267 - // await controller.stop();  
268 - // } catch (e) {  
269 - // // Don't do anything if the controller is already stopped.  
270 - // debugPrint('$e');  
271 - // }  
272 - // } 265 + // every start is a hot-restart. Related issue:
  266 + // https://github.com/flutter/flutter/issues/10437
  267 + if (kDebugMode) {
  268 + if (MobileScannerPlatform.instance
  269 + case final MethodChannelMobileScanner implementation) {
  270 + try {
  271 + await implementation.stop(force: true);
  272 + } catch (e) {
  273 + // Don't do anything if the controller is already stopped.
  274 + debugPrint('$e');
  275 + }
  276 + }
  277 + }
273 278
274 if (widget.controller == null) { 279 if (widget.controller == null) {
275 WidgetsBinding.instance.addObserver(this); 280 WidgetsBinding.instance.addObserver(this);
@@ -76,9 +76,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -76,9 +76,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
76 case "resetScale": 76 case "resetScale":
77 resetScale(call, result) 77 resetScale(call, result)
78 case "pause": 78 case "pause":
79 - pause(result) 79 + pause(call, result)
80 case "stop": 80 case "stop":
81 - stop(result) 81 + stop(call, result)
82 case "updateScanWindow": 82 case "updateScanWindow":
83 updateScanWindow(call, result) 83 updateScanWindow(call, result)
84 case "analyzeImage": 84 case "analyzeImage":
@@ -448,19 +448,24 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -448,19 +448,24 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
448 result(nil) 448 result(nil)
449 } 449 }
450 450
451 - func pause(_ result: FlutterResult) { 451 + func pause(_ call: FlutterMethodCall, _ result: FlutterResult) {
  452 + let force = (call.arguments as? Bool) ?? false
  453 + if (!force) {
452 if (paused || stopped) { 454 if (paused || stopped) {
453 result(nil) 455 result(nil)
454 456
455 return 457 return
456 } 458 }
  459 + }
  460 +
457 releaseCamera() 461 releaseCamera()
458 462
459 result(nil) 463 result(nil)
460 } 464 }
461 465
462 - func stop(_ result: FlutterResult) {  
463 - if (!paused && stopped) { 466 + func stop(_ call: FlutterMethodCall, _ result: FlutterResult) {
  467 + let force = (call.arguments as? Bool) ?? false
  468 + if (!paused && stopped && !force) {
464 result(nil) 469 result(nil)
465 470
466 return 471 return
@@ -491,6 +496,10 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -491,6 +496,10 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
491 } 496 }
492 497
493 private func releaseTexture() { 498 private func releaseTexture() {
  499 + if (textureId == nil) {
  500 + return
  501 + }
  502 +
494 registry.unregisterTexture(textureId) 503 registry.unregisterTexture(textureId)
495 textureId = nil 504 textureId = nil
496 } 505 }