Socket Mobile 是数据采集和交付解决方案的领先创新者,致力于提高生产力。
CaptureSDK 是将条形码扫描和 RFID/NFC 读取功能添加到 iOS 应用程序的最简单解决方案。
Socket Mobile 条形码扫描器和非接触式读/写器是一种符合人体工程学、快速且准确的解决方案,适用于各种数据输入场景。
该 SDK 非常容易集成到应用程序中,无需遵循特定的设计架构。
在 10 分钟内,条形码扫描或 RFID/NFC 读取功能即可集成到应用程序中。
CaptureSDK 提供一个内置的条形码扫描器,名为 SocketCam,允许在获得 Socket Mobile 扫描器之前,使用完全相同的 API 测试和集成 SDK,这使得从使用 SocketCam 过渡到使用 Socket 扫描器完全无缝。
更多文档请参见此处。
设备 | < 1.4 | 1.4 | 1.5 | 1.6 | 1.7 | 1.8 | 1.9 |
---|---|---|---|---|---|---|---|
SocketCam C820 | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
S720/D720/S820 | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
D600、S550 和所有其他条形码扫描器 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
S370 | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
M930 | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
SocketCam C860 | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
S320 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
我们改进和更改了架构中的一些内容,为未来做准备。 SDK 仍然可以按照您的预期工作。 但是,我们进行了一些更改,这些更改不需要您付出太多努力
CaptureSDK
CaptureSDK 使用 Swift Package Manager。
首先,您需要安装 Xcode。
要将 SDK 包含在您的 Xcode 项目中,您必须在项目的设置部分和“Package Dependencies”选项卡中添加一个 Package Dependency
。
添加此存储库的 URL:https://github.com/SocketMobile/swift-package-capturesdk.git
添加软件包后,您应该看到 CaptureSDK
添加到 Xcode 的项目导航器中的 Package Dependencies 中,如下所示
非常重要:在应用程序设置中支持的外部附件协议数组。 为了能够使用 Socket Mobile 条形码扫描器,需要在应用程序项目信息中的支持的外部附件协议数组中添加扫描器的外部附件协议字符串。
协议字符串是 com.socketmobile.chs
。
如果应用程序确实使用 Socket Mobile 条形码扫描器,则需要在将应用程序提交到 App Store 之前将其列入 MFi 白名单。 当您在 Socket Mobile 开发者帐户中提交您的应用程序以进行 MFi 时,Socket Mobile 将为您处理白名单 (MFi) 应用程序流程。 对于支持条形码扫描器的第一个版本,这必须完成一次。
您还需要将以下键添加到您的 Info.plist
:CFBundleAllowMixedLocalizations (Localized resources can be mixed) 设置为 YES
。 这允许我们的 SDK 显示本地化字符串。
需要 AppKey 才能使用 CaptureSDK。
AppKey 可以通过登录 Socket Mobile 开发者门户并注册您的应用程序来生成。
此注册需要 Socket Mobile 开发者 ID,应用程序 Bundle ID(区分大小写)。
现在您可以在您的主控制器中添加 import CaptureSDK
,并使其派生自您的应用程序需要的 CaptureHelperDelegate
之一。
转到 CaptureHelperDelegate
源,并复制粘贴您想要覆盖的委托,至少需要 onDecodedData 委托,以便能够在您的应用程序中接收条形码解码数据。
CaptureSDK
在文档中进行了更详细的描述。
推荐使用 CaptureSDK
的方式是使用 CaptureHelper
。 CaptureHelper
现在包含在框架中,而不是作为单独的文件:CaptureHelper
可以使用其 CaptureHelper.sharedInstance
静态成员在您的应用程序控制器之一中实例化 CaptureHelper
。
所选控制器必须实现 CaptureHelper[xxxxx]Delegate
协议之一,才能接收各种 CaptureSDK
异步事件。
可以使用 CaptureHelper pushDelegate
方法设置派生自至少一个 CaptureHelper[xxxxx]Delegate
的控制器的引用。
CaptureHelper
维护一个委托堆栈。 堆栈顶部的委托是接收来自 CaptureSDK
的通知的委托。 因此,如果应用程序有多个视图需要扫描功能,它可以将新视图控制器的引用推送到 CaptureHelper
委托堆栈,并在视图不再活动时删除该引用。
为了启动 CaptureSDK
,API 使用带有应用程序信息的 openWithAppInfo:withCompletionHandler
方法。
此打开方法只能调用一次,例如在主视图控制器中,并且 CaptureHelper.sharedInstance
可以在应用程序代码中的各个位置用作单例引用,而无需通过各种控制器传递它。
应用程序信息从 Socket Mobile 开发者门户检索,方法是用其应用程序 ID、开发者 ID 注册应用程序。 然后生成应用程序密钥,所有这三个密钥初始化打开 CaptureSDK
所需的 AppInfo。
应用程序 ID 由应用程序包 ID 前缀加上设计为运行应用程序的平台组成。
这是一个此类应用程序 ID 的示例:"ios:com.socketmobile.SingleEntry"
。 应用程序 ID 区分大小写。
一旦 CaptureSDK
打开,只要扫描器连接到 iOS 设备,就会发生设备到达通知。
可以通过覆盖 onDecodedData
委托来检索来自扫描器的解码数据。
SingleEntry 应用程序的 ViewController.m 示例
import UIKit
import CaptureSDK
class MasterViewController:
UITableViewController,
CaptureHelperDevicePresenceDelegate,
CaptureHelperDeviceManagerPresenceDelegate,
CaptureHelperDeviceDecodedDataDelegate,
CaptureHelperErrorDelegate,
CaptureHelperDevicePowerDelegate {
// Capture Helper shareInstance allows to share
// the same instance of Capture Helper with the
// entire application. That static property can
// be used in any views but it is recommended
// to open only once Capture Helper (in the main
// view controller) and pushDelegate, popDelegate
// each time a new view requiring scanning capability
// is loaded or unloaded respectively.
var captureHelper = CaptureHelper.sharedInstance
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// fill out the App Info with the Bundle ID which should start by the
// platform on which the application is running and followed with the
// case sensitive application Bundle ID,
// with the Socket Mobile Portal developer ID
// and with the Application Key generated from the Socket Mobile Developer
// portal
let AppInfo = SKTAppInfo()
AppInfo.appKey = "MC0CFQD1tdTpaABkppmG+iP3dB9kolYVtwIUY8c3UmEfaPoTI3AxbPOTpNgw+fo="
AppInfo.appID = "ios:com.socketmobile.SingleEntrySwift"
AppInfo.developerID = "bb57d8e1-f911-47ba-b510-693be162686a"
// there is a stack of delegates the last push is the
// delegate active, when a new view requiring notifications from the
// scanner, then push its delegate and pop its delegate when the
// view is done
captureHelper.pushDelegate(self)
// to make all the delegates able to update the UI without the app
// having to dispatch the UI update code, set the dispatchQueue
// property to the DispatchQueue.main
captureHelper.dispatchQueue = DispatchQueue.main
// open Capture Helper only once in the application
captureHelper.openWithAppInfo(AppInfo, withCompletionHandler: { (_ result: SKTResult) in
print("Result of Capture initialization: \(result.rawValue)")
})
}
}
CaptureHelper
通过调用协议的 onDeviceArrival
使应用程序知道新的设备连接,并且以相同的方式,当设备断开连接时,调用 onDeviceRemoval
。 可以使用表示已连接的设备的 CaptureHelper
设备实例来检索或设置设备属性。
视图控制器知道扫描器的示例
func didNotifyArrivalForDevice(_ device: CaptureHelperDevice, withResult result: SKTResult) {
print("Main view device arrival:\(device.deviceInfo.name!)")
}
func didNotifyRemovalForDevice(_ device: CaptureHelperDevice, withResult result: SKTResult) {
print("Main view device removal:\(device.deviceInfo.name!)")
}
对于像 S370 这样具有 2 个设备的组合设备,将有两个 didNotifyArrivalForDevice
和两个 didNotifyRemovalForDevice
通知。
以下代码显示了如何区分和处理它们
func didNotifyArrivalForDevice(_ device: CaptureHelperDevice, withResult result: SKTResult) {
print("didNotifyArrivalForDevice: \(String(describing: device.deviceInfo.name))")
if device.deviceInfo.deviceType == .NFCS370 {
// handle the NFC reader of the S370
} else if device.deviceInfo.deviceType == .scannerS370 {
// handle the Barcode scanner of the S370
}
}
如果扫描器触发扫描,则可以在协议函数 onDecodedData
中检索解码的数据。
检索扫描器接收到的解码数据的示例
func didReceiveDecodedData(_ decodedData: SKTCaptureDecodedData?, fromDevice device: CaptureHelperDevice, withResult result: SKTResult) {
if result == SKTCaptureErrors.E_NOERROR {
let rawData = decodedData?.decodedData
let rawDataSize = rawData?.count
print("Size: \(String(describing: rawDataSize))")
print("data: \(String(describing: decodedData?.decodedData))")
let string = decodedData?.stringFromDecodedData()!
print("Decoded Data \(String(describing: string))")
}
}
应用程序可以通过调用各种 CaptureHelperDevice
get/set 方法来检索或修改设备属性。 例如,有一种方法可以检索设备友好名称:getFriendlyNameWithCompletionHandler
。 调用是异步的,并将立即返回。 可以在完成处理程序函数块中检索最终结果和友好名称。
重要提示:如果无法通过可用的 CaptureHelper
方法访问属性,则通过创建 CaptureHelper
扩展类并复制粘贴类似的 get/set 方法并在新方法中更改属性设置,可以很容易地添加新属性。
创建 CaptureHelper
扩展允许避免在更新到更新的 CaptureSDK
CocoaPods 时覆盖修改版本的 CaptureHelper
。
示例代码可以在 GitHub / SocketMobile 中找到
我们将 SocketCam C820
& SocketCam C860
包含在 SDK 中,以前称为 SoftScan。
对于 SocketCam C860 是 SocketCam C820 的增强版本,您还需要将以下键添加到您的 Info.plist
:LSApplicationQueriesSchemes (Queried URL Schemes) ,并添加一个新项目:sktcompanion (小写)。
为了使用它,您必须在您的设备上安装 Socket Mobile Companion。
您可以在我们的网站上找到有关 SocketCam C860 的更多详细信息。
SocketCam
功能是指使用手机摄像头扫描条形码的功能。 在 CaptureSDK
中集成此功能的主要目的是为条形码读取器提供一致的接口。
无论是 Socket Mobile 扫描器,还是仅仅是手机摄像头,应用程序都依赖于相同的界面、相同的 API,这使得从使用 SocketCam 过渡到使用物理 Socket 扫描器完全无缝。
使用 SocketCam
功能的应用程序需要做 2 件不同的事情,而 Socket Mobile 扫描器不需要。
第一件事是提供触发逻辑,以启动 SocketCam
扫描操作。 该触发器是自第一个版本的 CaptureSDK
以来就存在的 CaptureSDK
属性 kSktCapturePropIdTriggerDevice
。
第三个属性 kSktCapturePropIdSocketCamStatus
允许启用或禁用 SocketCam
功能。 这是一个 CaptureSDK
属性,它在使用它的应用程序的整个生命周期中都是持久的。
如果启用 SocketCam
功能,CaptureSDK
将向应用程序发送设备到达通知,引用应用程序可以控制的 SocketCam
设备。
一旦应用程序触发读取操作,解码后的数据将以相同的方式到达,并包含与 CaptureSDK
支持的任何其他 Socket Mobile 设备相同的信息。
有关更多信息,请查看文档。
通过 CaptureSDK 的新版本,您可以按照您希望的方式在自定义视图、弹出窗口甚至全屏模式下呈现 SocketCam。 现在,您可以决定在应用程序流程中何时何地触发和移除 SocketCam 视图控制器。 您有责任处理视图控制器的呈现和关闭。 但是,为了显示所有 SocketCam 的 UI 元素,必须遵守 250px x 250px 的最小尺寸。
之前
之后
let scanner = CaptureHelperDevice()
scanner.setTrigger(.start, withCompletionHandler: { result, propertyObject in
DispatchQueue.main.async {
if let anObject = propertyObject?.object, let dic = anObject as? [String: Any], let objectType = dic["SKTObjectType"] as? String, objectType == "SKTSocketCamViewControllerType", let socketCamViewController = dic["SKTSocketCamViewController"] as? UIViewController {
////
// Present the socketCamViewController in a popover or a subview or in full screen
////
}
}
})
extension YourViewController: CaptureHelperDeviceDecodedDataDelegate {
// This delegate is called each time a decoded data is read from a scanner or SocketCam
func didReceiveDecodedData(_ decodedData: SKTCaptureDecodedData?, fromDevice device: CaptureHelperDevice, withResult result:SKTResult) {
print("--->>> didReceiveDecodedData for device: \(device.deviceInfo.deviceType)")
if result == .E_NOERROR {
let str = decodedData!.stringFromDecodedData()
print("Decoded Data \(String(describing: str))")
DispatchQueue.main.async {
////
// When receiving your decoded data you can dismiss, hide, remove the SocketCam custom view controller
////
}
}
}
}
根据您希望在应用程序中显示 SocketCam 的方式,可能需要显示或隐藏 SocketCam 视图控制器的关闭按钮。 理想情况下,您可以在 SocketCam 设备到达时执行此操作,无论是 C820 还是 C860。 为此,请添加如下特定配置
let prop = SKTCaptureProperty()
prop.id = SKTCapturePropertyID.configuration
prop.type = .string
prop.stringValue = "SocketCamCloseButton=enabled" /// to show the close button
// OR
prop.stringValue = "SocketCamCloseButton=disabled" /// to hide the close button
self.captureHelper.setProperty(prop) { result, complete in
}
如果您将 SocketCam 视图控制器作为子视图添加到另一个视图控制器(myView.addsubview(self.socketCamViewController.view)
),那么在使用完毕后,您需要移除 SocketCam 视图控制器的视图(self.socketCamViewController.view.removeFromSuperview()
),否则下次触发 SocketCam 时将无法显示。 因此,最好保留对 CaptureHelper 方法 setTrigger
提供的 SocketCam 视图控制器的引用。
CaptureSDK
旨在用于 iOS 平台上的所有 Socket Mobile 设备。
作为应用程序开发人员,CaptureSDK
将为您提供对连接的 Socket Mobile 数据捕获设备的完全编程访问权限,以自定义数据源(条形码符号或 RFID 标签)、数据支持并管理设备反馈消息和功能。
CaptureSDK
的 API 文档可以在这里找到。
Socket Mobile 设备默认以 MFi 模式发货,该模式与 CaptureSDK
兼容。
可以使用 Socket Mobile Companion app 将设备配置为 Application 模式。
您也可以参考文档,了解如何在不使用 Companion 的情况下进行配置的说明。
BLE 设备
对于 D600、S550 和 S370,BLE 设备管理器必须将首选项设置为 *
,有关更多信息,请查看文档。
主题选择允许选择在 S550 或 S370 设备上播放的 LED 序列。 请查看文档。
可以配置设备通知,以便在发生以下一个或多个事件时接收通知
默认情况下,设备通知处于关闭状态。 建议的用法是首先检查是否已关闭或打开特定通知。 根据此读取,如果尚未设置,则应用程序可以设置要接收的特定通知。 该设置在扫描仪关闭后仍保留在 Socket Mobile 设备中。 不建议在不首先检查该设置是否正确的情况下,在设备中系统地设置通知。
对于电池电量和电源状态,状态可能需要很长时间才能更改,因此通常使用相应的 CaptureHelper
Get 方法读取初始值。
最后,某些设备不支持某些通知。 如果是这种情况,则在尝试设置不支持的通知时会返回错误 ESKT_NOTSUPPORTED (-15)
。
有关更多信息,请查看文档。
不建议关闭 CaptureSDK
,因为下次打开 CaptureSDK
时扫描仪将重新初始化,这会导致在使用扫描仪之前出现延迟。
关闭 CaptureSDK
不会影响功耗,因为扫描仪仍然连接到 iOS 主机。
还值得注意的是,与建立连接相比,连接 Socket Mobile 设备时的功耗非常低。
如果关闭 CaptureSDK
的原因是不要接收来自设备的任何解码数据,则可以简单地删除应用程序代理,并且应用程序将不再接收来自扫描仪的任何事件,直到再次设置其代理为止。