From 51f43844d782e40d0dc9d374553a2f9660de91d8 Mon Sep 17 00:00:00 2001 From: Benjamin Sauer Date: Fri, 5 Jan 2018 17:21:25 +0100 Subject: [PATCH 1/5] Added error handling for declined permission requests. --- .../barcodescan/BarcodeScanPlugin.kt | 4 ++ .../barcodescan/BarcodeScannerActivity.kt | 47 +++++++++---------- example/lib/main.dart | 19 +++++++- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScanPlugin.kt b/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScanPlugin.kt index 18d4b10..bdb5adf 100644 --- a/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScanPlugin.kt +++ b/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScanPlugin.kt @@ -41,7 +41,11 @@ class BarcodeScanPlugin(val activity: Activity): MethodCallHandler, if (resultCode == Activity.RESULT_OK) { val barcode = data?.getStringExtra("SCAN_RESULT") barcode?.let { this.result?.success(barcode) } + } else { + val errorCode = data?.getStringExtra("ERROR_CODE") + this.result?.error(errorCode, null, null) } + return true } return false } diff --git a/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScannerActivity.kt b/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScannerActivity.kt index 189623e..5113947 100644 --- a/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScannerActivity.kt +++ b/android/src/main/kotlin/com/apptreesoftware/barcodescan/BarcodeScannerActivity.kt @@ -26,7 +26,6 @@ import android.app.Activity import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle -import android.support.design.widget.Snackbar import android.support.v4.app.ActivityCompat import android.support.v4.content.ContextCompat import android.view.Menu @@ -38,32 +37,29 @@ import me.dm7.barcodescanner.zxing.ZXingScannerView class BarcodeScannerActivity : Activity(), ZXingScannerView.ResultHandler { lateinit var scannerView: me.dm7.barcodescanner.zxing.ZXingScannerView - //lateinit var pressLightSnackBar: Snackbar companion object { val REQUEST_TAKE_PHOTO_CAMERA_PERMISSION = 100 val TOGGLE_FLASH = 200 } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) title = "" scannerView = ZXingScannerView(this) scannerView.setAutoFocus(true) setContentView(scannerView) -// pressLightSnackBar = Snackbar.make(scannerView, "Press Screen To Turn Light On", -// Int.MAX_VALUE) -// pressLightSnackBar.show() } override fun onCreateOptionsMenu(menu: Menu): Boolean { if (scannerView.flash) { val item = menu.add(0, - TOGGLE_FLASH, 0, "Flash Off") + TOGGLE_FLASH, 0, "Flash Off") item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) } else { val item = menu.add(0, - TOGGLE_FLASH, 0, "Flash On") + TOGGLE_FLASH, 0, "Flash On") item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS) } return super.onCreateOptionsMenu(menu) @@ -81,6 +77,7 @@ class BarcodeScannerActivity : Activity(), ZXingScannerView.ResultHandler { override fun onResume() { super.onResume() scannerView.setResultHandler(this) + // start camera immediately if permission is already given if (!requestCameraAccessIfNecessary()) { scannerView.startCamera() } @@ -98,38 +95,38 @@ class BarcodeScannerActivity : Activity(), ZXingScannerView.ResultHandler { finish() } + fun finishWithError(errorCode: String) { + val intent = Intent() + intent.putExtra("ERROR_CODE", errorCode) + setResult(Activity.RESULT_CANCELED, intent) + finish() + } + private fun requestCameraAccessIfNecessary(): Boolean { val array = arrayOf(Manifest.permission.CAMERA) if (ContextCompat - .checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) { - val snackbar = Snackbar.make(scannerView, "Grant access to the camera to enable barcode scanning.", Snackbar.LENGTH_INDEFINITE) - snackbar.setAction("OK") { - ActivityCompat.requestPermissions(this, - array, - REQUEST_TAKE_PHOTO_CAMERA_PERMISSION) - } - snackbar.show() - } else { - ActivityCompat.requestPermissions(this, - array, - REQUEST_TAKE_PHOTO_CAMERA_PERMISSION) - } + .checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { + + ActivityCompat.requestPermissions(this, array, + REQUEST_TAKE_PHOTO_CAMERA_PERMISSION) return true } return false } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, - grantResults: IntArray) { + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array,grantResults: IntArray) { when (requestCode) { REQUEST_TAKE_PHOTO_CAMERA_PERMISSION -> { if (PermissionUtil.verifyPermissions(grantResults)) { scannerView.startCamera() + } else { + finishWithError("PERMISSION_NOT_GRANTED") } } + else -> { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + } } - super.onRequestPermissionsResult(requestCode, permissions, grantResults) } } @@ -155,4 +152,4 @@ object PermissionUtil { } return true } -} \ No newline at end of file +} diff --git a/example/lib/main.dart b/example/lib/main.dart index be8c8c6..d91f89b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:barcode_scan/barcode_scan.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; void main() { runApp(new MyApp()); @@ -43,7 +44,21 @@ class _MyAppState extends State { } Future scan() async { - String barcode = await BarcodeScanner.scan(); - setState(() => this.barcode = barcode); + try { + String barcode = await BarcodeScanner.scan(); + setState(() => this.barcode = barcode); + } on PlatformException catch (e) { + if (e.code == 'PERMISSION_NOT_GRANTED') { + setState(() { + this.barcode = 'The user did not grant the camera permission!'; + }); + } else { + setState(() => this.barcode = 'Unknown error: $e'); + } + } on FormatException{ + setState(() => this.barcode = 'null (User returned using the "back"-button before scanning anything. Result)'); + } catch (e) { + setState(() => this.barcode = 'Unknown error: $e'); + } } } From 2156fe33fe9a00baad2929a66a865f0e7bcf8048 Mon Sep 17 00:00:00 2001 From: Benjamin Sauer Date: Mon, 8 Jan 2018 14:41:49 +0100 Subject: [PATCH 2/5] replaced iOs popup by throwing a flutter error --- ios/Classes/BarcodeScanPlugin.m | 6 +++++- ios/Classes/BarcodeScannerViewController.m | 15 +++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/ios/Classes/BarcodeScanPlugin.m b/ios/Classes/BarcodeScanPlugin.m index 97ff856..40ad5ac 100644 --- a/ios/Classes/BarcodeScanPlugin.m +++ b/ios/Classes/BarcodeScanPlugin.m @@ -27,7 +27,11 @@ } - (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithResult:(NSString *)result { - if (self.result) { + if (self.result && [result isEqualToString: @"PERMISSION_NOT_GRANTED"]){ + self.result([FlutterError errorWithCode:@"PERMISSION_NOT_GRANTED" + message:nil + details:nil]); + } else if (self.result) { self.result(result); } } diff --git a/ios/Classes/BarcodeScannerViewController.m b/ios/Classes/BarcodeScannerViewController.m index 6dbdc4e..114db43 100644 --- a/ios/Classes/BarcodeScannerViewController.m +++ b/ios/Classes/BarcodeScannerViewController.m @@ -38,7 +38,8 @@ if (success) { [self startScan]; } else { - [self showNoCameraAccessAlert]; + [self.delegate barcodeScannerViewController:self didScanBarcodeWithResult:@"PERMISSION_NOT_GRANTED"]; + [self dismissViewControllerAnimated:NO completion:nil]; } }]; } @@ -81,16 +82,6 @@ } } -- (void)showNoCameraAccessAlert { - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Camera access denied" - message:@"Camera access has been disabled for this application. To turn camera access back on, please go to the iOS settings application." - preferredStyle:UIAlertControllerStyleAlert]; - [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { - [self dismissViewControllerAnimated:YES completion:nil]; - }]]; - [self presentViewController:alertController animated:YES completion:nil]; -} - - (void)toggle { [self toggleFlash:!self.isFlashOn]; [self updateFlashButton]; @@ -132,4 +123,4 @@ } -@end \ No newline at end of file +@end From 616b286a5c0a049dc23abc7183a9a3190e9c19f3 Mon Sep 17 00:00:00 2001 From: Benjamin Sauer Date: Wed, 10 Jan 2018 14:55:58 +0100 Subject: [PATCH 3/5] main, example: added CameraAccessDenied constant --- example/lib/main.dart | 2 +- lib/barcode_scan.dart | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index d91f89b..34a643d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -48,7 +48,7 @@ class _MyAppState extends State { String barcode = await BarcodeScanner.scan(); setState(() => this.barcode = barcode); } on PlatformException catch (e) { - if (e.code == 'PERMISSION_NOT_GRANTED') { + if (e.code == BarcodeScanner.CameraAccessDenied) { setState(() { this.barcode = 'The user did not grant the camera permission!'; }); diff --git a/lib/barcode_scan.dart b/lib/barcode_scan.dart index f375363..d042a3d 100644 --- a/lib/barcode_scan.dart +++ b/lib/barcode_scan.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter/services.dart'; class BarcodeScanner { + static const CameraAccessDenied = 'PERMISSION_NOT_GRANTED'; static const MethodChannel _channel = const MethodChannel('com.apptreesoftware.barcode_scan'); static Future scan() async => await _channel.invokeMethod('scan'); From 1c34da8db99e96880382827d2dedb32b979d4e0e Mon Sep 17 00:00:00 2001 From: Benjamin Sauer Date: Wed, 10 Jan 2018 16:20:43 +0100 Subject: [PATCH 4/5] BarcodeScanPlugin.m: extracted errorHandling into seperate method --- ios/Classes/BarcodeScanPlugin.m | 14 +++++++++----- ios/Classes/BarcodeScannerViewController.m | 2 +- ios/Classes/BarcodeScannerViewControllerDelegate.h | 3 ++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ios/Classes/BarcodeScanPlugin.m b/ios/Classes/BarcodeScanPlugin.m index 40ad5ac..0786757 100644 --- a/ios/Classes/BarcodeScanPlugin.m +++ b/ios/Classes/BarcodeScanPlugin.m @@ -27,13 +27,17 @@ } - (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithResult:(NSString *)result { - if (self.result && [result isEqualToString: @"PERMISSION_NOT_GRANTED"]){ - self.result([FlutterError errorWithCode:@"PERMISSION_NOT_GRANTED" - message:nil - details:nil]); - } else if (self.result) { + if (self.result) { self.result(result); } } +- (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithErrorCode:(NSString *)errorCode { + if (self.result){ + self.result([FlutterError errorWithCode:errorCode + message:nil + details:nil]); + } +} + @end diff --git a/ios/Classes/BarcodeScannerViewController.m b/ios/Classes/BarcodeScannerViewController.m index 114db43..0835aaf 100644 --- a/ios/Classes/BarcodeScannerViewController.m +++ b/ios/Classes/BarcodeScannerViewController.m @@ -38,7 +38,7 @@ if (success) { [self startScan]; } else { - [self.delegate barcodeScannerViewController:self didScanBarcodeWithResult:@"PERMISSION_NOT_GRANTED"]; + [self.delegate barcodeScannerViewController:self didScanBarcodeWithErrorCode:@"PERMISSION_NOT_GRANTED"]; [self dismissViewControllerAnimated:NO completion:nil]; } }]; diff --git a/ios/Classes/BarcodeScannerViewControllerDelegate.h b/ios/Classes/BarcodeScannerViewControllerDelegate.h index b5c0663..1412686 100644 --- a/ios/Classes/BarcodeScannerViewControllerDelegate.h +++ b/ios/Classes/BarcodeScannerViewControllerDelegate.h @@ -9,5 +9,6 @@ @protocol BarcodeScannerViewControllerDelegate - (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithResult:(NSString *)result; +- (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithErrorCode:(NSString *)errorCode; -@end \ No newline at end of file +@end From 65193acf1cb5331652f9d8af05f84fc12ad70658 Mon Sep 17 00:00:00 2001 From: Benjamin Sauer Date: Wed, 10 Jan 2018 16:25:40 +0100 Subject: [PATCH 5/5] changed delegate method name to 'didFailWithErrorCode' --- ios/Classes/BarcodeScanPlugin.m | 2 +- ios/Classes/BarcodeScannerViewController.m | 2 +- ios/Classes/BarcodeScannerViewControllerDelegate.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/Classes/BarcodeScanPlugin.m b/ios/Classes/BarcodeScanPlugin.m index 0786757..012593c 100644 --- a/ios/Classes/BarcodeScanPlugin.m +++ b/ios/Classes/BarcodeScanPlugin.m @@ -32,7 +32,7 @@ } } -- (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithErrorCode:(NSString *)errorCode { +- (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didFailWithErrorCode:(NSString *)errorCode { if (self.result){ self.result([FlutterError errorWithCode:errorCode message:nil diff --git a/ios/Classes/BarcodeScannerViewController.m b/ios/Classes/BarcodeScannerViewController.m index 0835aaf..3ca4745 100644 --- a/ios/Classes/BarcodeScannerViewController.m +++ b/ios/Classes/BarcodeScannerViewController.m @@ -38,7 +38,7 @@ if (success) { [self startScan]; } else { - [self.delegate barcodeScannerViewController:self didScanBarcodeWithErrorCode:@"PERMISSION_NOT_GRANTED"]; + [self.delegate barcodeScannerViewController:self didFailWithErrorCode:@"PERMISSION_NOT_GRANTED"]; [self dismissViewControllerAnimated:NO completion:nil]; } }]; diff --git a/ios/Classes/BarcodeScannerViewControllerDelegate.h b/ios/Classes/BarcodeScannerViewControllerDelegate.h index 1412686..10290a3 100644 --- a/ios/Classes/BarcodeScannerViewControllerDelegate.h +++ b/ios/Classes/BarcodeScannerViewControllerDelegate.h @@ -9,6 +9,6 @@ @protocol BarcodeScannerViewControllerDelegate - (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithResult:(NSString *)result; -- (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didScanBarcodeWithErrorCode:(NSString *)errorCode; +- (void)barcodeScannerViewController:(BarcodeScannerViewController *)controller didFailWithErrorCode:(NSString *)errorCode; @end