The QR Code Scanner package for Appeto SDK.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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