Quellcode durchsuchen

Added future to functions. Changed min SDK to 2.6.0.

flutter-beta
Julian Steenbakker vor 5 Jahren
Ursprung
Commit
d1ed205249
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden GPG-Schlüssel-ID: 16E437C7A3D94250
13 geänderte Dateien mit 615 neuen und 250 gelöschten Zeilen
  1. +1
    -1
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt
  2. +150
    -59
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt
  3. +0
    -1
      android/src/main/kotlin/net/touchcapture/qr/flutterqr/Shared.kt
  4. +27
    -50
      example/lib/main.dart
  5. +110
    -10
      ios/Classes/QRView.swift
  6. +3
    -0
      lib/qr_code_scanner.dart
  7. +152
    -128
      lib/src/qr_code_scanner.dart
  8. +16
    -0
      lib/src/types/barcode.dart
  9. +121
    -0
      lib/src/types/barcode_format.dart
  10. +7
    -0
      lib/src/types/camera.dart
  11. +14
    -0
      lib/src/types/camera_exception.dart
  12. +13
    -0
      lib/src/types/features.dart
  13. +1
    -1
      pubspec.yaml

+ 1
- 1
android/src/main/kotlin/net/touchcapture/qr/flutterqr/FlutterQrPlugin.kt Datei anzeigen

@@ -7,6 +7,7 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.platform.PlatformViewRegistry

@@ -63,7 +64,6 @@ class FlutterQrPlugin : FlutterPlugin, ActivityAware {
inner class CameraRequestPermissionsListener : PluginRegistry.RequestPermissionsResultListener {
override fun onRequestPermissionsResult(id: Int, permissions: Array<String>, grantResults: IntArray): Boolean {
if (id == Shared.CAMERA_REQUEST_ID && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Shared.cameraPermissionContinuation?.run()
return true
}
return false


+ 150
- 59
android/src/main/kotlin/net/touchcapture/qr/flutterqr/QRView.kt Datei anzeigen

@@ -10,6 +10,7 @@ import android.view.View
import com.google.zxing.ResultPoint
import android.hardware.Camera.CameraInfo
import android.os.Build
import com.google.zxing.BarcodeFormat
import com.journeyapps.barcodescanner.BarcodeCallback
import com.journeyapps.barcodescanner.BarcodeResult
import com.journeyapps.barcodescanner.BarcodeView
@@ -22,8 +23,22 @@ class QRView(messenger: BinaryMessenger, id: Int, private val context: Context,

private var isTorchOn: Boolean = false
private var barcodeView: BarcodeView? = null
private var requestingPermission = false
private val channel: MethodChannel
var allowedBarcodeTypes = mutableListOf<BarcodeFormat>()

private val qrCodeTypes = mapOf(
0 to BarcodeFormat.AZTEC,
1 to BarcodeFormat.CODE_128,
2 to BarcodeFormat.CODE_39,
3 to BarcodeFormat.CODE_93,
4 to BarcodeFormat.DATA_MATRIX,
5 to BarcodeFormat.EAN_13,
6 to BarcodeFormat.EAN_8,
7 to BarcodeFormat.ITF,
8 to BarcodeFormat.PDF_417,
9 to BarcodeFormat.QR_CODE,
10 to BarcodeFormat.UPC_E
)

init {
checkAndRequestPermission(null)
@@ -65,68 +80,121 @@ class QRView(messenger: BinaryMessenger, id: Int, private val context: Context,
}

override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
when(call.method){
"startScan" -> {
startScan()
}
"stopScan" -> {
stopScan()
}
"flipCamera" -> {
flipCamera()
}
"toggleFlash" -> {
toggleFlash()
}
"pauseCamera" -> {
pauseCamera()
}
"resumeCamera" -> {
resumeCamera()
}
when(call.method) {
"startScan" -> startScan()
"stopScan" -> stopScan()
"flipCamera" -> flipCamera(result)
"toggleFlash" -> toggleFlash(result)
"pauseCamera" -> pauseCamera(result)
"resumeCamera" -> resumeCamera(result)
"requestPermissions" -> checkAndRequestPermission(result)
"getCameraInfo" -> getCameraInfo(result)
"getFlashInfo" -> getFlashInfo(result)
// "showNativeAlertDialog" -> showNativeAlertDialog(result)
"getSystemFeatures" -> getSystemFeatures(result)
"setAllowedBarcodeFormats" -> setBarcodeFormats(call.arguments as List<Int>, result)
else -> result.notImplemented()
}
}

private fun flipCamera() {
barcodeView?.pause()
val settings = barcodeView?.cameraSettings
private fun getCameraInfo(result: MethodChannel.Result) {
if (barcodeView == null) {
return barCodeViewNotSet(result)
}
result.success(barcodeView!!.cameraSettings.requestedCameraId)
}

private fun flipCamera(result: MethodChannel.Result) {
if (barcodeView == null) {
return barCodeViewNotSet(result)
}
barcodeView!!.pause()
val settings = barcodeView!!.cameraSettings

if(settings?.requestedCameraId == CameraInfo.CAMERA_FACING_FRONT)
if(settings.requestedCameraId == CameraInfo.CAMERA_FACING_FRONT)
settings.requestedCameraId = CameraInfo.CAMERA_FACING_BACK
else
settings?.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT
settings.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT

barcodeView?.cameraSettings = settings
barcodeView?.resume()
barcodeView!!.cameraSettings = settings
barcodeView!!.resume()
result.success(settings.requestedCameraId)
}

private fun toggleFlash() {
private fun getFlashInfo(result: MethodChannel.Result) {
if (barcodeView == null) {
return barCodeViewNotSet(result)
}
result.success(isTorchOn)
}

private fun toggleFlash(result: MethodChannel.Result) {
if (barcodeView == null) {
return barCodeViewNotSet(result)
}

if (hasFlash()) {
barcodeView?.setTorch(!isTorchOn)
barcodeView!!.setTorch(!isTorchOn)
isTorchOn = !isTorchOn
result.success(isTorchOn)
} else {
result.error("404", "This device doesn't support flash", null)
}

}

private fun pauseCamera() {
private fun pauseCamera(result: MethodChannel.Result) {
if (barcodeView == null) {
return barCodeViewNotSet(result)
}
if (barcodeView!!.isPreviewActive) {
barcodeView?.pause()
barcodeView!!.pause()
}
result.success(true)
}

private fun resumeCamera() {
private fun resumeCamera(result: MethodChannel.Result) {
if (barcodeView == null) {
return barCodeViewNotSet(result)
}
if (!barcodeView!!.isPreviewActive) {
barcodeView?.resume()
barcodeView!!.resume()
}
result.success(true)
}

private fun hasFlash(): Boolean {
return context.packageManager
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
return hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
}

private fun hasBackCamera(): Boolean {
return hasSystemFeature(PackageManager.FEATURE_CAMERA)
}

private fun hasFrontCamera(): Boolean {
return hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)
}

private fun hasSystemFeature(feature: String): Boolean {
return Shared.activity!!.packageManager
.hasSystemFeature(feature)
}

private fun barCodeViewNotSet(result: MethodChannel.Result) {
result.error("404", "No barcode view found", null)
}

override fun getView(): View {
return initBarCodeView()?.apply {
if (!hasBackCamera()) {
if (!hasFrontCamera()) {
// No camera available!
} else {
this.cameraSettings.requestedCameraId = CameraInfo.CAMERA_FACING_FRONT
}
} else {
this.cameraSettings.requestedCameraId = CameraInfo.CAMERA_FACING_BACK
}
resume()
}!!
}
@@ -145,11 +213,14 @@ class QRView(messenger: BinaryMessenger, id: Int, private val context: Context,
barcodeView?.decodeContinuous(
object : BarcodeCallback {
override fun barcodeResult(result: BarcodeResult) {
val code = mapOf(
"code" to result.text,
"type" to result.barcodeFormat.name,
"rawBytes" to result.rawBytes)
channel.invokeMethod("onRecognizeQR", code)
if (allowedBarcodeTypes.size == 0 || allowedBarcodeTypes.contains(result.barcodeFormat)) {
val code = mapOf(
"code" to result.text,
"type" to result.barcodeFormat.name,
"rawBytes" to result.rawBytes)
channel.invokeMethod("onRecognizeQR", code)
}

}

override fun possibleResultPoints(resultPoints: List<ResultPoint>) {}
@@ -161,35 +232,55 @@ class QRView(messenger: BinaryMessenger, id: Int, private val context: Context,
barcodeView?.stopDecoding()
}

private fun getSystemFeatures(result: MethodChannel.Result) {
try {
result.success(mapOf("hasFrontCamera" to hasFrontCamera(),
"hasBackCamera" to hasBackCamera(), "hasFlash" to hasFlash(),
"activeCamera" to barcodeView?.cameraSettings?.requestedCameraId))
} catch (e: Exception) {
result.error(null, null, null)
}
}

private fun setBarcodeFormats(arguments: List<Int>, result: MethodChannel.Result) {
try {
allowedBarcodeTypes.clear()
arguments.forEach {
allowedBarcodeTypes.add(qrCodeTypes[it]!!)
}
result.success(true)
} catch (e: java.lang.Exception) {
result.error(null, null, null)
}
}

// private fun showNativeAlertDialog(result: MethodChannel.Result) {
// AlertDialog.Builder(context)
// .setTitle("Scanning Unavailable")
// .setMessage("This app does not have permission to access the camera")
// .setPositiveButton(R.string.ok, null)
// .setCancelable(false)
// .setIcon(R.drawable.ic_dialog_alert)
// .show()
// result.success(true)
// }

private fun hasCameraPermission(): Boolean {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
Shared.activity?.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
}

private fun checkAndRequestPermission(result: MethodChannel.Result?) {
if (Shared.cameraPermissionContinuation != null) {
result?.error("cameraPermission", "Camera permission request ongoing", null)
}

Shared.cameraPermissionContinuation = Runnable {
Shared.cameraPermissionContinuation = null
if (!hasCameraPermission()) {
result?.error(
"cameraPermission", "MediaRecorderCamera permission not granted", null)
return@Runnable
}
}

requestingPermission = false
if (hasCameraPermission()) {
Shared.cameraPermissionContinuation?.run()
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestingPermission = true
when {
hasCameraPermission() -> result?.success(true)
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
Shared.activity?.requestPermissions(
arrayOf(Manifest.permission.CAMERA),
Shared.CAMERA_REQUEST_ID)
}
else -> {
result?.error("cameraPermission", "Platform Version to low for camera permission check", null)
}
}
}
}


+ 0
- 1
android/src/main/kotlin/net/touchcapture/qr/flutterqr/Shared.kt Datei anzeigen

@@ -5,5 +5,4 @@ import android.app.Activity
object Shared {
const val CAMERA_REQUEST_ID = 513469796
var activity: Activity? = null
var cameraPermissionContinuation: Runnable? = null
}

+ 27
- 50
example/lib/main.dart Datei anzeigen

@@ -6,11 +6,6 @@ import 'package:qr_code_scanner/qr_code_scanner.dart';

void main() => runApp(MaterialApp(home: QRViewExample()));

const flashOn = 'FLASH ON';
const flashOff = 'FLASH OFF';
const frontCamera = 'FRONT CAMERA';
const backCamera = 'BACK CAMERA';

class QRViewExample extends StatefulWidget {
const QRViewExample({
Key key,
@@ -21,9 +16,8 @@ class QRViewExample extends StatefulWidget {
}

class _QRViewExampleState extends State<QRViewExample> {

Barcode result;
var flashState = flashOn;
var cameraState = frontCamera;
QRViewController controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');

@@ -64,44 +58,33 @@ class _QRViewExampleState extends State<QRViewExample> {
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
if (controller != null) {
controller.toggleFlash();
if (_isFlashOn(flashState)) {
setState(() {
flashState = flashOff;
});
} else {
setState(() {
flashState = flashOn;
});
}
}
},
child:
Text(flashState, style: TextStyle(fontSize: 20)),
),
onPressed: () => setState(() {
controller?.toggleFlash();
}),
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
return Text('Flash: ${snapshot.data}');
},
)),
),
Container(
margin: EdgeInsets.all(8),
child: RaisedButton(
onPressed: () {
if (controller != null) {
controller.flipCamera();
if (_isBackCamera(cameraState)) {
setState(() {
cameraState = frontCamera;
});
} else {
setState(() {
cameraState = backCamera;
});
}
}
},
child:
Text(cameraState, style: TextStyle(fontSize: 20)),
),
onPressed: () => setState(() {
controller?.flipCamera();
}),
child: FutureBuilder(
future: controller?.getCameraInfo(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return Text(
'Camera facing ${describeEnum(snapshot.data)}');
} else {
return Text('loading');
}
},
)),
)
],
),
@@ -138,14 +121,6 @@ class _QRViewExampleState extends State<QRViewExample> {
);
}

bool _isFlashOn(String current) {
return flashOn == current;
}

bool _isBackCamera(String current) {
return backCamera == current;
}

Widget _buildQrView(BuildContext context) {
// For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
var scanArea = (MediaQuery.of(context).size.width < 400 ||
@@ -169,7 +144,9 @@ class _QRViewExampleState extends State<QRViewExample> {
}

void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;


+ 110
- 10
ios/Classes/QRView.swift Datei anzeigen

@@ -15,6 +15,22 @@ public class QRView:NSObject,FlutterPlatformView {
var channel: FlutterMethodChannel
var cameraFacing: MTBCamera
var allowedBarcodeTypes: Array<AVMetadataObject.ObjectType> = []
var QRCodeTypes = [
0: AVMetadataObject.ObjectType.aztec,
1: AVMetadataObject.ObjectType.code128,
2: AVMetadataObject.ObjectType.code39,
3: AVMetadataObject.ObjectType.code93,
4: AVMetadataObject.ObjectType.dataMatrix,
5: AVMetadataObject.ObjectType.ean13,
6: AVMetadataObject.ObjectType.ean8,
7: AVMetadataObject.ObjectType.interleaved2of5,
8: AVMetadataObject.ObjectType.pdf417,
9: AVMetadataObject.ObjectType.qr,
10: AVMetadataObject.ObjectType.upce
]
public init(withFrame frame: CGRect, withRegistrar registrar: FlutterPluginRegistrar, withId id: Int64, params: Dictionary<String, Any>){
self.registrar = registrar
previewView = UIView(frame: frame)
@@ -36,13 +52,23 @@ public class QRView:NSObject,FlutterPlatformView {
case "startScan":
self?.startScan(result)
case "flipCamera":
self?.flipCamera()
self?.flipCamera(result)
case "toggleFlash":
self?.toggleFlash()
self?.toggleFlash(result)
case "pauseCamera":
self?.pauseCamera()
self?.pauseCamera(result)
case "resumeCamera":
self?.resumeCamera()
self?.resumeCamera(result)
case "getCameraInfo":
self?.getCameraInfo(result)
case "getFlashInfo":
self?.getFlashInfo(result)
case "showNativeAlertDialog":
self?.showNativeAlertDialog(result)
case "getSystemFeatures":
self?.getSystemFeatures(result)
case "setAllowedBarcodeFormats":
self?.setBarcodeFormats(call.arguments as! Array<Int>, result)
default:
result(FlutterMethodNotImplemented)
return
@@ -108,7 +134,10 @@ public class QRView:NSObject,FlutterPlatformView {
}
guard let stringValue = code.stringValue else { continue }
let result = ["code": stringValue, "type": typeString]
self?.channel.invokeMethod("onRecognizeQR", arguments: result)
if self!.allowedBarcodeTypes.count == 0 || self!.allowedBarcodeTypes.contains(code.type) {
self?.channel.invokeMethod("onRecognizeQR", arguments: result)
}
}
}
})
@@ -131,35 +160,106 @@ public class QRView:NSObject,FlutterPlatformView {
}
}
func flipCamera(){
func getCameraInfo(_ result: @escaping FlutterResult) -> Void {
if let sc: MTBBarcodeScanner = scanner {
result(sc.camera.rawValue)
} else {
let error = FlutterError(code: "cameraInformationError", message: "Could not get camera information", details: nil)
result(error)
}
}
func flipCamera(_ result: @escaping FlutterResult){
if let sc: MTBBarcodeScanner = scanner {
if sc.hasOppositeCamera() {
sc.flipCamera()
}
return result(sc.camera.rawValue)
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}
func toggleFlash(){
func getFlashInfo(_ result: @escaping FlutterResult) -> Void {
if let sc: MTBBarcodeScanner = scanner {
result(sc.torchMode.rawValue != 0)
} else {
let error = FlutterError(code: "cameraInformationError", message: "Could not get flash information", details: nil)
result(error)
}
}
func toggleFlash(_ result: @escaping FlutterResult){
if let sc: MTBBarcodeScanner = scanner {
if sc.hasTorch() {
sc.toggleTorch()
return result(sc.torchMode == MTBTorchMode(rawValue: 1))
}
return result(FlutterError(code: "404", message: "This device doesn\'t support flash", details: nil))
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}
func pauseCamera() {
func pauseCamera(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = scanner {
if sc.isScanning() {
sc.freezeCapture()
}
return result(true)
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}
func resumeCamera() {
func resumeCamera(_ result: @escaping FlutterResult) {
if let sc: MTBBarcodeScanner = scanner {
if !sc.isScanning() {
sc.unfreezeCapture()
}
return result(true)
}
return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
}
func showNativeAlertDialog(_ result: @escaping FlutterResult) -> Void {
UIAlertView(title: "Scanning Unavailable", message: "This app does not have permission to access the camera", delegate: nil, cancelButtonTitle: nil, otherButtonTitles: "Ok").show()
return result(true)
}

func getSystemFeatures(_ result: @escaping FlutterResult) -> Void {
if let sc: MTBBarcodeScanner = scanner {
var hasBackCameraVar = false
var hasFrontCameraVar = false
let camera = sc.camera

if(camera == MTBCamera(rawValue: 0)){
hasBackCameraVar = true
if sc.hasOppositeCamera() {
hasFrontCameraVar = true
}
}else{
hasFrontCameraVar = true
if sc.hasOppositeCamera() {
hasBackCameraVar = true
}
}
return result([
"hasFrontCamera": hasFrontCameraVar,
"hasBackCamera": hasBackCameraVar,
"hasFlash": sc.hasTorch(),
"activeCamera": camera.rawValue
])
}
return result(FlutterError(code: "404", message: nil, details: nil))
}

func setBarcodeFormats(_ arguments: Array<Int>, _ result: @escaping FlutterResult){
do{
allowedBarcodeTypes.removeAll()
try arguments.forEach { arg in
allowedBarcodeTypes.append(try QRCodeTypes[arg]!)
}
result(true)
}catch{
result(FlutterError(code: "404", message: nil, details: nil))
}
}
}
}

+ 3
- 0
lib/qr_code_scanner.dart Datei anzeigen

@@ -1,2 +1,5 @@
export 'src/qr_code_scanner.dart';
export 'src/qr_scanner_overlay_shape.dart';
export 'src/types/barcode.dart';
export 'src/types/camera.dart';
export 'src/types/features.dart';

+ 152
- 128
lib/src/qr_code_scanner.dart Datei anzeigen

@@ -3,105 +3,16 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';

typedef QRViewCreatedCallback = void Function(QRViewController);

enum CameraFacing {
/// Shows back facing camera.
back,

/// Shows front facing camera.
front
}

enum BarcodeFormat {
/// Aztec 2D barcode format.
aztec,

/// CODABAR 1D format.
codabar,

/// Code 39 1D format.
code39,

/// Code 93 1D format.
code93,

/// Code 128 1D format.
code128,

/// Data Matrix 2D barcode format.
dataMatrix,

/// EAN-8 1D format.
ean8,

/// EAN-13 1D format.
ean13,

/// ITF (Interleaved Two of Five) 1D format.
itf,

/// MaxiCode 2D barcode format.
maxicode,

/// PDF417 format.
pdf417,

/// QR Code 2D barcode format.
qrcode,

/// RSS 14
rss14,

/// RSS EXPANDED
rssExpanded,

/// UPC-A 1D format.
upcA,

/// UPC-E 1D format.
upcE,

/// UPC/EAN extension format. Not a stand-alone format.
upcEanExtension
}

const _formatNames = <String, BarcodeFormat>{
'AZTEC': BarcodeFormat.aztec,
'CODABAR': BarcodeFormat.codabar,
'CODE_39': BarcodeFormat.code39,
'CODE_93': BarcodeFormat.code93,
'CODE_128': BarcodeFormat.code128,
'DATA_MATRIX': BarcodeFormat.dataMatrix,
'EAN_8': BarcodeFormat.ean8,
'EAN_13': BarcodeFormat.ean13,
'ITF': BarcodeFormat.itf,
'MAXICODE': BarcodeFormat.maxicode,
'PDF_417': BarcodeFormat.pdf417,
'QR_CODE': BarcodeFormat.qrcode,
'RSS_14': BarcodeFormat.rss14,
'RSS_EXPANDED': BarcodeFormat.rssExpanded,
'UPC_A': BarcodeFormat.upcA,
'UPC_E': BarcodeFormat.upcE,
'UPC_EAN_EXTENSION': BarcodeFormat.upcEanExtension,
};

/// The [Barcode] object holds information about the barcode or qr code.
///
/// [code] is the content of the barcode.
/// [format] displays which type the code is.
/// Only for Android, [rawBytes] gives a list of bytes of the result.
class Barcode {
Barcode(this.code, this.format, this.rawBytes);

final String code;
final BarcodeFormat format;
import 'qr_scanner_overlay_shape.dart';
import 'types/barcode.dart';
import 'types/barcode_format.dart';
import 'types/camera.dart';
import 'types/camera_exception.dart';
import 'types/features.dart';

/// Raw bytes are only supported by Android.
final List<int> rawBytes;
}
typedef QRViewCreatedCallback = void Function(QRViewController);
typedef PermissionSetCallback = void Function(QRViewController, bool);

/// The [QRView] is the view where the camera and the barcode scanner gets displayed.
class QRView extends StatefulWidget {
@@ -111,6 +22,8 @@ class QRView extends StatefulWidget {
this.overlay,
this.overlayMargin = EdgeInsets.zero,
this.cameraFacing = CameraFacing.back,
this.onPermissionSet,
this.showNativeAlertDialog = false,
}) : assert(key != null),
assert(onQRViewCreated != null),
super(key: key);
@@ -119,6 +32,8 @@ class QRView extends StatefulWidget {
final ShapeBorder overlay;
final EdgeInsetsGeometry overlayMargin;
final CameraFacing cameraFacing;
final PermissionSetCallback onPermissionSet;
final bool showNativeAlertDialog;

@override
State<StatefulWidget> createState() => _QRViewState();
@@ -201,7 +116,8 @@ class _QRViewState extends State<QRView> {
_channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id');

// Start scan after creation of the view
final controller = QRViewController._(_channel, widget.key, cutOutSize)
final controller = QRViewController._(_channel, widget.key, cutOutSize,
widget.onPermissionSet, widget.showNativeAlertDialog)
.._startScan(widget.key, cutOutSize);

// Initialize the controller for controlling the QRView
@@ -225,10 +141,70 @@ class _QrCameraSettings {
}
}

const _formatNames = <String, BarcodeFormat>{
'AZTEC': BarcodeFormat.aztec,
'CODABAR': BarcodeFormat.codabar,
'CODE_39': BarcodeFormat.code39,
'CODE_93': BarcodeFormat.code93,
'CODE_128': BarcodeFormat.code128,
'DATA_MATRIX': BarcodeFormat.dataMatrix,
'EAN_8': BarcodeFormat.ean8,
'EAN_13': BarcodeFormat.ean13,
'ITF': BarcodeFormat.itf,
'MAXICODE': BarcodeFormat.maxicode,
'PDF_417': BarcodeFormat.pdf417,
'QR_CODE': BarcodeFormat.qrcode,
'RSS_14': BarcodeFormat.rss14,
'RSS_EXPANDED': BarcodeFormat.rssExpanded,
'UPC_A': BarcodeFormat.upcA,
'UPC_E': BarcodeFormat.upcE,
'UPC_EAN_EXTENSION': BarcodeFormat.upcEanExtension,
};

class QRViewController {
QRViewController._(MethodChannel channel, GlobalKey qrKey, double scanArea)
: _channel = channel {
_channel.setMethodCallHandler(_onMethodCall);
QRViewController._(
MethodChannel channel,
GlobalKey qrKey,
double scanArea,
PermissionSetCallback onPermissionSet,
bool showNativeAlertDialogOnError,
) : _channel = channel {
_channel.setMethodCallHandler((call) async {
switch (call.method) {
case 'onRecognizeQR':
if (call.arguments != null) {
final args = call.arguments as Map;
final code = args['code'] as String;
final rawType = args['type'] as String;
// Raw bytes are only supported by Android.
final rawBytes = args['rawBytes'] as List<int>;
final format = _formatNames[rawType];
if (format != null) {
final barcode = Barcode(code, format, rawBytes);
_scanUpdateController.sink.add(barcode);
} else {
throw Exception('Unexpected barcode type $rawType');
}
}
break;
case 'onPermissionSet':
await getSystemFeatures(); // if we have no permission all features will not be avaible
if (call.arguments != null) {
if (call.arguments as bool) {
_hasPermissions = true;
} else {
_hasPermissions = false;
if (showNativeAlertDialogOnError) {
await showNativeAlertDialog();
}
}
if (onPermissionSet != null) {
onPermissionSet(this, call.arguments as bool);
}
}
break;
}
});
}

final MethodChannel _channel;
@@ -237,25 +213,11 @@ class QRViewController {

Stream<Barcode> get scannedDataStream => _scanUpdateController.stream;

Future<void> _onMethodCall(MethodCall call) async {
switch (call.method) {
case 'onRecognizeQR':
if (call.arguments != null) {
final args = call.arguments as Map;
final code = args['code'] as String;
final rawType = args['type'] as String;
// Raw bytes are only supported by Android.
final rawBytes = args['rawBytes'] as List<int>;
final format = _formatNames[rawType];
if (format != null) {
final barcode = Barcode(code, format, rawBytes);
_scanUpdateController.sink.add(barcode);
} else {
throw Exception('Unexpected barcode type $rawType');
}
}
}
}
SystemFeatures _features;
bool _hasPermissions;

SystemFeatures get systemFeatures => _features;
bool get hasPermissions => _hasPermissions;

/// Starts the barcode scanner
Future<void> _startScan(
@@ -267,24 +229,86 @@ class QRViewController {
return _channel.invokeMethod('startScan');
}

Future<CameraFacing> getCameraInfo() async {
try {
return CameraFacing
.values[await _channel.invokeMethod('getCameraInfo') as int];
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Flips the camera between available modes
void flipCamera() {
_channel.invokeMethod('flipCamera');
Future<CameraFacing> flipCamera() async {
try {
return CameraFacing
.values[await _channel.invokeMethod('flipCamera') as int];
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Get flashlight status
Future<bool> getFlashStatus() async {
try {
return await _channel.invokeMethod('getFlashInfo');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Toggles the flashlight between available modes
void toggleFlash() {
_channel.invokeMethod('toggleFlash');
Future<void> toggleFlash() async {
try {
await _channel.invokeMethod('toggleFlash') as bool;
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Pauses barcode scanning
void pauseCamera() {
_channel.invokeMethod('pauseCamera');
Future<void> pauseCamera() async {
try {
await _channel.invokeMethod('pauseCamera');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Resumes barcode scanning
void resumeCamera() {
_channel.invokeMethod('resumeCamera');
Future<void> resumeCamera() async {
try {
await _channel.invokeMethod('resumeCamera');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

Future<void> showNativeAlertDialog() async {
try {
await _channel.invokeMethod('showNativeAlertDialog');
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

Future<void> setAllowedBarcodeTypes(List<BarcodeFormat> list) async {
try {
await _channel.invokeMethod('setAllowedBarcodeFormats',
list?.map((e) => e.asInt())?.toList() ?? []);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

Future<SystemFeatures> getSystemFeatures() async {
try {
var features =
await _channel.invokeMapMethod<String, dynamic>('getSystemFeatures');
return SystemFeatures.fromJson(features);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}

/// Disposes the barcode stream.


+ 16
- 0
lib/src/types/barcode.dart Datei anzeigen

@@ -0,0 +1,16 @@
import 'barcode_format.dart';

/// The [Barcode] object holds information about the barcode or qr code.
///
/// [code] is the content of the barcode.
/// [format] displays which type the code is.
/// Only for Android, [rawBytes] gives a list of bytes of the result.
class Barcode {
Barcode(this.code, this.format, this.rawBytes);

final String code;
final BarcodeFormat format;

/// Raw bytes are only supported by Android.
final List<int> rawBytes;
}

+ 121
- 0
lib/src/types/barcode_format.dart Datei anzeigen

@@ -0,0 +1,121 @@
enum BarcodeFormat {
/// Aztec 2D barcode format.
aztec,

/// CODABAR 1D format.
codabar,

/// Code 39 1D format.
code39,

/// Code 93 1D format.
code93,

/// Code 128 1D format.
code128,

/// Data Matrix 2D barcode format.
dataMatrix,

/// EAN-8 1D format.
ean8,

/// EAN-13 1D format.
ean13,

/// ITF (Interleaved Two of Five) 1D format.
itf,

/// MaxiCode 2D barcode format.
maxicode,

/// PDF417 format.
pdf417,

/// QR Code 2D barcode format.
qrcode,

/// RSS 14
rss14,

/// RSS EXPANDED
rssExpanded,

/// UPC-A 1D format.
upcA,

/// UPC-E 1D format.
upcE,

/// UPC/EAN extension format. Not a stand-alone format.
upcEanExtension
}

extension BarcodeTypesExtension on BarcodeFormat {
int asInt() {
return index;
}

BarcodeFormat fromString(String format) {

}

String get formatName {
switch (this) {

case BarcodeFormat.aztec:
return 'AZTEC';
break;
case BarcodeFormat.codabar:
return 'CODABAR';
break;
case BarcodeFormat.code39:
return 'CODE_39';
break;
case BarcodeFormat.code93:
return 'CODE_93';
break;
case BarcodeFormat.code128:
return 'CODE_128';
break;
case BarcodeFormat.dataMatrix:
return 'DATA_MATRIX';
break;
case BarcodeFormat.ean8:
return 'EAN_8';
break;
case BarcodeFormat.ean13:
return 'EAN_13';
break;
case BarcodeFormat.itf:
return 'ITF';
break;
case BarcodeFormat.maxicode:
return 'MAXICODE';
break;
case BarcodeFormat.pdf417:
return 'PDF_417';
break;
case BarcodeFormat.qrcode:
return 'QR_CODE';
break;
case BarcodeFormat.rss14:
return 'RSS14';
break;
case BarcodeFormat.rssExpanded:
return 'RSS_EXPANDED';
break;
case BarcodeFormat.upcA:
return 'UPC_A';
break;
case BarcodeFormat.upcE:
return 'UPC_E';
break;
case BarcodeFormat.upcEanExtension:
return 'UPC_EAN_EXTENSION';
break;
}
return 'NOT_VALID';
}

}

+ 7
- 0
lib/src/types/camera.dart Datei anzeigen

@@ -0,0 +1,7 @@
enum CameraFacing {
/// Shows back facing camera.
back,

/// Shows front facing camera.
front
}

+ 14
- 0
lib/src/types/camera_exception.dart Datei anzeigen

@@ -0,0 +1,14 @@
/// This is thrown when the plugin reports an error.
class CameraException implements Exception {
/// Creates a new camera exception with the given error code and description.
CameraException(this.code, this.description);

/// Error code.
String code;

/// Textual description of the error.
String description;

@override
String toString() => 'CameraException($code, $description)';
}

+ 13
- 0
lib/src/types/features.dart Datei anzeigen

@@ -0,0 +1,13 @@
class SystemFeatures {
SystemFeatures(this.hasFlash, this.hasBackCamera, this.hasFrontCamera);

factory SystemFeatures.fromJson(Map<String, dynamic> features) =>
SystemFeatures(
features['hasFlash'] ?? false,
features['hasBackCamera'] ?? false,
features['hasFrontCamera'] ?? false);

final bool hasFlash;
final bool hasFrontCamera;
final bool hasBackCamera;
}

+ 1
- 1
pubspec.yaml Datei anzeigen

@@ -5,7 +5,7 @@ homepage: https://juliuscanute.com
repository: https://github.com/juliuscanute/qr_code_scanner

environment:
sdk: ">=2.3.0 <3.0.0"
sdk: ">=2.6.0 <3.0.0"
flutter: ^1.10.0

dependencies:


Laden…
Abbrechen
Speichern