iOS - Catch NSExceptions and repackage as FlutterErrors #64
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
Currently, if the iOS license is invalid/expires, the app crashes with:
Instead of crashing the app, the Flutter SDK should throw an exception, so that it can be caught and handled by the app.
Cause
This is caused by the license key not being validated before launching the scanner:
Unfortunately, the iOS SDK method
[MBMicroblinkSDK setLicenseKey:andLicensee:errorCallback:];
does not return a value, nor does it have a success callback - it only has anerrorCallback
, and even then the Flutter plugin just has an empty callback body, so this isn't being handled 🥹.Solution
The solution I've implemented is not 100% ideal, but it does deal with the problem in the short term without requiring more in-depth changes to either the Flutter SDK or iOS SDK...
I just catch all exceptions and repackage them as
FlutterErrors
. In practice this means I'm not actually getting the error callback when setting the license - I'm catching the exception that gets thrown when launching the scanner with an invalid license.Better solutions
There are definitely some better potential solutions but these would require more work and/or potentially changes to the underlying iOS SDK:
Improve
[MBMicroblinkSDK setLicenseKey:andLicensee:errorCallback:]
It seems currently we have no API to tell if the license is valid, only if it's invalid.
Assuming that this method needs to remain async, rename
errorCallback
tocallback
, and make it so that theMBLicenseError
isNULL
if the license was validated successfully.This way you could make it so:
(a) If the license is valid, call
[BlinkIDFlutterPlugin scanWith:overlaySettingsDict:]
(so we don't have to rely on it throwing anInvalidLicenseKeyException
.(b) If the license is invalid, don't try and launch the scanner and instead, repackage the
MBLicenseError
into aFlutterError
and send it as the result.Separate setting the license and launching the scanner
The BlinkID iOS SDK documentation says:
However, in the Flutter SDK we are only allowed to set the license key immediately before launching the scanner (see above).
The Flutter SDK could be refactored to expose a separate method in the
MethodChannel
specifically for setting the license. This way we could set the license (and validate it) before we launch the scanner.For example, we might want to hide the option to use the scanner if the license is expired/invalid (for which we also need a way to check the license validity, as above). We also want to avoid what is I guess currently a potential race condition where the scanner could be launched (and fail) before the license validation (async) has completed (but you may already have mitigations for this!)
Anyway, thanks for all the great work 💪 - hope this is helpful!