@fww_123/uni-ble-scanner 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/dist/core/base-scanner.d.ts +99 -0
- package/dist/core/base-scanner.d.ts.map +1 -0
- package/dist/factory.d.ts +44 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +1791 -0
- package/dist/index.js +1818 -0
- package/dist/platforms/android-native.d.ts +30 -0
- package/dist/platforms/android-native.d.ts.map +1 -0
- package/dist/platforms/harmony-native.d.ts +24 -0
- package/dist/platforms/harmony-native.d.ts.map +1 -0
- package/dist/platforms/ios-native.d.ts +27 -0
- package/dist/platforms/ios-native.d.ts.map +1 -0
- package/dist/platforms/uniapp-scanner.d.ts +30 -0
- package/dist/platforms/uniapp-scanner.d.ts.map +1 -0
- package/dist/types.d.ts +170 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/data-parser.d.ts +32 -0
- package/dist/utils/data-parser.d.ts.map +1 -0
- package/dist/utils/errors.d.ts +27 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/permissions.d.ts +9 -0
- package/dist/utils/permissions.d.ts.map +1 -0
- package/dist/utils/platform.d.ts +18 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/package.json +58 -0
- package/src/core/base-scanner.ts +309 -0
- package/src/factory.ts +116 -0
- package/src/index.ts +54 -0
- package/src/platforms/android-native.ts +300 -0
- package/src/platforms/harmony-native.ts +267 -0
- package/src/platforms/ios-native.ts +264 -0
- package/src/platforms/uniapp-scanner.ts +171 -0
- package/src/types/global.d.ts +25 -0
- package/src/types/uni-types.d.ts +83 -0
- package/src/types.ts +178 -0
- package/src/utils/data-parser.ts +217 -0
- package/src/utils/errors.ts +105 -0
- package/src/utils/permissions.ts +244 -0
- package/src/utils/platform.ts +70 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { BaseScanner } from '../core/base-scanner';
|
|
2
|
+
import {
|
|
3
|
+
Platform,
|
|
4
|
+
AdapterState,
|
|
5
|
+
BLEError,
|
|
6
|
+
PlatformConfig,
|
|
7
|
+
} from '../types';
|
|
8
|
+
import { Errors, createError, ErrorCodes, handlePlatformError } from '../utils/errors';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Android 原生蓝牙扫描器
|
|
12
|
+
* 使用 uni-app 的 Native.js 调用 Android 原生 API
|
|
13
|
+
*/
|
|
14
|
+
export class AndroidNativeScanner extends BaseScanner {
|
|
15
|
+
private bluetoothAdapter: any = null;
|
|
16
|
+
private bluetoothLeScanner: any = null;
|
|
17
|
+
private scanCallback: any = null;
|
|
18
|
+
private adapterStateReceiver: any = null;
|
|
19
|
+
|
|
20
|
+
getPlatform(): Platform {
|
|
21
|
+
return Platform.ANDROID;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async init(): Promise<void> {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
try {
|
|
27
|
+
// #ifdef APP-PLUS
|
|
28
|
+
const mainActivity = plus.android.runtimeMainActivity();
|
|
29
|
+
const BluetoothManager = plus.android.importClass('android.bluetooth.BluetoothManager');
|
|
30
|
+
const bluetoothManager = mainActivity.getSystemService('bluetooth');
|
|
31
|
+
|
|
32
|
+
this.bluetoothAdapter = bluetoothManager.getAdapter();
|
|
33
|
+
|
|
34
|
+
if (!this.bluetoothAdapter) {
|
|
35
|
+
reject(Errors.adapterNotAvailable());
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!this.bluetoothAdapter.isEnabled()) {
|
|
40
|
+
reject(Errors.bluetoothDisabled());
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
this.initialized = true;
|
|
45
|
+
resolve();
|
|
46
|
+
// #endif
|
|
47
|
+
|
|
48
|
+
// #ifndef APP-PLUS
|
|
49
|
+
reject(createError(ErrorCodes.UNSUPPORTED_PLATFORM, '非 APP 环境不支持原生 Android 扫描'));
|
|
50
|
+
// #endif
|
|
51
|
+
} catch (error) {
|
|
52
|
+
reject(handlePlatformError(error, 'android'));
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
protected async startScanInternal(): Promise<void> {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
try {
|
|
60
|
+
// #ifdef APP-PLUS
|
|
61
|
+
const systemInfo = uni.getSystemInfoSync();
|
|
62
|
+
const osVersion = parseInt(systemInfo.system?.split('.')[0] || '0');
|
|
63
|
+
|
|
64
|
+
if (osVersion >= 21 && this.bluetoothAdapter.getBluetoothLeScanner) {
|
|
65
|
+
// Android 5.0+ 使用新的扫描 API
|
|
66
|
+
this.startNewScanAPI(resolve, reject);
|
|
67
|
+
} else {
|
|
68
|
+
// 旧版扫描 API
|
|
69
|
+
this.startLegacyScan(resolve, reject);
|
|
70
|
+
}
|
|
71
|
+
// #endif
|
|
72
|
+
|
|
73
|
+
// #ifndef APP-PLUS
|
|
74
|
+
reject(Errors.unsupportedPlatform());
|
|
75
|
+
// #endif
|
|
76
|
+
} catch (error) {
|
|
77
|
+
reject(handlePlatformError(error, 'android'));
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
protected async stopScanInternal(): Promise<void> {
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
try {
|
|
85
|
+
// #ifdef APP-PLUS
|
|
86
|
+
if (this.bluetoothLeScanner && this.scanCallback) {
|
|
87
|
+
this.bluetoothLeScanner.stopScan(this.scanCallback);
|
|
88
|
+
} else if (this.bluetoothAdapter) {
|
|
89
|
+
this.bluetoothAdapter.stopLeScan(this.legacyScanCallback);
|
|
90
|
+
}
|
|
91
|
+
resolve();
|
|
92
|
+
// #endif
|
|
93
|
+
|
|
94
|
+
// #ifndef APP-PLUS
|
|
95
|
+
reject(Errors.unsupportedPlatform());
|
|
96
|
+
// #endif
|
|
97
|
+
} catch (error) {
|
|
98
|
+
reject(handlePlatformError(error, 'android'));
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async checkPermissions(): Promise<boolean> {
|
|
104
|
+
// #ifdef APP-PLUS
|
|
105
|
+
const mainActivity = plus.android.runtimeMainActivity();
|
|
106
|
+
const PackageManager = plus.android.importClass('android.content.pm.PackageManager');
|
|
107
|
+
|
|
108
|
+
const systemInfo = uni.getSystemInfoSync();
|
|
109
|
+
const osVersion = parseInt(systemInfo.system?.split('.')[0] || '0');
|
|
110
|
+
|
|
111
|
+
let permissions: string[];
|
|
112
|
+
if (osVersion >= 12) {
|
|
113
|
+
permissions = [
|
|
114
|
+
'android.permission.BLUETOOTH_SCAN',
|
|
115
|
+
'android.permission.BLUETOOTH_CONNECT',
|
|
116
|
+
'android.permission.ACCESS_FINE_LOCATION',
|
|
117
|
+
];
|
|
118
|
+
} else {
|
|
119
|
+
permissions = [
|
|
120
|
+
'android.permission.BLUETOOTH',
|
|
121
|
+
'android.permission.BLUETOOTH_ADMIN',
|
|
122
|
+
'android.permission.ACCESS_FINE_LOCATION',
|
|
123
|
+
];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
for (const permission of permissions) {
|
|
127
|
+
const result = mainActivity.checkSelfPermission(permission);
|
|
128
|
+
if (result !== PackageManager.PERMISSION_GRANTED) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return true;
|
|
133
|
+
// #endif
|
|
134
|
+
|
|
135
|
+
// #ifndef APP-PLUS
|
|
136
|
+
return false;
|
|
137
|
+
// #endif
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async requestPermissions(): Promise<boolean> {
|
|
141
|
+
// #ifdef APP-PLUS
|
|
142
|
+
return new Promise((resolve) => {
|
|
143
|
+
const systemInfo = uni.getSystemInfoSync();
|
|
144
|
+
const osVersion = parseInt(systemInfo.system?.split('.')[0] || '0');
|
|
145
|
+
|
|
146
|
+
let permissions: string[];
|
|
147
|
+
if (osVersion >= 12) {
|
|
148
|
+
permissions = [
|
|
149
|
+
'android.permission.BLUETOOTH_SCAN',
|
|
150
|
+
'android.permission.BLUETOOTH_CONNECT',
|
|
151
|
+
'android.permission.ACCESS_FINE_LOCATION',
|
|
152
|
+
];
|
|
153
|
+
} else {
|
|
154
|
+
permissions = [
|
|
155
|
+
'android.permission.BLUETOOTH',
|
|
156
|
+
'android.permission.BLUETOOTH_ADMIN',
|
|
157
|
+
'android.permission.ACCESS_FINE_LOCATION',
|
|
158
|
+
];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
uni.requestAndroidPermission(
|
|
162
|
+
permissions[0],
|
|
163
|
+
(result: any) => {
|
|
164
|
+
resolve(result.granted);
|
|
165
|
+
},
|
|
166
|
+
() => {
|
|
167
|
+
resolve(false);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
});
|
|
171
|
+
// #endif
|
|
172
|
+
|
|
173
|
+
// #ifndef APP-PLUS
|
|
174
|
+
return false;
|
|
175
|
+
// #endif
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
onAdapterStateChange(callback: (state: AdapterState) => void): void {
|
|
179
|
+
this.adapterStateListeners.push(callback);
|
|
180
|
+
|
|
181
|
+
// #ifdef APP-PLUS
|
|
182
|
+
if (!this.adapterStateReceiver) {
|
|
183
|
+
const mainActivity = plus.android.runtimeMainActivity();
|
|
184
|
+
const IntentFilter = plus.android.importClass('android.content.IntentFilter');
|
|
185
|
+
const BluetoothAdapter = plus.android.importClass('android.bluetooth.BluetoothAdapter');
|
|
186
|
+
|
|
187
|
+
const filter = new IntentFilter();
|
|
188
|
+
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
|
|
189
|
+
|
|
190
|
+
// 这里简化处理,实际应该创建 BroadcastReceiver
|
|
191
|
+
// 由于 Native.js 限制,建议使用 uni-app 的标准 API 监听状态
|
|
192
|
+
}
|
|
193
|
+
// #endif
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
destroy(): void {
|
|
197
|
+
super.destroy();
|
|
198
|
+
this.bluetoothAdapter = null;
|
|
199
|
+
this.bluetoothLeScanner = null;
|
|
200
|
+
this.scanCallback = null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* 使用新版扫描 API (Android 5.0+)
|
|
205
|
+
*/
|
|
206
|
+
private startNewScanAPI(resolve: () => void, reject: (error: BLEError) => void): void {
|
|
207
|
+
// #ifdef APP-PLUS
|
|
208
|
+
try {
|
|
209
|
+
const ScanSettings = plus.android.importClass('android.bluetooth.le.ScanSettings');
|
|
210
|
+
const ScanFilter = plus.android.importClass('android.bluetooth.le.ScanFilter');
|
|
211
|
+
const ScanCallback = plus.android.importClass('android.bluetooth.le.ScanCallback');
|
|
212
|
+
|
|
213
|
+
this.bluetoothLeScanner = this.bluetoothAdapter.getBluetoothLeScanner();
|
|
214
|
+
|
|
215
|
+
// 构建扫描设置
|
|
216
|
+
const builder = new ScanSettings.Builder();
|
|
217
|
+
|
|
218
|
+
// 设置扫描模式
|
|
219
|
+
const scanMode = this.platformConfig.android?.scanMode || ScanSettings.SCAN_MODE_LOW_LATENCY;
|
|
220
|
+
builder.setScanMode(scanMode);
|
|
221
|
+
|
|
222
|
+
const settings = builder.build();
|
|
223
|
+
|
|
224
|
+
// 构建扫描过滤器
|
|
225
|
+
const filters: any[] = [];
|
|
226
|
+
if (this.options.services && this.options.services.length > 0) {
|
|
227
|
+
// 可以添加服务 UUID 过滤
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// 创建扫描回调
|
|
231
|
+
const self = this;
|
|
232
|
+
this.scanCallback = new ScanCallback({
|
|
233
|
+
onScanResult: (callbackType: number, result: any) => {
|
|
234
|
+
const device = result.getDevice();
|
|
235
|
+
const rssi = result.getRssi();
|
|
236
|
+
const scanRecord = result.getScanRecord();
|
|
237
|
+
|
|
238
|
+
self.handleDeviceFound({
|
|
239
|
+
deviceId: device.getAddress(),
|
|
240
|
+
name: device.getName(),
|
|
241
|
+
RSSI: rssi,
|
|
242
|
+
advertisData: scanRecord ? scanRecord.getBytes() : null,
|
|
243
|
+
});
|
|
244
|
+
},
|
|
245
|
+
onBatchScanResults: (results: any[]) => {
|
|
246
|
+
results.forEach((result) => {
|
|
247
|
+
this.scanCallback.onScanResult(0, result);
|
|
248
|
+
});
|
|
249
|
+
},
|
|
250
|
+
onScanFailed: (errorCode: number) => {
|
|
251
|
+
reject(Errors.scanFailed(`错误码: ${errorCode}`));
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
this.bluetoothLeScanner.startScan(filters, settings, this.scanCallback);
|
|
256
|
+
resolve();
|
|
257
|
+
} catch (error) {
|
|
258
|
+
reject(handlePlatformError(error, 'android'));
|
|
259
|
+
}
|
|
260
|
+
// #endif
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* 使用旧版扫描 API
|
|
265
|
+
*/
|
|
266
|
+
private startLegacyScan(resolve: () => void, reject: (error: BLEError) => void): void {
|
|
267
|
+
// #ifdef APP-PLUS
|
|
268
|
+
try {
|
|
269
|
+
const self = this;
|
|
270
|
+
this.legacyScanCallback = new plus.android.implements('android.bluetooth.BluetoothAdapter.LeScanCallback', {
|
|
271
|
+
onLeScan: (device: any, rssi: number, scanRecord: number[]) => {
|
|
272
|
+
self.handleDeviceFound({
|
|
273
|
+
deviceId: device.getAddress(),
|
|
274
|
+
name: device.getName(),
|
|
275
|
+
RSSI: rssi,
|
|
276
|
+
advertisData: scanRecord,
|
|
277
|
+
});
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
let serviceUuids: string[] | null = null;
|
|
282
|
+
if (this.options.services && this.options.services.length > 0) {
|
|
283
|
+
serviceUuids = this.options.services;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const started = this.bluetoothAdapter.startLeScan(serviceUuids, this.legacyScanCallback);
|
|
287
|
+
|
|
288
|
+
if (started) {
|
|
289
|
+
resolve();
|
|
290
|
+
} else {
|
|
291
|
+
reject(Errors.scanFailed('启动扫描失败'));
|
|
292
|
+
}
|
|
293
|
+
} catch (error) {
|
|
294
|
+
reject(handlePlatformError(error, 'android'));
|
|
295
|
+
}
|
|
296
|
+
// #endif
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private legacyScanCallback: any = null;
|
|
300
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { BaseScanner } from '../core/base-scanner';
|
|
2
|
+
import {
|
|
3
|
+
Platform,
|
|
4
|
+
AdapterState,
|
|
5
|
+
BLEError,
|
|
6
|
+
PlatformConfig,
|
|
7
|
+
} from '../types';
|
|
8
|
+
import { Errors, createError, ErrorCodes, handlePlatformError } from '../utils/errors';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 鸿蒙原生蓝牙扫描器
|
|
12
|
+
* 使用鸿蒙原生 API 进行蓝牙扫描
|
|
13
|
+
*/
|
|
14
|
+
export class HarmonyNativeScanner extends BaseScanner {
|
|
15
|
+
private bluetoothManager: any = null;
|
|
16
|
+
private bleScanner: any = null;
|
|
17
|
+
private scanCallback: any = null;
|
|
18
|
+
|
|
19
|
+
getPlatform(): Platform {
|
|
20
|
+
return Platform.HARMONY;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async init(): Promise<void> {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
try {
|
|
26
|
+
// #ifdef HARMONY
|
|
27
|
+
// 导入鸿蒙蓝牙模块
|
|
28
|
+
const bluetooth = require('@ohos.bluetooth.ble');
|
|
29
|
+
|
|
30
|
+
// 获取蓝牙管理器
|
|
31
|
+
this.bluetoothManager = bluetooth.BLE;
|
|
32
|
+
|
|
33
|
+
if (!this.bluetoothManager) {
|
|
34
|
+
reject(Errors.adapterNotAvailable());
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 检查蓝牙是否开启
|
|
39
|
+
const state = this.bluetoothManager.getState();
|
|
40
|
+
if (state !== 2) { // STATE_ON = 2
|
|
41
|
+
reject(Errors.bluetoothDisabled());
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this.initialized = true;
|
|
46
|
+
resolve();
|
|
47
|
+
// #endif
|
|
48
|
+
|
|
49
|
+
// #ifndef HARMONY
|
|
50
|
+
reject(createError(ErrorCodes.UNSUPPORTED_PLATFORM, '非鸿蒙环境不支持原生鸿蒙扫描'));
|
|
51
|
+
// #endif
|
|
52
|
+
} catch (error) {
|
|
53
|
+
reject(handlePlatformError(error, 'harmony'));
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected async startScanInternal(): Promise<void> {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
try {
|
|
61
|
+
// #ifdef HARMONY
|
|
62
|
+
const bluetooth = require('@ohos.bluetooth.ble');
|
|
63
|
+
|
|
64
|
+
// 构建扫描过滤器
|
|
65
|
+
const filters: any[] = [];
|
|
66
|
+
|
|
67
|
+
if (this.options.services && this.options.services.length > 0) {
|
|
68
|
+
this.options.services.forEach((uuid) => {
|
|
69
|
+
const filter = {
|
|
70
|
+
serviceUuid: uuid,
|
|
71
|
+
};
|
|
72
|
+
filters.push(filter);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (this.options.nameFilter) {
|
|
77
|
+
const names = Array.isArray(this.options.nameFilter)
|
|
78
|
+
? this.options.nameFilter
|
|
79
|
+
: [this.options.nameFilter];
|
|
80
|
+
|
|
81
|
+
names.forEach((name) => {
|
|
82
|
+
if (typeof name === 'string') {
|
|
83
|
+
filters.push({ deviceName: name });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 构建扫描配置
|
|
89
|
+
const scanOptions = {
|
|
90
|
+
interval: 0,
|
|
91
|
+
dutyMode: bluetooth.ScanDuty.SCAN_MODE_LOW_LATENCY,
|
|
92
|
+
matchMode: bluetooth.MatchMode.MATCH_MODE_AGGRESSIVE,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// 创建扫描回调
|
|
96
|
+
const self = this;
|
|
97
|
+
this.scanCallback = {
|
|
98
|
+
onScanResult: (result: any) => {
|
|
99
|
+
const device = result.device;
|
|
100
|
+
const data = result.data;
|
|
101
|
+
const rssi = result.rssi;
|
|
102
|
+
|
|
103
|
+
self.handleDeviceFound({
|
|
104
|
+
deviceId: device.deviceId,
|
|
105
|
+
name: device.deviceName,
|
|
106
|
+
RSSI: rssi,
|
|
107
|
+
advertisData: data,
|
|
108
|
+
serviceUuids: result.serviceUuids,
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
onScanFailed: (errorCode: number) => {
|
|
112
|
+
console.error('扫描失败:', errorCode);
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// 开始扫描
|
|
117
|
+
this.bluetoothManager.startBLEScan(filters, scanOptions, this.scanCallback);
|
|
118
|
+
resolve();
|
|
119
|
+
// #endif
|
|
120
|
+
|
|
121
|
+
// #ifndef HARMONY
|
|
122
|
+
reject(Errors.unsupportedPlatform());
|
|
123
|
+
// #endif
|
|
124
|
+
} catch (error) {
|
|
125
|
+
reject(handlePlatformError(error, 'harmony'));
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
protected async stopScanInternal(): Promise<void> {
|
|
131
|
+
return new Promise((resolve, reject) => {
|
|
132
|
+
try {
|
|
133
|
+
// #ifdef HARMONY
|
|
134
|
+
if (this.bluetoothManager) {
|
|
135
|
+
this.bluetoothManager.stopBLEScan();
|
|
136
|
+
}
|
|
137
|
+
resolve();
|
|
138
|
+
// #endif
|
|
139
|
+
|
|
140
|
+
// #ifndef HARMONY
|
|
141
|
+
reject(Errors.unsupportedPlatform());
|
|
142
|
+
// #endif
|
|
143
|
+
} catch (error) {
|
|
144
|
+
reject(handlePlatformError(error, 'harmony'));
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async checkPermissions(): Promise<boolean> {
|
|
150
|
+
// #ifdef HARMONY
|
|
151
|
+
try {
|
|
152
|
+
const atManager = require('@ohos.abilityAccessCtrl').createAtManager();
|
|
153
|
+
const tokenId = require('@ohos.process').process.accessTokenId;
|
|
154
|
+
|
|
155
|
+
const permissions = [
|
|
156
|
+
'ohos.permission.ACCESS_BLUETOOTH',
|
|
157
|
+
'ohos.permission.LOCATION',
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
for (const permission of permissions) {
|
|
161
|
+
const result = await atManager.verifyAccessToken(tokenId, permission);
|
|
162
|
+
if (result !== 0) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error('检查权限失败:', error);
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
// #endif
|
|
172
|
+
|
|
173
|
+
// #ifndef HARMONY
|
|
174
|
+
return false;
|
|
175
|
+
// #endif
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async requestPermissions(): Promise<boolean> {
|
|
179
|
+
// #ifdef HARMONY
|
|
180
|
+
try {
|
|
181
|
+
const atManager = require('@ohos.abilityAccessCtrl').createAtManager();
|
|
182
|
+
const context = getContext(this);
|
|
183
|
+
|
|
184
|
+
const permissions = [
|
|
185
|
+
'ohos.permission.ACCESS_BLUETOOTH',
|
|
186
|
+
'ohos.permission.LOCATION',
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
const result = await atManager.requestPermissionsFromUser(context, permissions);
|
|
190
|
+
return result.authResults.every((authResult: number) => authResult === 0);
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('请求权限失败:', error);
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
// #endif
|
|
196
|
+
|
|
197
|
+
// #ifndef HARMONY
|
|
198
|
+
return false;
|
|
199
|
+
// #endif
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
onAdapterStateChange(callback: (state: AdapterState) => void): void {
|
|
203
|
+
this.adapterStateListeners.push(callback);
|
|
204
|
+
|
|
205
|
+
// #ifdef HARMONY
|
|
206
|
+
try {
|
|
207
|
+
const bluetooth = require('@ohos.bluetooth.ble');
|
|
208
|
+
|
|
209
|
+
// 监听蓝牙状态变化
|
|
210
|
+
bluetooth.on('stateChange', (data: any) => {
|
|
211
|
+
this.emitAdapterStateChange({
|
|
212
|
+
available: data.state === 2, // STATE_ON = 2
|
|
213
|
+
discovering: this.state === 'scanning',
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.error('监听状态变化失败:', error);
|
|
218
|
+
}
|
|
219
|
+
// #endif
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
destroy(): void {
|
|
223
|
+
super.destroy();
|
|
224
|
+
|
|
225
|
+
// #ifdef HARMONY
|
|
226
|
+
try {
|
|
227
|
+
const bluetooth = require('@ohos.bluetooth.ble');
|
|
228
|
+
|
|
229
|
+
// 停止扫描
|
|
230
|
+
if (this.bluetoothManager) {
|
|
231
|
+
this.bluetoothManager.stopBLEScan();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 移除状态监听
|
|
235
|
+
bluetooth.off('stateChange');
|
|
236
|
+
} catch (error) {
|
|
237
|
+
console.error('销毁失败:', error);
|
|
238
|
+
}
|
|
239
|
+
// #endif
|
|
240
|
+
|
|
241
|
+
this.bluetoothManager = null;
|
|
242
|
+
this.scanCallback = null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 获取鸿蒙蓝牙适配器状态
|
|
247
|
+
*/
|
|
248
|
+
async getAdapterState(): Promise<AdapterState> {
|
|
249
|
+
return new Promise((resolve, reject) => {
|
|
250
|
+
// #ifdef HARMONY
|
|
251
|
+
try {
|
|
252
|
+
const state = this.bluetoothManager.getState();
|
|
253
|
+
resolve({
|
|
254
|
+
available: state === 2,
|
|
255
|
+
discovering: this.state === 'scanning',
|
|
256
|
+
});
|
|
257
|
+
} catch (error) {
|
|
258
|
+
reject(handlePlatformError(error, 'harmony'));
|
|
259
|
+
}
|
|
260
|
+
// #endif
|
|
261
|
+
|
|
262
|
+
// #ifndef HARMONY
|
|
263
|
+
reject(Errors.unsupportedPlatform());
|
|
264
|
+
// #endif
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|