@ruhiverse/thermal-printer-plugin 1.0.11 → 1.0.15
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/README.md
CHANGED
|
@@ -136,22 +136,28 @@ Returns a list of connected USB printers.
|
|
|
136
136
|
|
|
137
137
|
## Platform Support
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
| Platform | Bluetooth | USB | Printer Discovery |
|
|
140
|
+
| -------- | --------- | --- | ----------------- |
|
|
141
|
+
| Android | ✅ | ✅ | ✅ (paired + scan) |
|
|
142
|
+
| iOS | ✅ (MFi & BLE) | ✅ (MFi only) | ✅ (MFi + BLE scan) |
|
|
143
|
+
| Web | ❌ | ❌ | ❌ |
|
|
142
144
|
|
|
143
145
|
## Android Setup
|
|
144
146
|
|
|
145
147
|
### Permissions
|
|
146
148
|
|
|
147
|
-
The plugin
|
|
149
|
+
The plugin declares the following permissions in its `AndroidManifest.xml`:
|
|
148
150
|
|
|
149
151
|
- `BLUETOOTH`
|
|
150
152
|
- `BLUETOOTH_ADMIN`
|
|
151
153
|
- `BLUETOOTH_CONNECT` (Android 12+)
|
|
152
154
|
- `BLUETOOTH_SCAN` (Android 12+)
|
|
155
|
+
- `ACCESS_FINE_LOCATION` (required for Bluetooth scanning on Android 6-11)
|
|
156
|
+
- `ACCESS_COARSE_LOCATION`
|
|
153
157
|
- `USB_PERMISSION`
|
|
154
158
|
|
|
159
|
+
The plugin automatically requests Bluetooth permissions at runtime when needed.
|
|
160
|
+
|
|
155
161
|
### USB Printing
|
|
156
162
|
|
|
157
163
|
1. Connect your thermal printer via USB
|
|
@@ -160,20 +166,21 @@ The plugin automatically requests the following permissions:
|
|
|
160
166
|
|
|
161
167
|
### Bluetooth Printing
|
|
162
168
|
|
|
163
|
-
1. Pair your thermal printer with the device via Bluetooth
|
|
164
|
-
2.
|
|
169
|
+
1. Pair your thermal printer with the device via **Android Settings > Bluetooth**
|
|
170
|
+
2. Use `listBluetoothPrinters()` to get the list of paired devices
|
|
171
|
+
3. Use `printByBluetooth()` with the printer's `address` to print, or omit `address` to use the first paired printer
|
|
165
172
|
|
|
166
173
|
## iOS Setup
|
|
167
174
|
|
|
168
|
-
### Info.plist Configuration
|
|
175
|
+
### Required Info.plist Configuration
|
|
169
176
|
|
|
170
|
-
Add the following to your app's `Info.plist
|
|
177
|
+
Add the following keys to your app's `Info.plist`. **Without these, Bluetooth will not work on iOS.**
|
|
171
178
|
|
|
172
179
|
```xml
|
|
173
180
|
<key>NSBluetoothAlwaysUsageDescription</key>
|
|
174
|
-
<string>This app needs Bluetooth access to connect to thermal printers
|
|
181
|
+
<string>This app needs Bluetooth access to connect to thermal printers.</string>
|
|
175
182
|
<key>NSBluetoothPeripheralUsageDescription</key>
|
|
176
|
-
<string>This app needs Bluetooth access to connect to thermal printers
|
|
183
|
+
<string>This app needs Bluetooth access to connect to thermal printers.</string>
|
|
177
184
|
<key>UISupportedExternalAccessoryProtocols</key>
|
|
178
185
|
<array>
|
|
179
186
|
<string>com.epson.escpos</string>
|
|
@@ -181,72 +188,70 @@ Add the following to your app's `Info.plist`:
|
|
|
181
188
|
</array>
|
|
182
189
|
```
|
|
183
190
|
|
|
184
|
-
|
|
191
|
+
| Key | Required | Description |
|
|
192
|
+
| --- | -------- | ----------- |
|
|
193
|
+
| `NSBluetoothAlwaysUsageDescription` | **Yes** | iOS will silently block Bluetooth access without this. Triggers the permission dialog. |
|
|
194
|
+
| `NSBluetoothPeripheralUsageDescription` | **Yes** | Required for connecting to Bluetooth peripherals (iOS 12 and earlier). |
|
|
195
|
+
| `UISupportedExternalAccessoryProtocols` | **Yes** (for MFi printers) | Lists the protocol strings your printer supports. Update with your printer's protocols. |
|
|
185
196
|
|
|
186
|
-
|
|
197
|
+
### iOS Bluetooth Printing
|
|
187
198
|
|
|
188
|
-
|
|
199
|
+
The plugin supports two types of Bluetooth connections on iOS:
|
|
189
200
|
|
|
190
|
-
|
|
201
|
+
**MFi / ExternalAccessory printers (classic Bluetooth):**
|
|
202
|
+
- Requires the printer to be MFi-certified (Made for iPhone)
|
|
203
|
+
- Uses the ExternalAccessory framework
|
|
204
|
+
- Printer must be paired in iOS Settings > Bluetooth
|
|
205
|
+
- Protocol strings must be listed in `UISupportedExternalAccessoryProtocols`
|
|
191
206
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
207
|
+
**BLE printers (Bluetooth Low Energy):**
|
|
208
|
+
- Uses CoreBluetooth framework
|
|
209
|
+
- Discovered via BLE scanning (4-second scan)
|
|
210
|
+
- Use the `address` from `listBluetoothPrinters()` when calling `printByBluetooth()`
|
|
196
211
|
|
|
197
|
-
|
|
212
|
+
### iOS USB Printing
|
|
198
213
|
|
|
199
|
-
|
|
200
|
-
cd /path/to/milkwala/project
|
|
201
|
-
npm link @ruhiverse/thermal-printer-plugin
|
|
202
|
-
npx cap sync
|
|
203
|
-
```
|
|
214
|
+
USB printing on iOS requires MFi (Made for iPhone) certification for the printer. The printer is accessed through the ExternalAccessory framework.
|
|
204
215
|
|
|
205
|
-
|
|
216
|
+
### iOS Troubleshooting
|
|
206
217
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
```
|
|
218
|
+
| Issue | Solution |
|
|
219
|
+
| ----- | -------- |
|
|
220
|
+
| `listBluetoothPrinters()` returns empty | Make sure `NSBluetoothAlwaysUsageDescription` is in your Info.plist and Bluetooth permission is granted |
|
|
221
|
+
| Printer not found (MFi) | Verify the printer's protocol string is listed in `UISupportedExternalAccessoryProtocols` |
|
|
222
|
+
| Printer not found (BLE) | Ensure the printer is powered on and in range. BLE scan runs for 4 seconds |
|
|
223
|
+
| Permission dialog not showing | Delete and reinstall the app to reset permissions |
|
|
214
224
|
|
|
215
|
-
|
|
225
|
+
## Local Development
|
|
216
226
|
|
|
217
|
-
|
|
227
|
+
### Testing Locally Before Publishing
|
|
218
228
|
|
|
219
|
-
|
|
220
|
-
cd /path/to/milkwala/project
|
|
221
|
-
npm install /Users/apple/Desktop/ionic/workspace/plugin/thermal-printer-plugin
|
|
222
|
-
npx cap sync
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
## Publishing to npm
|
|
226
|
-
|
|
227
|
-
1. **Login to npm (if not already logged in):**
|
|
229
|
+
1. **Link the plugin locally:**
|
|
228
230
|
|
|
229
231
|
```bash
|
|
230
|
-
|
|
231
|
-
|
|
232
|
+
cd path/to/thermal-printer-plugin
|
|
233
|
+
npm link
|
|
232
234
|
```
|
|
233
235
|
|
|
234
|
-
2. **
|
|
236
|
+
2. **In your Ionic/Capacitor project:**
|
|
235
237
|
|
|
236
238
|
```bash
|
|
237
|
-
|
|
239
|
+
cd path/to/your-project
|
|
240
|
+
npm link @ruhiverse/thermal-printer-plugin
|
|
241
|
+
npx cap sync
|
|
238
242
|
```
|
|
239
243
|
|
|
240
|
-
3. **
|
|
244
|
+
3. **Build and test:**
|
|
241
245
|
|
|
242
246
|
```bash
|
|
243
|
-
|
|
247
|
+
npx cap run android
|
|
248
|
+
npx cap run ios
|
|
244
249
|
```
|
|
245
250
|
|
|
246
|
-
|
|
251
|
+
### Alternative: Install from local path
|
|
247
252
|
|
|
248
253
|
```bash
|
|
249
|
-
npm install
|
|
254
|
+
npm install path/to/thermal-printer-plugin
|
|
250
255
|
npx cap sync
|
|
251
256
|
```
|
|
252
257
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
package com.ruhiverse.thermalprinter;
|
|
2
2
|
|
|
3
|
-
import android.app.AlertDialog;
|
|
4
|
-
import android.app.ProgressDialog;
|
|
5
3
|
import android.content.Context;
|
|
6
4
|
import android.os.AsyncTask;
|
|
7
5
|
|
|
@@ -28,7 +26,6 @@ public abstract class AsyncEscPosPrint extends AsyncTask<AsyncEscPosPrinter, Int
|
|
|
28
26
|
protected final static int PROGRESS_PRINTING = 3;
|
|
29
27
|
protected final static int PROGRESS_PRINTED = 4;
|
|
30
28
|
|
|
31
|
-
protected ProgressDialog dialog;
|
|
32
29
|
protected WeakReference<Context> weakContext;
|
|
33
30
|
protected OnPrintFinished onPrintFinished;
|
|
34
31
|
|
|
@@ -95,91 +92,14 @@ public abstract class AsyncEscPosPrint extends AsyncTask<AsyncEscPosPrinter, Int
|
|
|
95
92
|
}
|
|
96
93
|
|
|
97
94
|
protected void onPreExecute() {
|
|
98
|
-
|
|
99
|
-
Context context = weakContext.get();
|
|
100
|
-
|
|
101
|
-
if (context == null) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
this.dialog = new ProgressDialog(context);
|
|
106
|
-
this.dialog.setTitle("Printing in progress...");
|
|
107
|
-
this.dialog.setMessage("...");
|
|
108
|
-
this.dialog.setProgressNumberFormat("%1d / %2d");
|
|
109
|
-
this.dialog.setCancelable(false);
|
|
110
|
-
this.dialog.setIndeterminate(false);
|
|
111
|
-
this.dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
|
112
|
-
this.dialog.show();
|
|
113
|
-
}
|
|
95
|
+
// No UI — progress is handled silently
|
|
114
96
|
}
|
|
115
97
|
|
|
116
98
|
protected void onProgressUpdate(Integer... progress) {
|
|
117
|
-
|
|
118
|
-
case AsyncEscPosPrint.PROGRESS_CONNECTING:
|
|
119
|
-
this.dialog.setMessage("Connecting printer...");
|
|
120
|
-
break;
|
|
121
|
-
case AsyncEscPosPrint.PROGRESS_CONNECTED:
|
|
122
|
-
this.dialog.setMessage("Printer is connected...");
|
|
123
|
-
break;
|
|
124
|
-
case AsyncEscPosPrint.PROGRESS_PRINTING:
|
|
125
|
-
this.dialog.setMessage("Printer is printing...");
|
|
126
|
-
break;
|
|
127
|
-
case AsyncEscPosPrint.PROGRESS_PRINTED:
|
|
128
|
-
this.dialog.setMessage("Printer has finished...");
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
this.dialog.setProgress(progress[0]);
|
|
132
|
-
this.dialog.setMax(4);
|
|
99
|
+
// No UI — progress is handled silently
|
|
133
100
|
}
|
|
134
101
|
|
|
135
102
|
protected void onPostExecute(PrinterStatus result) {
|
|
136
|
-
this.dialog.dismiss();
|
|
137
|
-
this.dialog = null;
|
|
138
|
-
|
|
139
|
-
Context context = weakContext.get();
|
|
140
|
-
|
|
141
|
-
if (context == null) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
switch (result.getPrinterStatus()) {
|
|
146
|
-
case AsyncEscPosPrint.FINISH_SUCCESS:
|
|
147
|
-
new AlertDialog.Builder(context)
|
|
148
|
-
.setTitle("Success")
|
|
149
|
-
.setMessage("Print completed successfully!")
|
|
150
|
-
.show();
|
|
151
|
-
break;
|
|
152
|
-
case AsyncEscPosPrint.FINISH_NO_PRINTER:
|
|
153
|
-
new AlertDialog.Builder(context)
|
|
154
|
-
.setTitle("No printer")
|
|
155
|
-
.setMessage("The application can't find any printer connected.")
|
|
156
|
-
.show();
|
|
157
|
-
break;
|
|
158
|
-
case AsyncEscPosPrint.FINISH_PRINTER_DISCONNECTED:
|
|
159
|
-
new AlertDialog.Builder(context)
|
|
160
|
-
.setTitle("Broken connection")
|
|
161
|
-
.setMessage("Unable to connect the printer.")
|
|
162
|
-
.show();
|
|
163
|
-
break;
|
|
164
|
-
case AsyncEscPosPrint.FINISH_PARSER_ERROR:
|
|
165
|
-
new AlertDialog.Builder(context)
|
|
166
|
-
.setTitle("Invalid formatted text")
|
|
167
|
-
.setMessage("It seems to be an invalid syntax problem.")
|
|
168
|
-
.show();
|
|
169
|
-
break;
|
|
170
|
-
case AsyncEscPosPrint.FINISH_ENCODING_ERROR:
|
|
171
|
-
new AlertDialog.Builder(context)
|
|
172
|
-
.setTitle("Bad selected encoding")
|
|
173
|
-
.setMessage("The selected encoding character returning an error.")
|
|
174
|
-
.show();
|
|
175
|
-
break;
|
|
176
|
-
case AsyncEscPosPrint.FINISH_BARCODE_ERROR:
|
|
177
|
-
new AlertDialog.Builder(context)
|
|
178
|
-
.setTitle("Invalid barcode")
|
|
179
|
-
.setMessage("Data send to be converted to barcode or QR code seems to be invalid.")
|
|
180
|
-
.show();
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
103
|
if(this.onPrintFinished != null) {
|
|
184
104
|
if (result.getPrinterStatus() == AsyncEscPosPrint.FINISH_SUCCESS) {
|
|
185
105
|
this.onPrintFinished.onSuccess(result.getAsyncEscPosPrinter());
|
package/dist/docs.json
CHANGED
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"name": "listBluetoothPrinters",
|
|
56
|
-
"signature": "() => Promise<{ name: string; address: string; }[]>",
|
|
56
|
+
"signature": "() => Promise<{ printers: { name: string; address: string; }[]; }>",
|
|
57
57
|
"parameters": [],
|
|
58
|
-
"returns": "Promise<{ name: string; address: string; }[]>",
|
|
58
|
+
"returns": "Promise<{ printers: { name: string; address: string; }[]; }>",
|
|
59
59
|
"tags": [],
|
|
60
60
|
"docs": "Get list of paired Bluetooth printers",
|
|
61
61
|
"complexTypes": [],
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
"name": "listUsbPrinters",
|
|
66
|
-
"signature": "() => Promise<{ name: string; address: string; }[]>",
|
|
66
|
+
"signature": "() => Promise<{ printers: { name: string; address: string; }[]; }>",
|
|
67
67
|
"parameters": [],
|
|
68
|
-
"returns": "Promise<{ name: string; address: string; }[]>",
|
|
68
|
+
"returns": "Promise<{ printers: { name: string; address: string; }[]; }>",
|
|
69
69
|
"tags": [],
|
|
70
70
|
"docs": "Get list of connected USB printers",
|
|
71
71
|
"complexTypes": [],
|
|
@@ -13,16 +13,20 @@ export interface ThermalPrinterPlugin {
|
|
|
13
13
|
* Get list of paired Bluetooth printers
|
|
14
14
|
*/
|
|
15
15
|
listBluetoothPrinters(): Promise<{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
printers: {
|
|
17
|
+
name: string;
|
|
18
|
+
address: string;
|
|
19
|
+
}[];
|
|
20
|
+
}>;
|
|
19
21
|
/**
|
|
20
22
|
* Get list of connected USB printers
|
|
21
23
|
*/
|
|
22
24
|
listUsbPrinters(): Promise<{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
printers: {
|
|
26
|
+
name: string;
|
|
27
|
+
address: string;
|
|
28
|
+
}[];
|
|
29
|
+
}>;
|
|
26
30
|
}
|
|
27
31
|
export interface PrintObject {
|
|
28
32
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["export interface ThermalPrinterPlugin {\n /**\n * Print text using USB connection\n * @param printObject Object containing text to print\n */\n printByUsb(printObject: PrintObject): Promise<void>;\n\n /**\n * Print text using Bluetooth connection\n * @param printObject Object containing text to print\n */\n printByBluetooth(printObject: PrintObject): Promise<void>;\n\n /**\n * Get list of paired Bluetooth printers\n */\n listBluetoothPrinters(): Promise<{ name: string; address: string }[]>;\n\n /**\n * Get list of connected USB printers\n */\n listUsbPrinters(): Promise<{ name: string; address: string }[]>;\n}\n\nexport interface PrintObject {\n /**\n * Text to print. Supports ESC/POS formatting commands.\n * Example: \"[C]<b>Hello World</b>\\n[C]This is a test\"\n */\n textToPrint: string;\n\n /**\n * Optional Bluetooth MAC address of the printer to use.\n * Only applicable for printByBluetooth.\n */\n address?: string;\n\n /**\n * Optional USB device name of the printer to use.\n * Only applicable for printByUsb.\n */\n name?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["export interface ThermalPrinterPlugin {\n /**\n * Print text using USB connection\n * @param printObject Object containing text to print\n */\n printByUsb(printObject: PrintObject): Promise<void>;\n\n /**\n * Print text using Bluetooth connection\n * @param printObject Object containing text to print\n */\n printByBluetooth(printObject: PrintObject): Promise<void>;\n\n /**\n * Get list of paired Bluetooth printers\n */\n listBluetoothPrinters(): Promise<{ printers: { name: string; address: string }[] }>;\n\n /**\n * Get list of connected USB printers\n */\n listUsbPrinters(): Promise<{ printers: { name: string; address: string }[] }>;\n}\n\nexport interface PrintObject {\n /**\n * Text to print. Supports ESC/POS formatting commands.\n * Example: \"[C]<b>Hello World</b>\\n[C]This is a test\"\n */\n textToPrint: string;\n\n /**\n * Optional Bluetooth MAC address of the printer to use.\n * Only applicable for printByBluetooth.\n */\n address?: string;\n\n /**\n * Optional USB device name of the printer to use.\n * Only applicable for printByUsb.\n */\n name?: string;\n}\n"]}
|
package/package.json
CHANGED