/** * Android 系统扫码 API 实现 * 使用 android.device.ScanDevice + 广播监听 */ // UTF8 字节数组解码为 Unicode 字符串 function utf8ByteToUnicodeStr(utf8Bytes) { var unicodeStr = '' for (var pos = 0; pos < utf8Bytes.length;) { var flag = utf8Bytes[pos] var unicode = 0 if ((flag >>> 7) === 0) { unicodeStr += String.fromCharCode(utf8Bytes[pos]) pos += 1 } else if ((flag & 0xFC) === 0xFC) { unicode = (utf8Bytes[pos] & 0x3) << 30 unicode |= (utf8Bytes[pos + 1] & 0x3F) << 24 unicode |= (utf8Bytes[pos + 2] & 0x3F) << 18 unicode |= (utf8Bytes[pos + 3] & 0x3F) << 12 unicode |= (utf8Bytes[pos + 4] & 0x3F) << 6 unicode |= (utf8Bytes[pos + 5] & 0x3F) unicodeStr += String.fromCodePoint(unicode) pos += 6 } else if ((flag & 0xF8) === 0xF8) { unicode = (utf8Bytes[pos] & 0x7) << 24 unicode |= (utf8Bytes[pos + 1] & 0x3F) << 18 unicode |= (utf8Bytes[pos + 2] & 0x3F) << 12 unicode |= (utf8Bytes[pos + 3] & 0x3F) << 6 unicode |= (utf8Bytes[pos + 4] & 0x3F) unicodeStr += String.fromCodePoint(unicode) pos += 5 } else if ((flag & 0xF0) === 0xF0) { unicode = (utf8Bytes[pos] & 0xF) << 18 unicode |= (utf8Bytes[pos + 1] & 0x3F) << 12 unicode |= (utf8Bytes[pos + 2] & 0x3F) << 6 unicode |= (utf8Bytes[pos + 3] & 0x3F) unicodeStr += String.fromCodePoint(unicode) pos += 4 } else if ((flag & 0xE0) === 0xE0) { unicode = (utf8Bytes[pos] & 0x1F) << 12 unicode |= (utf8Bytes[pos + 1] & 0x3F) << 6 unicode |= (utf8Bytes[pos + 2] & 0x3F) unicodeStr += String.fromCharCode(unicode) pos += 3 } else if ((flag & 0xC0) === 0xC0) { unicode = (utf8Bytes[pos] & 0x3F) << 6 unicode |= (utf8Bytes[pos + 1] & 0x3F) unicodeStr += String.fromCharCode(unicode) pos += 2 } else { unicodeStr += String.fromCharCode(utf8Bytes[pos]) pos += 1 } } return unicodeStr } class ScanAndroidImpl { constructor() { this.scanDevice = null this._receiver = null this._filter = null this._main = null this._callback = null this._isScanning = false } /** * 初始化:打开扫描设备,设置广播模式 */ init() { // var ScanDeviceClass = plus.android.importClass('android.device.ScanDevice') // this.scanDevice = new ScanDeviceClass() // 使用 plus.android.newObject 创建实例(更兼容) try { this.scanDevice = plus.android.newObject('android.device.ScanDevice') } catch (e) { throw new Error('[Scan-Android] 当前设备不支持 android.device.ScanDevice,请切换到 iData 模式或使用其他扫码方式: ' + e.message) } this.scanDevice.openScan() this.scanDevice.setOutScanMode(0) // 0 = 广播模式 this._main = plus.android.runtimeMainActivity() var IntentFilter = plus.android.importClass('android.content.IntentFilter') this._filter = new IntentFilter() this._filter.addAction('scan.rcv.message') } /** * 注册扫码结果回调 * @param {Function} callback - (codeStr: string) => void */ register(callback) { this._callback = callback var self = this this._receiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', { onReceive: function (context, intent) { plus.android.importClass(intent) var code = intent.getByteArrayExtra('barocode') if (code) { var codeStr = utf8ByteToUnicodeStr(code) console.log('[Scan-Android] 扫码结果:', codeStr) self.scanDevice.stopScan() self._isScanning = false if (self._callback) { self._callback(codeStr) } } } }) this._main.registerReceiver(this._receiver, this._filter) } /** * 注销监听(页面卸载时调用) */ unregister() { if (this._receiver && this._main) { this._main.unregisterReceiver(this._receiver) this._receiver = null } this._callback = null } /** * 开始扫描 */ startScan() { if (this.scanDevice) { this.scanDevice.stopScan() this.scanDevice.startScan() this._isScanning = true } } /** * 停止扫描 */ stopScan() { if (this.scanDevice) { this.scanDevice.stopScan() this._isScanning = false } } /** * 是否正在扫描 */ isScanning() { return this._isScanning } /** * 完全销毁(应用退出时调用) */ destroy() { this.unregister() if (this.scanDevice) { this.scanDevice.closeScan() this.scanDevice = null } this._main = null this._filter = null } } export default ScanAndroidImpl