172 lines
4.7 KiB
JavaScript
172 lines
4.7 KiB
JavaScript
/**
|
|
* 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
|