The QR Code Scanner package for Appeto SDK.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 
 

278 řádky
11 KiB

  1. //
  2. // QRView.swift
  3. // flutter_qr
  4. //
  5. // Created by Julius Canute on 21/12/18.
  6. //
  7. import Foundation
  8. import MTBBarcodeScanner
  9. public class QRView:NSObject,FlutterPlatformView {
  10. @IBOutlet var previewView: UIView!
  11. var scanner: MTBBarcodeScanner?
  12. var registrar: FlutterPluginRegistrar
  13. var channel: FlutterMethodChannel
  14. var cameraFacing: MTBCamera
  15. // Codabar, maxicode, rss14 & rssexpanded not supported. Replaced with qr.
  16. // UPCa uses ean13 object.
  17. var QRCodeTypes = [
  18. 0: AVMetadataObject.ObjectType.aztec,
  19. 1: AVMetadataObject.ObjectType.qr,
  20. 2: AVMetadataObject.ObjectType.code39,
  21. 3: AVMetadataObject.ObjectType.code93,
  22. 4: AVMetadataObject.ObjectType.code128,
  23. 5: AVMetadataObject.ObjectType.dataMatrix,
  24. 6: AVMetadataObject.ObjectType.ean8,
  25. 7: AVMetadataObject.ObjectType.ean13,
  26. 8: AVMetadataObject.ObjectType.interleaved2of5,
  27. 9: AVMetadataObject.ObjectType.qr,
  28. 10: AVMetadataObject.ObjectType.pdf417,
  29. 11: AVMetadataObject.ObjectType.qr,
  30. 12: AVMetadataObject.ObjectType.qr,
  31. 13: AVMetadataObject.ObjectType.qr,
  32. 14: AVMetadataObject.ObjectType.ean13,
  33. 15: AVMetadataObject.ObjectType.upce
  34. ]
  35. public init(withFrame frame: CGRect, withRegistrar registrar: FlutterPluginRegistrar, withId id: Int64, params: Dictionary<String, Any>){
  36. self.registrar = registrar
  37. previewView = UIView(frame: frame)
  38. cameraFacing = MTBCamera.init(rawValue: UInt(Int(params["cameraFacing"] as! Double))) ?? MTBCamera.back
  39. channel = FlutterMethodChannel(name: "net.touchcapture.qr.flutterqr/qrview_\(id)", binaryMessenger: registrar.messenger())
  40. }
  41. deinit {
  42. scanner?.stopScanning()
  43. }
  44. public func view() -> UIView {
  45. channel.setMethodCallHandler({
  46. [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
  47. switch(call.method){
  48. case "setDimensions":
  49. let arguments = call.arguments as! Dictionary<String, Double>
  50. self?.setDimensions(result,
  51. width: arguments["width"] ?? 0,
  52. height: arguments["height"] ?? 0,
  53. scanArea: arguments["scanArea"] ?? 0,
  54. scanAreaOffset: arguments["scanAreaOffset"] ?? 0)
  55. case "startScan":
  56. self?.startScan(call.arguments as! Array<Int>, result)
  57. case "flipCamera":
  58. self?.flipCamera(result)
  59. case "toggleFlash":
  60. self?.toggleFlash(result)
  61. case "pauseCamera":
  62. self?.pauseCamera(result)
  63. case "stopCamera":
  64. self?.stopCamera(result)
  65. case "resumeCamera":
  66. self?.resumeCamera(result)
  67. case "getCameraInfo":
  68. self?.getCameraInfo(result)
  69. case "getFlashInfo":
  70. self?.getFlashInfo(result)
  71. case "getSystemFeatures":
  72. self?.getSystemFeatures(result)
  73. default:
  74. result(FlutterMethodNotImplemented)
  75. return
  76. }
  77. })
  78. return previewView
  79. }
  80. func setDimensions(_ result: @escaping FlutterResult, width: Double, height: Double, scanArea: Double, scanAreaOffset: Double) {
  81. // Then set the size of the preview area.
  82. previewView.frame = CGRect(x: 0, y: 0, width: width, height: height)
  83. // Then set the size of the scan area.
  84. let midX = self.view().bounds.midX
  85. let midY = self.view().bounds.midY
  86. if let sc: MTBBarcodeScanner = scanner {
  87. // Set the size of the preview if preview is already created.
  88. if let previewLayer = sc.previewLayer {
  89. previewLayer.frame = self.previewView.bounds
  90. }
  91. } else {
  92. // Create new preview.
  93. scanner = MTBBarcodeScanner(previewView: previewView)
  94. }
  95. // Set scanArea if provided.
  96. if (scanArea != 0) {
  97. scanner?.didStartScanningBlock = {
  98. self.scanner?.scanRect = CGRect(x: Double(midX) - (scanArea / 2), y: Double(midY) - (scanArea / 2), width: scanArea, height: scanArea)
  99. // Set offset if provided.
  100. if (scanAreaOffset != 0) {
  101. let reversedOffset = -scanAreaOffset
  102. self.scanner?.scanRect = (self.scanner?.scanRect.offsetBy(dx: 0, dy: CGFloat(reversedOffset)))!
  103. }
  104. }
  105. }
  106. return result(width)
  107. }
  108. func startScan(_ arguments: Array<Int>, _ result: @escaping FlutterResult) {
  109. // Check for allowed barcodes
  110. var allowedBarcodeTypes: Array<AVMetadataObject.ObjectType> = []
  111. arguments.forEach { arg in
  112. allowedBarcodeTypes.append( QRCodeTypes[arg]!)
  113. }
  114. MTBBarcodeScanner.requestCameraPermission(success: { [weak self] permissionGranted in
  115. guard let self = self else { return }
  116. self.channel.invokeMethod("onPermissionSet", arguments: permissionGranted)
  117. if permissionGranted {
  118. do {
  119. try self.scanner?.startScanning(with: self.cameraFacing, resultBlock: { [weak self] codes in
  120. if let codes = codes {
  121. for code in codes {
  122. var typeString: String;
  123. switch(code.type) {
  124. case AVMetadataObject.ObjectType.aztec:
  125. typeString = "AZTEC"
  126. case AVMetadataObject.ObjectType.code39:
  127. typeString = "CODE_39"
  128. case AVMetadataObject.ObjectType.code93:
  129. typeString = "CODE_93"
  130. case AVMetadataObject.ObjectType.code128:
  131. typeString = "CODE_128"
  132. case AVMetadataObject.ObjectType.dataMatrix:
  133. typeString = "DATA_MATRIX"
  134. case AVMetadataObject.ObjectType.ean8:
  135. typeString = "EAN_8"
  136. case AVMetadataObject.ObjectType.ean13:
  137. typeString = "EAN_13"
  138. case AVMetadataObject.ObjectType.itf14,
  139. AVMetadataObject.ObjectType.interleaved2of5:
  140. typeString = "ITF"
  141. case AVMetadataObject.ObjectType.pdf417:
  142. typeString = "PDF_417"
  143. case AVMetadataObject.ObjectType.qr:
  144. typeString = "QR_CODE"
  145. case AVMetadataObject.ObjectType.upce:
  146. typeString = "UPC_E"
  147. default:
  148. return
  149. }
  150. guard let stringValue = code.stringValue else { continue }
  151. let result = ["code": stringValue, "type": typeString]
  152. if allowedBarcodeTypes.count == 0 || allowedBarcodeTypes.contains(code.type) {
  153. self?.channel.invokeMethod("onRecognizeQR", arguments: result)
  154. }
  155. }
  156. }
  157. })
  158. } catch {
  159. let scanError = FlutterError(code: "unknown-error", message: "Unable to start scanning", details: error)
  160. result(scanError)
  161. }
  162. } else {
  163. let error = FlutterError(code: "cameraPermission", message: "Permission denied to access the camera", details: nil)
  164. result(error)
  165. }
  166. })
  167. }
  168. func stopCamera(_ result: @escaping FlutterResult) {
  169. if let sc: MTBBarcodeScanner = self.scanner {
  170. if sc.isScanning() {
  171. sc.stopScanning()
  172. }
  173. }
  174. }
  175. func getCameraInfo(_ result: @escaping FlutterResult) {
  176. result(self.cameraFacing.rawValue)
  177. }
  178. func flipCamera(_ result: @escaping FlutterResult) {
  179. if let sc: MTBBarcodeScanner = self.scanner {
  180. if sc.hasOppositeCamera() {
  181. sc.flipCamera()
  182. self.cameraFacing = sc.camera
  183. }
  184. return result(sc.camera.rawValue)
  185. }
  186. return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
  187. }
  188. func getFlashInfo(_ result: @escaping FlutterResult) {
  189. if let sc: MTBBarcodeScanner = self.scanner {
  190. result(sc.torchMode.rawValue != 0)
  191. } else {
  192. let error = FlutterError(code: "cameraInformationError", message: "Could not get flash information", details: nil)
  193. result(error)
  194. }
  195. }
  196. func toggleFlash(_ result: @escaping FlutterResult){
  197. if let sc: MTBBarcodeScanner = self.scanner {
  198. if sc.hasTorch() {
  199. sc.toggleTorch()
  200. return result(sc.torchMode == MTBTorchMode(rawValue: 1))
  201. }
  202. return result(FlutterError(code: "404", message: "This device doesn\'t support flash", details: nil))
  203. }
  204. return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
  205. }
  206. func pauseCamera(_ result: @escaping FlutterResult) {
  207. if let sc: MTBBarcodeScanner = self.scanner {
  208. if sc.isScanning() {
  209. sc.freezeCapture()
  210. }
  211. return result(true)
  212. }
  213. return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
  214. }
  215. func resumeCamera(_ result: @escaping FlutterResult) {
  216. if let sc: MTBBarcodeScanner = self.scanner {
  217. if !sc.isScanning() {
  218. sc.unfreezeCapture()
  219. }
  220. return result(true)
  221. }
  222. return result(FlutterError(code: "404", message: "No barcode scanner found", details: nil))
  223. }
  224. func getSystemFeatures(_ result: @escaping FlutterResult) {
  225. if let sc: MTBBarcodeScanner = scanner {
  226. var hasBackCameraVar = false
  227. var hasFrontCameraVar = false
  228. let camera = sc.camera
  229. if(camera == MTBCamera(rawValue: 0)){
  230. hasBackCameraVar = true
  231. if sc.hasOppositeCamera() {
  232. hasFrontCameraVar = true
  233. }
  234. }else{
  235. hasFrontCameraVar = true
  236. if sc.hasOppositeCamera() {
  237. hasBackCameraVar = true
  238. }
  239. }
  240. return result([
  241. "hasFrontCamera": hasFrontCameraVar,
  242. "hasBackCamera": hasBackCameraVar,
  243. "hasFlash": sc.hasTorch(),
  244. "activeCamera": camera.rawValue
  245. ])
  246. }
  247. return result(FlutterError(code: "404", message: nil, details: nil))
  248. }
  249. }