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.
 
 
 
 
 
 

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