@ruhiverse/thermal-printer-plugin 1.0.6 → 1.0.8

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.
@@ -265,18 +265,37 @@ public class ThermalPrinterPlugin extends Plugin {
265
265
  try {
266
266
  BluetoothConnection[] bluetoothPrinters = (new BluetoothPrintersConnections()).getList();
267
267
  JSArray printers = new JSArray();
268
- if (bluetoothPrinters != null) {
268
+
269
+ if (bluetoothPrinters != null && bluetoothPrinters.length > 0) {
269
270
  for (BluetoothConnection printer : bluetoothPrinters) {
270
- JSObject printerObj = new JSObject();
271
- printerObj.put("name", printer.getDevice().getName());
272
- printerObj.put("address", printer.getDevice().getAddress());
273
- printers.put(printerObj);
271
+ try {
272
+ JSObject printerObj = new JSObject();
273
+ String name = printer.getDevice().getName();
274
+ String address = printer.getDevice().getAddress();
275
+
276
+ // Handle null/empty names
277
+ if (name == null || name.isEmpty()) {
278
+ name = "Unknown Device";
279
+ }
280
+
281
+ printerObj.put("name", name);
282
+ printerObj.put("address", address != null ? address : "");
283
+ printers.put(printerObj);
284
+
285
+ Log.d(TAG, "Found Bluetooth printer: " + name + " (" + address + ")");
286
+ } catch (Exception e) {
287
+ Log.e(TAG, "Error processing printer: " + e.getMessage());
288
+ }
274
289
  }
290
+ } else {
291
+ Log.d(TAG, "No paired Bluetooth printers found. Make sure printers are paired in Android Settings.");
275
292
  }
293
+
276
294
  JSObject ret = new JSObject();
277
295
  ret.put("printers", printers);
278
296
  call.resolve(ret);
279
297
  } catch (Exception e) {
298
+ Log.e(TAG, "Error listing Bluetooth printers: " + e.getMessage(), e);
280
299
  call.reject("Error listing Bluetooth printers: " + e.getMessage());
281
300
  }
282
301
  }
@@ -288,18 +307,37 @@ public class ThermalPrinterPlugin extends Plugin {
288
307
  try {
289
308
  UsbConnection[] usbPrinters = (new UsbPrintersConnections(getContext())).getList();
290
309
  JSArray printers = new JSArray();
291
- if (usbPrinters != null) {
310
+
311
+ if (usbPrinters != null && usbPrinters.length > 0) {
292
312
  for (UsbConnection printer : usbPrinters) {
293
- JSObject printerObj = new JSObject();
294
- printerObj.put("name", printer.getDevice().getDeviceName());
295
- printerObj.put("address", printer.getDevice().getSerialNumber()); // Using serial number as address for USB
296
- printers.put(printerObj);
313
+ try {
314
+ JSObject printerObj = new JSObject();
315
+ String name = printer.getDevice().getDeviceName();
316
+ String serial = printer.getDevice().getSerialNumber();
317
+
318
+ // Handle null/empty names
319
+ if (name == null || name.isEmpty()) {
320
+ name = "USB Printer";
321
+ }
322
+
323
+ printerObj.put("name", name);
324
+ printerObj.put("address", serial != null ? serial : printer.getDevice().getDeviceId() + "");
325
+ printers.put(printerObj);
326
+
327
+ Log.d(TAG, "Found USB printer: " + name + " (ID: " + printer.getDevice().getDeviceId() + ")");
328
+ } catch (Exception e) {
329
+ Log.e(TAG, "Error processing USB printer: " + e.getMessage());
330
+ }
297
331
  }
332
+ } else {
333
+ Log.d(TAG, "No USB printers found. Make sure printer is connected via USB.");
298
334
  }
335
+
299
336
  JSObject ret = new JSObject();
300
337
  ret.put("printers", printers);
301
338
  call.resolve(ret);
302
339
  } catch (Exception e) {
340
+ Log.e(TAG, "Error listing USB printers: " + e.getMessage(), e);
303
341
  call.reject("Error listing USB printers: " + e.getMessage());
304
342
  }
305
343
  }
@@ -26,6 +26,7 @@ public class ThermalPrinterPlugin: CAPPlugin, CBCentralManagerDelegate, CBPeriph
26
26
  private var printCompletion: ((Bool, String?) -> Void)?
27
27
  private var printData: Data?
28
28
  private var targetPrintAddress: String?
29
+ private var listPrintersCall: CAPPluginCall?
29
30
 
30
31
  // Common BLE service UUIDs for thermal printers (Serial Port Profile)
31
32
  // Note: We scan with nil services to find all peripherals, then filter by name
@@ -282,86 +283,163 @@ public class ThermalPrinterPlugin: CAPPlugin, CBCentralManagerDelegate, CBPeriph
282
283
  }
283
284
 
284
285
  @objc func listBluetoothPrinters(_ call: CAPPluginCall) {
286
+ print("ThermalPrinter: listBluetoothPrinters called")
285
287
  var printers: [[String: String]] = []
286
288
 
287
289
  // First, get MFi/ExternalAccessory printers
288
290
  let manager = EAAccessoryManager.shared()
289
291
  let accessories = manager.connectedAccessories
290
292
 
293
+ print("ThermalPrinter: Found \(accessories.count) ExternalAccessory devices")
294
+
291
295
  let mfiPrinters: [[String: String]] = accessories.compactMap { accessory in
292
296
  guard accessory.protocolStrings.contains(where: { supportedPrinterProtocols.contains($0) }) else {
293
297
  return nil
294
298
  }
299
+ print("ThermalPrinter: Found MFi printer: \(accessory.name)")
295
300
  return [
296
301
  "name": accessory.name,
297
302
  "address": accessory.serialNumber.isEmpty ? "\(accessory.connectionID)" : accessory.serialNumber,
298
303
  ]
299
304
  }
300
305
  printers.append(contentsOf: mfiPrinters)
306
+ print("ThermalPrinter: Found \(mfiPrinters.count) MFi printers")
301
307
 
302
308
  // Then scan for BLE printers
303
309
  discoveredPeripherals.removeAll()
310
+ listPrintersCall = call
304
311
 
312
+ // Initialize central manager if needed
305
313
  if centralManager == nil {
306
- centralManager = CBCentralManager(delegate: self, queue: nil)
314
+ print("ThermalPrinter: Initializing CBCentralManager")
315
+ centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
307
316
  }
308
317
 
309
318
  guard let centralManager = centralManager else {
319
+ print("ThermalPrinter: Central manager is nil, returning \(printers.count) printers")
310
320
  call.resolve(["printers": printers])
311
321
  return
312
322
  }
313
323
 
314
- // Wait a bit for central manager to be ready, then scan
315
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
316
- if centralManager.state == .poweredOn {
317
- // Scan for all peripherals (we'll filter by name/characteristics)
318
- centralManager.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
319
-
320
- // Stop scanning after 5 seconds
321
- DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
322
- centralManager.stopScan()
323
-
324
- // Add discovered BLE printers
325
- let blePrinters: [[String: String]] = self.discoveredPeripherals.compactMap { peripheral in
326
- guard let name = peripheral.name, !name.isEmpty else {
327
- return nil
328
- }
329
- // Filter for common printer names or accept all if we found them
330
- let printerKeywords = ["printer", "print", "thermal", "pos", "epson", "star", "receipt"]
331
- let isLikelyPrinter = printerKeywords.contains { keyword in
332
- name.lowercased().contains(keyword)
333
- }
334
-
335
- // Include if it's a likely printer or if we have no other printers found
336
- if isLikelyPrinter || printers.isEmpty {
337
- return [
338
- "name": name,
339
- "address": peripheral.identifier.uuidString,
340
- ]
341
- }
342
- return nil
343
- }
344
-
345
- printers.append(contentsOf: blePrinters)
346
- call.resolve(["printers": printers])
347
- }
348
- } else {
349
- // Bluetooth not available, return what we have
350
- call.resolve(["printers": printers])
324
+ print("ThermalPrinter: Bluetooth state: \(centralManager.state.rawValue)")
325
+
326
+ // Check Bluetooth state
327
+ switch centralManager.state {
328
+ case .poweredOn:
329
+ // Start scanning immediately
330
+ print("ThermalPrinter: Bluetooth powered on, starting scan")
331
+ startBLEScan(for: call, existingPrinters: printers)
332
+ case .poweredOff:
333
+ print("ThermalPrinter: Bluetooth powered off, returning \(printers.count) printers")
334
+ call.resolve(["printers": printers])
335
+ case .unauthorized:
336
+ print("ThermalPrinter: Bluetooth unauthorized")
337
+ call.reject("Bluetooth access denied. Please enable Bluetooth permissions in Settings.")
338
+ case .unsupported:
339
+ print("ThermalPrinter: Bluetooth unsupported")
340
+ call.reject("Bluetooth is not supported on this device.")
341
+ case .resetting, .unknown:
342
+ print("ThermalPrinter: Bluetooth state unknown/resetting, waiting for update")
343
+ // Wait for state update
344
+ // The state will be updated via centralManagerDidUpdateState
345
+ break
346
+ @unknown default:
347
+ print("ThermalPrinter: Unknown Bluetooth state, returning \(printers.count) printers")
348
+ call.resolve(["printers": printers])
349
+ }
350
+ }
351
+
352
+ private func startBLEScan(for call: CAPPluginCall, existingPrinters: [[String: String]]) {
353
+ guard let centralManager = centralManager else {
354
+ call.resolve(["printers": existingPrinters])
355
+ return
356
+ }
357
+
358
+ guard centralManager.state == .poweredOn else {
359
+ call.resolve(["printers": existingPrinters])
360
+ return
361
+ }
362
+
363
+ // Clear previous discoveries
364
+ discoveredPeripherals.removeAll()
365
+
366
+ // Scan for all peripherals
367
+ print("ThermalPrinter: Starting BLE scan...")
368
+ centralManager.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
369
+
370
+ // Stop scanning after 8 seconds (increased from 5 to give more time)
371
+ DispatchQueue.main.asyncAfter(deadline: .now() + 8.0) {
372
+ centralManager.stopScan()
373
+ print("ThermalPrinter: Stopped BLE scan. Found \(self.discoveredPeripherals.count) peripherals")
374
+
375
+ var printers = existingPrinters
376
+
377
+ // Add discovered BLE printers - return all devices, even without names
378
+ let blePrinters: [[String: String]] = self.discoveredPeripherals.compactMap { peripheral in
379
+ // Include all peripherals, even if they don't have names
380
+ // Some printers don't advertise names until connected
381
+ let name = peripheral.name ?? "Unknown Device"
382
+ return [
383
+ "name": name,
384
+ "address": peripheral.identifier.uuidString,
385
+ ]
351
386
  }
387
+
388
+ print("ThermalPrinter: Returning \(blePrinters.count) BLE printers")
389
+ printers.append(contentsOf: blePrinters)
390
+ call.resolve(["printers": printers])
391
+ self.listPrintersCall = nil
352
392
  }
353
393
  }
354
394
 
355
395
  // MARK: - CBCentralManagerDelegate
356
396
 
357
397
  public func centralManagerDidUpdateState(_ central: CBCentralManager) {
358
- // State updated, scanning will start when ready
398
+ print("ThermalPrinter: Central manager state updated: \(central.state.rawValue)")
399
+
400
+ // If we're waiting to list printers, start scanning now
401
+ if let call = listPrintersCall {
402
+ switch central.state {
403
+ case .poweredOn:
404
+ print("ThermalPrinter: Bluetooth now powered on, starting scan")
405
+ // Get existing MFi printers first
406
+ let manager = EAAccessoryManager.shared()
407
+ let accessories = manager.connectedAccessories
408
+ let mfiPrinters: [[String: String]] = accessories.compactMap { accessory in
409
+ guard accessory.protocolStrings.contains(where: { supportedPrinterProtocols.contains($0) }) else {
410
+ return nil
411
+ }
412
+ return [
413
+ "name": accessory.name,
414
+ "address": accessory.serialNumber.isEmpty ? "\(accessory.connectionID)" : accessory.serialNumber,
415
+ ]
416
+ }
417
+ startBLEScan(for: call, existingPrinters: mfiPrinters)
418
+ case .poweredOff:
419
+ print("ThermalPrinter: Bluetooth powered off")
420
+ call.resolve(["printers": []])
421
+ listPrintersCall = nil
422
+ case .unauthorized:
423
+ print("ThermalPrinter: Bluetooth unauthorized")
424
+ call.reject("Bluetooth access denied. Please enable Bluetooth permissions in Settings.")
425
+ listPrintersCall = nil
426
+ case .unsupported:
427
+ print("ThermalPrinter: Bluetooth unsupported")
428
+ call.reject("Bluetooth is not supported on this device.")
429
+ listPrintersCall = nil
430
+ default:
431
+ print("ThermalPrinter: Bluetooth state: \(central.state.rawValue)")
432
+ break
433
+ }
434
+ }
359
435
  }
360
436
 
361
437
  public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
362
438
  // Avoid duplicates
363
439
  if !discoveredPeripherals.contains(where: { $0.identifier == peripheral.identifier }) {
364
440
  discoveredPeripherals.append(peripheral)
441
+ let name = peripheral.name ?? "Unknown"
442
+ print("ThermalPrinter: Discovered peripheral: \(name) (\(peripheral.identifier.uuidString))")
365
443
  }
366
444
 
367
445
  // If we're looking for a specific printer to print to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruhiverse/thermal-printer-plugin",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Capacitor plugin for thermal printing via USB and Bluetooth",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",