概览
许多应用需要第二台设备:摄像头和观看端、手机和平板、自助终端和管理员手机。在第二台设备上登录正是用户放弃的环节:他们得记住用户名、输入密码,或等待邮件验证码。
KlugRegister 把这一步变成一次拍摄。第一台设备生成二维码;第二台设备用原生扫描器扫描,应用即完成登录。二维码携带您的应用所需的任何内容,通常是来自服务器的一次性代码,绝不是密码本身。
两部分都是原生的:二维码由系统生成(任意尺寸都清晰锐利,以可直接显示的 AIR BitmapData 形式提供),扫描器同样是原生的:iOS 上是带有您自己提示文字的全屏摄像头视图,Android 上是 Google 的代码扫描器,完全不需要摄像头权限。
KlugRegister 运行在我们的应用的当前版本中,这就是我们的概念验证:注册后应用显示一个二维码,第二台设备数秒内即可完成配对,即使是刚从商店安装应用之后。
特性
- 自成一体:一个 ANE,无需添加核心库或依赖 ANE
- 可从任意文本或 URL 生成二维码,以带有合规静区的 BitmapData 返回
- 以每个模块的像素数选择尺寸,在任何屏幕上都清晰锐利
- 原生全屏摄像头扫描器,可自定义提示文字和取消按钮
- 请求摄像头权限,并在被拒绝时进行报告
- Android:使用 Play 服务的 Google 代码扫描器,无需摄像头权限
- 在手机和平板上均支持竖屏和横屏
- iOS 和 macOS:仅使用系统框架;Android:ZXing 和 Google 代码扫描器,在打包应用时自动解析
支持的平台
Android 生成 + 扫描
iOS 生成 + 扫描 · arm64
macOS 生成 + 扫描 (macOS 13+) · arm64 · x86_64
Mac 上的 iPad 生成 + 扫描
在某项功能不可用的平台上,isSupported 和 isScanSupported 返回 false,因此同一份代码可以保留在每个应用中。
入门
将扩展添加到您的应用描述文件中:
<extensions>
<extensionID>com.klug.register.KlugRegister</extensionID>
</extensions>
要在 iOS 上扫描,请在 InfoAdditions 中添加摄像头使用说明:
<key>NSCameraUsageDescription</key> <string>Scan the QR code of your first device</string>
代码示例
配对第二台设备的四个完整流程。生成二维码是即时完成的;扫描结果以 KlugRegisterEvent 的形式到达。完整文档 →
1 · 在第一台设备上显示配对码
import com.klug.register.KlugRegister; import com.klug.register.KlugRegisterEvent; import flash.display.Bitmap; import flash.display.BitmapData; var reg:KlugRegister = KlugRegister.getInstance(); if ( reg.isSupported ) // Android, iOS, macOS { // a short-lived one-time code from your server, never the password var bmp:BitmapData = reg.createQRCode( "https://your.server/pair?t=" + oneTimeCode, 10 ); if ( bmp != null ) // null: no code could be made from the text { var qr:Bitmap = new Bitmap( bmp ); // black on white, 4-module quiet zone included qr.x = ( stage.stageWidth - qr.width ) / 2; qr.y = 120; addChild( qr ); } }
2 · 在第二台设备上扫描
reg.addEventListener( KlugRegisterEvent.SCANNED, onScanned ); reg.addEventListener( KlugRegisterEvent.CANCELED, onScanCanceled ); reg.addEventListener( KlugRegisterEvent.ERROR, onScanError ); function startScan():void { if ( !reg.isScanSupported ) { showCodeEntry(); // your app function: type the one-time code instead return; } // iOS: full-screen scanner with your hint and button; macOS 13+: a sheet on the app window; // Android: Google's own localized scanner, hint and cancel title are not used if ( !reg.scanQRCode( "Point the camera at the code on your first device", "Cancel" ) ) trace( "a scanner is already open" ); }
3 · 向您的服务器兑换该代码
function onScanned( e:KlugRegisterEvent ):void { var prefix:String = "https://your.server/pair?t="; if ( e.text.indexOf( prefix ) != 0 ) { showMessage( "This is not a pairing code." ); // your app function return; } var vars:URLVariables = new URLVariables(); vars.t = e.text.substr( prefix.length ); var req:URLRequest = new URLRequest( "https://your.server/pair" ); req.method = URLRequestMethod.POST; req.data = vars; var loader:URLLoader = new URLLoader(); loader.addEventListener( Event.COMPLETE, function( ev:Event ):void { signInWith( String( loader.data ) ); // your app function: the server's answer }); loader.load( req ); }
4 · 取消与错误
function onScanCanceled( e:KlugRegisterEvent ):void { showPairingScreen(); // the user closed the scanner: back to the screen, no message } function onScanError( e:KlugRegisterEvent ):void { switch ( e.errorCode ) { case "denied": // iOS, macOS: camera permission refused showMessage( "Allow camera access in Settings to scan the code." ); break; case "nocamera": // iOS, macOS: no usable camera showCodeEntry(); break; default: // Android: "scanner" (e.g. scanner not ready yet) or "empty" showMessage( "The scanner could not start: " + e.errorMessage ); } }
API 概览
| KlugRegister.getInstance() | 返回唯一实例。 |
| isSupported | 在可以生成二维码的平台上为 True(Android、iOS、macOS)。 |
| isScanSupported | 在扫描器可用的平台上为 True:Android、iOS,以及配有摄像头的 macOS 13 或更高版本。 |
| createQRCode(text, modulePx) | 以 BitmapData 返回二维码,白底黑码,带 4 个模块宽的静区;modulePx 为每个模块的像素数(默认 8)。若无法生成则返回 Null。 |
| scanQRCode(hint, cancelTitle) | 打开扫描器:iOS 上为全屏,Mac 上为面板,Android 上为 Google 的扫描器(此处不使用提示和标题)。结果以事件形式到达。如果已有扫描器打开,则返回 false。 |
| KlugRegisterEvent | text, errorCode, errorMessage. |
事件
| KlugRegisterEvent.SCANNED | 已读取到一个代码;e.text 保存其内容。 |
| KlugRegisterEvent.CANCELED | 用户关闭了扫描器。 |
| KlugRegisterEvent.ERROR | e.errorCode:denied(无摄像头权限)· nocamera 适用于 iOS 和 macOS;scanner · empty 适用于 Android。详情见 e.errorMessage。 |
购买 KlugRegister
一个 AIR 应用的年度许可,含 12 个月内的所有更新。付款后,您将通过电子邮件收到扩展、ActionScript 库和文档,通常在一个工作日内。许可与条款
税费在结账时由 Link (Stripe) 计算。您需要在结账时输入 AIR 应用的应用 ID。
要求
| AIR SDK | 51.x (HARMAN) |
| Android | Android 6 或更高版本,Google Play 服务(扫描器) |
| iOS | iOS 13 或更高版本 |
| macOS | macOS 10.15 或更高版本(生成二维码);扫描需 macOS 13 或更高版本 |
| 权限 | iOS 和 macOS:扫描需要摄像头 (NSCameraUsageDescription);Android:无 |