Julian Steenbakker
Committed by GitHub

Merge pull request #21 from juliansteenbakker/bug/start-stop-crash

bugfix: Fixed crash on multiple start() or stop() calls.
1 -include: package:flutter_lints/flutter.yaml  
  1 +include: package:flutter_lints/flutter.yaml
  2 +
  3 +linter:
  4 + rules:
  5 + unawaited_futures: true
@@ -38,8 +38,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -38,8 +38,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
38 private var camera: Camera? = null 38 private var camera: Camera? = null
39 private var textureEntry: TextureRegistry.SurfaceTextureEntry? = null 39 private var textureEntry: TextureRegistry.SurfaceTextureEntry? = null
40 40
41 - @AnalyzeMode  
42 - private var analyzeMode: Int = AnalyzeMode.NONE 41 +// @AnalyzeMode
  42 +// private var analyzeMode: Int = AnalyzeMode.NONE
43 43
44 @ExperimentalGetImage 44 @ExperimentalGetImage
45 override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) { 45 override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) {
@@ -47,8 +47,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -47,8 +47,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
47 "state" -> checkPermission(result) 47 "state" -> checkPermission(result)
48 "request" -> requestPermission(result) 48 "request" -> requestPermission(result)
49 "start" -> start(call, result) 49 "start" -> start(call, result)
50 - "torch" -> switchTorch(call, result)  
51 - "analyze" -> switchAnalyzeMode(call, result) 50 + "torch" -> toggleTorch(call, result)
  51 +// "analyze" -> switchAnalyzeMode(call, result)
52 "stop" -> stop(result) 52 "stop" -> stop(result)
53 else -> result.notImplemented() 53 else -> result.notImplemented()
54 } 54 }
@@ -92,8 +92,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -92,8 +92,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
92 92
93 @ExperimentalGetImage 93 @ExperimentalGetImage
94 val analyzer = ImageAnalysis.Analyzer { imageProxy -> // YUV_420_888 format 94 val analyzer = ImageAnalysis.Analyzer { imageProxy -> // YUV_420_888 format
95 - when (analyzeMode) {  
96 - AnalyzeMode.BARCODE -> { 95 +// when (analyzeMode) {
  96 +// AnalyzeMode.BARCODE -> {
97 val mediaImage = imageProxy.image ?: return@Analyzer 97 val mediaImage = imageProxy.image ?: return@Analyzer
98 val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) 98 val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
99 99
@@ -106,9 +106,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -106,9 +106,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
106 } 106 }
107 .addOnFailureListener { e -> Log.e(TAG, e.message, e) } 107 .addOnFailureListener { e -> Log.e(TAG, e.message, e) }
108 .addOnCompleteListener { imageProxy.close() } 108 .addOnCompleteListener { imageProxy.close() }
109 - }  
110 - else -> imageProxy.close()  
111 - } 109 +// }
  110 +// else -> imageProxy.close()
  111 +// }
112 } 112 }
113 113
114 114
@@ -116,6 +116,10 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -116,6 +116,10 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
116 116
117 @ExperimentalGetImage 117 @ExperimentalGetImage
118 private fun start(call: MethodCall, result: MethodChannel.Result) { 118 private fun start(call: MethodCall, result: MethodChannel.Result) {
  119 + if (camera != null) {
  120 + result.error(TAG, "Called start() while already started!", null)
  121 + return
  122 + }
119 123
120 val facing: Int = call.argument<Int>("facing") ?: 0 124 val facing: Int = call.argument<Int>("facing") ?: 0
121 val ratio: Int? = call.argument<Int>("ratio") 125 val ratio: Int? = call.argument<Int>("ratio")
@@ -186,24 +190,32 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -186,24 +190,32 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
186 }, executor) 190 }, executor)
187 } 191 }
188 192
189 - private fun switchTorch(call: MethodCall, result: MethodChannel.Result) {  
190 - val state = call.arguments == 1  
191 - camera!!.cameraControl.enableTorch(state) 193 + private fun toggleTorch(call: MethodCall, result: MethodChannel.Result) {
  194 + if (camera == null) {
  195 + result.error(TAG,"Called toggleTorch() while stopped!", null)
  196 + return
  197 + }
  198 + camera!!.cameraControl.enableTorch(call.arguments == 1)
192 result.success(null) 199 result.success(null)
193 } 200 }
194 201
195 - private fun switchAnalyzeMode(call: MethodCall, result: MethodChannel.Result) {  
196 - analyzeMode = call.arguments as Int  
197 - result.success(null)  
198 - } 202 +// private fun switchAnalyzeMode(call: MethodCall, result: MethodChannel.Result) {
  203 +// analyzeMode = call.arguments as Int
  204 +// result.success(null)
  205 +// }
199 206
200 private fun stop(result: MethodChannel.Result) { 207 private fun stop(result: MethodChannel.Result) {
  208 + if (camera == null) {
  209 + result.error(TAG,"Called stop() while already stopped!", null)
  210 + return
  211 + }
  212 +
201 val owner = activity as LifecycleOwner 213 val owner = activity as LifecycleOwner
202 camera!!.cameraInfo.torchState.removeObservers(owner) 214 camera!!.cameraInfo.torchState.removeObservers(owner)
203 cameraProvider!!.unbindAll() 215 cameraProvider!!.unbindAll()
204 textureEntry!!.release() 216 textureEntry!!.release()
205 217
206 - analyzeMode = AnalyzeMode.NONE 218 +// analyzeMode = AnalyzeMode.NONE
207 camera = null 219 camera = null
208 textureEntry = null 220 textureEntry = null
209 cameraProvider = null 221 cameraProvider = null
1 -platform :osx, '10.11' 1 +platform :osx, '10.13'
2 2
3 # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 3 # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
4 ENV['COCOAPODS_DISABLE_STATS'] = 'true' 4 ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 26 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
27 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 27 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
28 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 28 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
29 - 5225F51353DA345E2811B6A4 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65E614A1DF8B88C7B0CE1B97 /* Pods_Runner.framework */; }; 29 + 5B9BD2ADBC68B74D80B57DF1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC099C2B6D6B30BFB3FA6DB8 /* Pods_Runner.framework */; };
30 /* End PBXBuildFile section */ 30 /* End PBXBuildFile section */
31 31
32 /* Begin PBXContainerItemProxy section */ 32 /* Begin PBXContainerItemProxy section */
@@ -67,12 +67,12 @@ @@ -67,12 +67,12 @@
67 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; }; 67 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
68 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; }; 68 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
69 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; }; 69 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
70 - 65E614A1DF8B88C7B0CE1B97 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 70 + 3CEE8DB43A84811F33EB0202 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
71 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; }; 71 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
72 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; }; 72 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
73 - CB0901144E09E7D7CA20584F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };  
74 - D522F9F6F348C5944077606B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };  
75 - F63009B5E287A1C82F9D7D2F /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; 73 + A1CBC07680A8ED396DBB68C0 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
  74 + CAD760C57A57D903AB03B47A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
  75 + EC099C2B6D6B30BFB3FA6DB8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
76 /* End PBXFileReference section */ 76 /* End PBXFileReference section */
77 77
78 /* Begin PBXFrameworksBuildPhase section */ 78 /* Begin PBXFrameworksBuildPhase section */
@@ -80,19 +80,27 @@ @@ -80,19 +80,27 @@
80 isa = PBXFrameworksBuildPhase; 80 isa = PBXFrameworksBuildPhase;
81 buildActionMask = 2147483647; 81 buildActionMask = 2147483647;
82 files = ( 82 files = (
83 - 5225F51353DA345E2811B6A4 /* Pods_Runner.framework in Frameworks */, 83 + 5B9BD2ADBC68B74D80B57DF1 /* Pods_Runner.framework in Frameworks */,
84 ); 84 );
85 runOnlyForDeploymentPostprocessing = 0; 85 runOnlyForDeploymentPostprocessing = 0;
86 }; 86 };
87 /* End PBXFrameworksBuildPhase section */ 87 /* End PBXFrameworksBuildPhase section */
88 88
89 /* Begin PBXGroup section */ 89 /* Begin PBXGroup section */
  90 + 18927D60C719EB75FC0A6633 /* Frameworks */ = {
  91 + isa = PBXGroup;
  92 + children = (
  93 + EC099C2B6D6B30BFB3FA6DB8 /* Pods_Runner.framework */,
  94 + );
  95 + name = Frameworks;
  96 + sourceTree = "<group>";
  97 + };
90 20F8C9AA20C2A495C125E194 /* Pods */ = { 98 20F8C9AA20C2A495C125E194 /* Pods */ = {
91 isa = PBXGroup; 99 isa = PBXGroup;
92 children = ( 100 children = (
93 - CB0901144E09E7D7CA20584F /* Pods-Runner.debug.xcconfig */,  
94 - D522F9F6F348C5944077606B /* Pods-Runner.release.xcconfig */,  
95 - F63009B5E287A1C82F9D7D2F /* Pods-Runner.profile.xcconfig */, 101 + CAD760C57A57D903AB03B47A /* Pods-Runner.debug.xcconfig */,
  102 + A1CBC07680A8ED396DBB68C0 /* Pods-Runner.release.xcconfig */,
  103 + 3CEE8DB43A84811F33EB0202 /* Pods-Runner.profile.xcconfig */,
96 ); 104 );
97 path = Pods; 105 path = Pods;
98 sourceTree = "<group>"; 106 sourceTree = "<group>";
@@ -115,7 +123,7 @@ @@ -115,7 +123,7 @@
115 33CEB47122A05771004F2AC0 /* Flutter */, 123 33CEB47122A05771004F2AC0 /* Flutter */,
116 33CC10EE2044A3C60003C045 /* Products */, 124 33CC10EE2044A3C60003C045 /* Products */,
117 20F8C9AA20C2A495C125E194 /* Pods */, 125 20F8C9AA20C2A495C125E194 /* Pods */,
118 - 3539353E79638640B4999C09 /* Frameworks */, 126 + 18927D60C719EB75FC0A6633 /* Frameworks */,
119 ); 127 );
120 sourceTree = "<group>"; 128 sourceTree = "<group>";
121 }; 129 };
@@ -162,14 +170,6 @@ @@ -162,14 +170,6 @@
162 path = Runner; 170 path = Runner;
163 sourceTree = "<group>"; 171 sourceTree = "<group>";
164 }; 172 };
165 - 3539353E79638640B4999C09 /* Frameworks */ = {  
166 - isa = PBXGroup;  
167 - children = (  
168 - 65E614A1DF8B88C7B0CE1B97 /* Pods_Runner.framework */,  
169 - );  
170 - name = Frameworks;  
171 - sourceTree = "<group>";  
172 - };  
173 /* End PBXGroup section */ 173 /* End PBXGroup section */
174 174
175 /* Begin PBXNativeTarget section */ 175 /* Begin PBXNativeTarget section */
@@ -177,13 +177,13 @@ @@ -177,13 +177,13 @@
177 isa = PBXNativeTarget; 177 isa = PBXNativeTarget;
178 buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; 178 buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
179 buildPhases = ( 179 buildPhases = (
180 - 696298230BDAD783AEC51C81 /* [CP] Check Pods Manifest.lock */, 180 + 20903D1E9D9F08576541FFD7 /* [CP] Check Pods Manifest.lock */,
181 33CC10E92044A3C60003C045 /* Sources */, 181 33CC10E92044A3C60003C045 /* Sources */,
182 33CC10EA2044A3C60003C045 /* Frameworks */, 182 33CC10EA2044A3C60003C045 /* Frameworks */,
183 33CC10EB2044A3C60003C045 /* Resources */, 183 33CC10EB2044A3C60003C045 /* Resources */,
184 33CC110E2044A8840003C045 /* Bundle Framework */, 184 33CC110E2044A8840003C045 /* Bundle Framework */,
185 3399D490228B24CF009A79C7 /* ShellScript */, 185 3399D490228B24CF009A79C7 /* ShellScript */,
186 - 8A90D2BC4083C5ACCEEBF32B /* [CP] Embed Pods Frameworks */, 186 + DF45614760BB9B24F49B2055 /* [CP] Embed Pods Frameworks */,
187 ); 187 );
188 buildRules = ( 188 buildRules = (
189 ); 189 );
@@ -253,7 +253,7 @@ @@ -253,7 +253,7 @@
253 /* End PBXResourcesBuildPhase section */ 253 /* End PBXResourcesBuildPhase section */
254 254
255 /* Begin PBXShellScriptBuildPhase section */ 255 /* Begin PBXShellScriptBuildPhase section */
256 - 3399D490228B24CF009A79C7 /* ShellScript */ = { 256 + 20903D1E9D9F08576541FFD7 /* [CP] Check Pods Manifest.lock */ = {
257 isa = PBXShellScriptBuildPhase; 257 isa = PBXShellScriptBuildPhase;
258 buildActionMask = 2147483647; 258 buildActionMask = 2147483647;
259 files = ( 259 files = (
@@ -261,58 +261,58 @@ @@ -261,58 +261,58 @@
261 inputFileListPaths = ( 261 inputFileListPaths = (
262 ); 262 );
263 inputPaths = ( 263 inputPaths = (
  264 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  265 + "${PODS_ROOT}/Manifest.lock",
264 ); 266 );
  267 + name = "[CP] Check Pods Manifest.lock";
265 outputFileListPaths = ( 268 outputFileListPaths = (
266 ); 269 );
267 outputPaths = ( 270 outputPaths = (
  271 + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
268 ); 272 );
269 runOnlyForDeploymentPostprocessing = 0; 273 runOnlyForDeploymentPostprocessing = 0;
270 shellPath = /bin/sh; 274 shellPath = /bin/sh;
271 - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; 275 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  276 + showEnvVarsInLog = 0;
272 }; 277 };
273 - 33CC111E2044C6BF0003C045 /* ShellScript */ = { 278 + 3399D490228B24CF009A79C7 /* ShellScript */ = {
274 isa = PBXShellScriptBuildPhase; 279 isa = PBXShellScriptBuildPhase;
275 buildActionMask = 2147483647; 280 buildActionMask = 2147483647;
276 files = ( 281 files = (
277 ); 282 );
278 inputFileListPaths = ( 283 inputFileListPaths = (
279 - Flutter/ephemeral/FlutterInputs.xcfilelist,  
280 ); 284 );
281 inputPaths = ( 285 inputPaths = (
282 - Flutter/ephemeral/tripwire,  
283 ); 286 );
284 outputFileListPaths = ( 287 outputFileListPaths = (
285 - Flutter/ephemeral/FlutterOutputs.xcfilelist,  
286 ); 288 );
287 outputPaths = ( 289 outputPaths = (
288 ); 290 );
289 runOnlyForDeploymentPostprocessing = 0; 291 runOnlyForDeploymentPostprocessing = 0;
290 shellPath = /bin/sh; 292 shellPath = /bin/sh;
291 - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; 293 + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
292 }; 294 };
293 - 696298230BDAD783AEC51C81 /* [CP] Check Pods Manifest.lock */ = { 295 + 33CC111E2044C6BF0003C045 /* ShellScript */ = {
294 isa = PBXShellScriptBuildPhase; 296 isa = PBXShellScriptBuildPhase;
295 buildActionMask = 2147483647; 297 buildActionMask = 2147483647;
296 files = ( 298 files = (
297 ); 299 );
298 inputFileListPaths = ( 300 inputFileListPaths = (
  301 + Flutter/ephemeral/FlutterInputs.xcfilelist,
299 ); 302 );
300 inputPaths = ( 303 inputPaths = (
301 - "${PODS_PODFILE_DIR_PATH}/Podfile.lock",  
302 - "${PODS_ROOT}/Manifest.lock", 304 + Flutter/ephemeral/tripwire,
303 ); 305 );
304 - name = "[CP] Check Pods Manifest.lock";  
305 outputFileListPaths = ( 306 outputFileListPaths = (
  307 + Flutter/ephemeral/FlutterOutputs.xcfilelist,
306 ); 308 );
307 outputPaths = ( 309 outputPaths = (
308 - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",  
309 ); 310 );
310 runOnlyForDeploymentPostprocessing = 0; 311 runOnlyForDeploymentPostprocessing = 0;
311 shellPath = /bin/sh; 312 shellPath = /bin/sh;
312 - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";  
313 - showEnvVarsInLog = 0; 313 + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
314 }; 314 };
315 - 8A90D2BC4083C5ACCEEBF32B /* [CP] Embed Pods Frameworks */ = { 315 + DF45614760BB9B24F49B2055 /* [CP] Embed Pods Frameworks */ = {
316 isa = PBXShellScriptBuildPhase; 316 isa = PBXShellScriptBuildPhase;
317 buildActionMask = 2147483647; 317 buildActionMask = 2147483647;
318 files = ( 318 files = (
@@ -23,7 +23,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -23,7 +23,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
23 var latestBuffer: CVImageBuffer! 23 var latestBuffer: CVImageBuffer!
24 24
25 25
26 - var analyzeMode: Int = 0 26 +// var analyzeMode: Int = 0
27 var analyzing: Bool = false 27 var analyzing: Bool = false
28 var position = AVCaptureDevice.Position.back 28 var position = AVCaptureDevice.Position.back
29 29
@@ -53,9 +53,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -53,9 +53,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
53 case "start": 53 case "start":
54 start(call, result) 54 start(call, result)
55 case "torch": 55 case "torch":
56 - switchTorch(call, result)  
57 - case "analyze":  
58 - switchAnalyzeMode(call, result) 56 + toggleTorch(call, result)
  57 +// case "analyze":
  58 +// switchAnalyzeMode(call, result)
59 case "stop": 59 case "stop":
60 stop(result) 60 stop(result)
61 default: 61 default:
@@ -89,10 +89,10 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -89,10 +89,10 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
89 latestBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) 89 latestBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
90 registry.textureFrameAvailable(textureId) 90 registry.textureFrameAvailable(textureId)
91 91
92 - switch analyzeMode {  
93 - case 1: // barcode 92 +// switch analyzeMode {
  93 +// case 1: // barcode
94 if analyzing { 94 if analyzing {
95 - break 95 + return
96 } 96 }
97 analyzing = true 97 analyzing = true
98 let buffer = CMSampleBufferGetImageBuffer(sampleBuffer) 98 let buffer = CMSampleBufferGetImageBuffer(sampleBuffer)
@@ -112,9 +112,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -112,9 +112,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
112 } 112 }
113 analyzing = false 113 analyzing = false
114 } 114 }
115 - default: // none  
116 - break  
117 - } 115 +// default: // none
  116 +// break
  117 +// }
118 } 118 }
119 119
120 func imageOrientation( 120 func imageOrientation(
@@ -154,6 +154,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -154,6 +154,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
154 } 154 }
155 155
156 func start(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { 156 func start(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  157 + if (device != nil) {
  158 + result(FlutterError(code: "MobileScanner",
  159 + message: "Called start() while already started!",
  160 + details: nil))
  161 + return
  162 + }
  163 +
157 textureId = registry.register(self) 164 textureId = registry.register(self)
158 captureSession = AVCaptureSession() 165 captureSession = AVCaptureSession()
159 166
@@ -173,6 +180,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -173,6 +180,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
173 device = AVCaptureDevice.devices(for: .video).filter({$0.position == position}).first 180 device = AVCaptureDevice.devices(for: .video).filter({$0.position == position}).first
174 } 181 }
175 182
  183 + if (device == nil) {
  184 + result(FlutterError(code: "MobileScanner",
  185 + message: "No camera found or failed to open camera!",
  186 + details: nil))
  187 + return
  188 + }
  189 +
176 // Enable the torch if parameter is set and torch is available 190 // Enable the torch if parameter is set and torch is available
177 if (device.hasTorch && device.isTorchAvailable) { 191 if (device.hasTorch && device.isTorchAvailable) {
178 do { 192 do {
@@ -219,7 +233,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -219,7 +233,13 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
219 result(answer) 233 result(answer)
220 } 234 }
221 235
222 - func switchTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { 236 + func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  237 + if (device == nil) {
  238 + result(FlutterError(code: "MobileScanner",
  239 + message: "Called toggleTorch() while stopped!",
  240 + details: nil))
  241 + return
  242 + }
223 do { 243 do {
224 try device.lockForConfiguration() 244 try device.lockForConfiguration()
225 device.torchMode = call.arguments as! Int == 1 ? .on : .off 245 device.torchMode = call.arguments as! Int == 1 ? .on : .off
@@ -230,12 +250,18 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -230,12 +250,18 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
230 } 250 }
231 } 251 }
232 252
233 - func switchAnalyzeMode(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {  
234 - analyzeMode = call.arguments as! Int  
235 - result(nil)  
236 - } 253 +// func switchAnalyzeMode(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  254 +// analyzeMode = call.arguments as! Int
  255 +// result(nil)
  256 +// }
237 257
238 func stop(_ result: FlutterResult) { 258 func stop(_ result: FlutterResult) {
  259 + if (device == nil) {
  260 + result(FlutterError(code: "MobileScanner",
  261 + message: "Called stop() while already stopped!",
  262 + details: nil))
  263 + return
  264 + }
239 captureSession.stopRunning() 265 captureSession.stopRunning()
240 for input in captureSession.inputs { 266 for input in captureSession.inputs {
241 captureSession.removeInput(input) 267 captureSession.removeInput(input)
@@ -246,7 +272,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -246,7 +272,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
246 device.removeObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode)) 272 device.removeObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode))
247 registry.unregisterTexture(textureId) 273 registry.unregisterTexture(textureId)
248 274
249 - analyzeMode = 0 275 +// analyzeMode = 0
250 latestBuffer = nil 276 latestBuffer = nil
251 captureSession = nil 277 captureSession = nil
252 device = nil 278 device = nil
@@ -27,7 +27,7 @@ enum TorchState { @@ -27,7 +27,7 @@ enum TorchState {
27 on, 27 on,
28 } 28 }
29 29
30 -enum AnalyzeMode { none, barcode } 30 +// enum AnalyzeMode { none, barcode }
31 31
32 class MobileScannerController { 32 class MobileScannerController {
33 MethodChannel methodChannel = 33 MethodChannel methodChannel =
@@ -62,9 +62,9 @@ class MobileScannerController { @@ -62,9 +62,9 @@ class MobileScannerController {
62 62
63 // Sets analyze mode and barcode stream 63 // Sets analyze mode and barcode stream
64 barcodesController = StreamController.broadcast( 64 barcodesController = StreamController.broadcast(
65 - onListen: () => setAnalyzeMode(AnalyzeMode.barcode.index),  
66 - onCancel: () => setAnalyzeMode(AnalyzeMode.none.index),  
67 - ); 65 + // onListen: () => setAnalyzeMode(AnalyzeMode.barcode.index),
  66 + // onCancel: () => setAnalyzeMode(AnalyzeMode.none.index),
  67 + );
68 68
69 start(); 69 start();
70 70
@@ -94,12 +94,13 @@ class MobileScannerController { @@ -94,12 +94,13 @@ class MobileScannerController {
94 } 94 }
95 } 95 }
96 96
97 - void setAnalyzeMode(int mode) {  
98 - if (hashCode != _controllerHashcode) {  
99 - return;  
100 - }  
101 - methodChannel.invokeMethod('analyze', mode);  
102 - } 97 + // TODO: Add more analyzers like text analyzer
  98 + // void setAnalyzeMode(int mode) {
  99 + // if (hashCode != _controllerHashcode) {
  100 + // return;
  101 + // }
  102 + // methodChannel.invokeMethod('analyze', mode);
  103 + // }
103 104
104 // List<BarcodeFormats>? formats = _defaultBarcodeFormats, 105 // List<BarcodeFormats>? formats = _defaultBarcodeFormats,
105 /// Start barcode scanning. This will first check if the required permissions 106 /// Start barcode scanning. This will first check if the required permissions
@@ -107,7 +108,7 @@ class MobileScannerController { @@ -107,7 +108,7 @@ class MobileScannerController {
107 Future<void> start() async { 108 Future<void> start() async {
108 ensure('startAsync'); 109 ensure('startAsync');
109 110
110 - setAnalyzeMode(AnalyzeMode.barcode.index); 111 + // setAnalyzeMode(AnalyzeMode.barcode.index);
111 // Check authorization status 112 // Check authorization status
112 MobileScannerState state = 113 MobileScannerState state =
113 MobileScannerState.values[await methodChannel.invokeMethod('state')]; 114 MobileScannerState.values[await methodChannel.invokeMethod('state')];
@@ -132,8 +133,15 @@ class MobileScannerController { @@ -132,8 +133,15 @@ class MobileScannerController {
132 if (torchEnabled != null) arguments['torch'] = torchEnabled; 133 if (torchEnabled != null) arguments['torch'] = torchEnabled;
133 134
134 // Start the camera with arguments 135 // Start the camera with arguments
135 - final Map<String, dynamic>? startResult = await methodChannel  
136 - .invokeMapMethod<String, dynamic>('start', arguments); 136 + Map<String, dynamic>? startResult = {};
  137 + try {
  138 + startResult = await methodChannel.invokeMapMethod<String, dynamic>(
  139 + 'start', arguments);
  140 + } on PlatformException catch (error) {
  141 + debugPrint('${error.code}: ${error.message}');
  142 + // setAnalyzeMode(AnalyzeMode.none.index);
  143 + return;
  144 + }
137 145
138 if (startResult == null) { 146 if (startResult == null) {
139 throw PlatformException(code: 'INITIALIZATION ERROR'); 147 throw PlatformException(code: 'INITIALIZATION ERROR');
@@ -146,17 +154,32 @@ class MobileScannerController { @@ -146,17 +154,32 @@ class MobileScannerController {
146 hasTorch: hasTorch); 154 hasTorch: hasTorch);
147 } 155 }
148 156
149 - Future<void> stop() async => await methodChannel.invokeMethod('stop'); 157 + Future<void> stop() async {
  158 + try {
  159 + await methodChannel.invokeMethod('stop');
  160 + } on PlatformException catch (error) {
  161 + debugPrint('${error.code}: ${error.message}');
  162 + }
  163 + }
150 164
151 /// Switches the torch on or off. 165 /// Switches the torch on or off.
152 /// 166 ///
153 /// Only works if torch is available. 167 /// Only works if torch is available.
154 - void toggleTorch() { 168 + Future<void> toggleTorch() async {
155 ensure('toggleTorch'); 169 ensure('toggleTorch');
156 - if (!hasTorch) return; 170 + if (!hasTorch) {
  171 + debugPrint('Device has no torch/flash.');
  172 + return;
  173 + }
  174 +
157 TorchState state = 175 TorchState state =
158 torchState.value == TorchState.off ? TorchState.on : TorchState.off; 176 torchState.value == TorchState.off ? TorchState.on : TorchState.off;
159 - methodChannel.invokeMethod('torch', state.index); 177 +
  178 + try {
  179 + await methodChannel.invokeMethod('torch', state.index);
  180 + } on PlatformException catch (error) {
  181 + debugPrint('${error.code}: ${error.message}');
  182 + }
160 } 183 }
161 184
162 /// Switches the torch on or off. 185 /// Switches the torch on or off.
@@ -164,10 +187,16 @@ class MobileScannerController { @@ -164,10 +187,16 @@ class MobileScannerController {
164 /// Only works if torch is available. 187 /// Only works if torch is available.
165 Future<void> switchCamera() async { 188 Future<void> switchCamera() async {
166 ensure('switchCamera'); 189 ensure('switchCamera');
167 - await stop(); 190 + try {
  191 + await methodChannel.invokeMethod('stop');
  192 + } on PlatformException catch (error) {
  193 + debugPrint(
  194 + '${error.code}: camera is stopped! Please start before switching camera.');
  195 + return;
  196 + }
168 facing = 197 facing =
169 facing == CameraFacing.back ? CameraFacing.front : CameraFacing.back; 198 facing == CameraFacing.back ? CameraFacing.front : CameraFacing.back;
170 - start(); 199 + await start();
171 } 200 }
172 201
173 /// Disposes the controller and closes all listeners. 202 /// Disposes the controller and closes all listeners.
@@ -22,7 +22,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -22,7 +22,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
22 var latestBuffer: CVImageBuffer! 22 var latestBuffer: CVImageBuffer!
23 23
24 24
25 - var analyzeMode: Int = 0 25 +// var analyzeMode: Int = 0
26 var analyzing: Bool = false 26 var analyzing: Bool = false
27 var position = AVCaptureDevice.Position.back 27 var position = AVCaptureDevice.Position.back
28 28
@@ -52,9 +52,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -52,9 +52,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
52 case "start": 52 case "start":
53 start(call, result) 53 start(call, result)
54 case "torch": 54 case "torch":
55 - switchTorch(call, result)  
56 - case "analyze":  
57 - switchAnalyzeMode(call, result) 55 + toggleTorch(call, result)
  56 +// case "analyze":
  57 +// switchAnalyzeMode(call, result)
58 case "stop": 58 case "stop":
59 stop(result) 59 stop(result)
60 default: 60 default:
@@ -92,14 +92,14 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -92,14 +92,14 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
92 latestBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) 92 latestBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
93 registry.textureFrameAvailable(textureId) 93 registry.textureFrameAvailable(textureId)
94 94
95 - switch analyzeMode {  
96 - case 1: // barcode 95 +// switch analyzeMode {
  96 +// case 1: // barcode
97 97
98 // Limit the analyzer because the texture output will freeze otherwise 98 // Limit the analyzer because the texture output will freeze otherwise
99 if i / 10 == 1 { 99 if i / 10 == 1 {
100 i = 0 100 i = 0
101 } else { 101 } else {
102 - break 102 + return
103 } 103 }
104 let imageRequestHandler = VNImageRequestHandler( 104 let imageRequestHandler = VNImageRequestHandler(
105 cvPixelBuffer: latestBuffer, 105 cvPixelBuffer: latestBuffer,
@@ -129,9 +129,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -129,9 +129,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
129 print(error) 129 print(error)
130 } 130 }
131 131
132 - default: // none  
133 - break  
134 - } 132 +// default: // none
  133 +// break
  134 +// }
135 } 135 }
136 136
137 func checkPermission(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { 137 func checkPermission(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
@@ -159,6 +159,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -159,6 +159,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
159 } 159 }
160 160
161 func start(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { 161 func start(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  162 + if (device != nil) {
  163 + result(FlutterError(code: "MobileScanner",
  164 + message: "Called start() while already started!",
  165 + details: nil))
  166 + return
  167 + }
  168 +
162 textureId = registry.register(self) 169 textureId = registry.register(self)
163 captureSession = AVCaptureSession() 170 captureSession = AVCaptureSession()
164 171
@@ -178,6 +185,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -178,6 +185,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
178 device = AVCaptureDevice.devices(for: .video).filter({$0.position == position}).first 185 device = AVCaptureDevice.devices(for: .video).filter({$0.position == position}).first
179 } 186 }
180 187
  188 + if (device == nil) {
  189 + result(FlutterError(code: "MobileScanner",
  190 + message: "No camera found or failed to open camera!",
  191 + details: nil))
  192 + return
  193 + }
  194 +
181 // Enable the torch if parameter is set and torch is available 195 // Enable the torch if parameter is set and torch is available
182 if (device.hasTorch) { 196 if (device.hasTorch) {
183 do { 197 do {
@@ -222,7 +236,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -222,7 +236,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
222 result(answer) 236 result(answer)
223 } 237 }
224 238
225 - func switchTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { 239 + func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  240 + if (device == nil) {
  241 + result(FlutterError(code: "MobileScanner",
  242 + message: "Called toggleTorch() while stopped!",
  243 + details: nil))
  244 + return
  245 + }
226 do { 246 do {
227 try device.lockForConfiguration() 247 try device.lockForConfiguration()
228 device.torchMode = call.arguments as! Int == 1 ? .on : .off 248 device.torchMode = call.arguments as! Int == 1 ? .on : .off
@@ -232,13 +252,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -232,13 +252,19 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
232 result(FlutterError(code: error.localizedDescription, message: nil, details: nil)) 252 result(FlutterError(code: error.localizedDescription, message: nil, details: nil))
233 } 253 }
234 } 254 }
235 -  
236 - func switchAnalyzeMode(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {  
237 - analyzeMode = call.arguments as! Int  
238 - result(nil)  
239 - }  
240 - 255 +
  256 +// func switchAnalyzeMode(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
  257 +// analyzeMode = call.arguments as! Int
  258 +// result(nil)
  259 +// }
  260 +
241 func stop(_ result: FlutterResult) { 261 func stop(_ result: FlutterResult) {
  262 + if (device == nil) {
  263 + result(FlutterError(code: "MobileScanner",
  264 + message: "Called stop() while already stopped!",
  265 + details: nil))
  266 + return
  267 + }
242 captureSession.stopRunning() 268 captureSession.stopRunning()
243 for input in captureSession.inputs { 269 for input in captureSession.inputs {
244 captureSession.removeInput(input) 270 captureSession.removeInput(input)
@@ -249,7 +275,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, @@ -249,7 +275,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler,
249 device.removeObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode)) 275 device.removeObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode))
250 registry.unregisterTexture(textureId) 276 registry.unregisterTexture(textureId)
251 277
252 - analyzeMode = 0 278 +// analyzeMode = 0
253 latestBuffer = nil 279 latestBuffer = nil
254 captureSession = nil 280 captureSession = nil
255 device = nil 281 device = nil