react-native-pdf417-scanner 1.1.0 → 1.3.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/README.md
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
# React Native PDF417 Scanner SDK
|
|
2
2
|
|
|
3
|
-
A comprehensive React Native SDK for live PDF417 barcode scanning
|
|
3
|
+
A comprehensive React Native SDK for live PDF417 barcode scanning with **native camera view** using Android implementation and ZXing library.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
7
|
+
- **🎥 Live Camera View**: Real-time camera preview with native Android TextureView
|
|
8
|
+
- **📱 Live PDF417 Scanning**: Real-time barcode detection using device camera
|
|
9
|
+
- **⚡ Native Performance**: Optimized native Android implementation with ZXing
|
|
10
|
+
- **🎛️ Camera Management**: Automatic camera permission handling and lifecycle management
|
|
11
|
+
- **🔦 Advanced Controls**: Autofocus, torch/flashlight control, scan timeout
|
|
12
|
+
- **📡 Event-Driven API**: Clean React Native bridge with events and callbacks
|
|
13
|
+
- **🛡️ Error Handling**: Comprehensive error reporting and recovery
|
|
14
|
+
- **📝 TypeScript Support**: Full TypeScript definitions included
|
|
15
|
+
|
|
16
|
+
## What's New in v1.2.0
|
|
17
|
+
|
|
18
|
+
- **Native Camera View Component**: Show live camera feed instead of black screen
|
|
19
|
+
- **Real-time Preview**: See exactly what the camera sees while scanning
|
|
20
|
+
- **Overlay Support**: Add custom UI overlays on top of camera view
|
|
21
|
+
- **Better UX**: Professional scanning experience with live preview
|
|
14
22
|
|
|
15
23
|
## Installation
|
|
16
24
|
|
|
@@ -65,14 +73,247 @@ add(PDF417ScannerPackage())
|
|
|
65
73
|
|
|
66
74
|
## Usage
|
|
67
75
|
|
|
68
|
-
###
|
|
76
|
+
### Method 1: With Native Camera View (Recommended)
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import React, { useEffect, useState } from 'react';
|
|
80
|
+
import { View, Modal, TouchableOpacity, Text, StyleSheet } from 'react-native';
|
|
81
|
+
import PDF417Scanner, {
|
|
82
|
+
PDF417ScanResult,
|
|
83
|
+
PDF417ScanError,
|
|
84
|
+
PDF417CameraView
|
|
85
|
+
} from 'react-native-pdf417-scanner';
|
|
86
|
+
|
|
87
|
+
const ScannerWithCameraView = () => {
|
|
88
|
+
const [showScanner, setShowScanner] = useState(false);
|
|
89
|
+
const [torchEnabled, setTorchEnabled] = useState(false);
|
|
90
|
+
const [cameraReady, setCameraReady] = useState(false);
|
|
91
|
+
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
const scanResultUnsubscribe = PDF417Scanner.onScanResult(handleScanResult);
|
|
94
|
+
const scanErrorUnsubscribe = PDF417Scanner.onScanError(handleScanError);
|
|
95
|
+
|
|
96
|
+
return () => {
|
|
97
|
+
scanResultUnsubscribe();
|
|
98
|
+
scanErrorUnsubscribe();
|
|
99
|
+
};
|
|
100
|
+
}, []);
|
|
101
|
+
|
|
102
|
+
const handleScanResult = (result: PDF417ScanResult) => {
|
|
103
|
+
console.log('Scanned:', result.data);
|
|
104
|
+
setShowScanner(false);
|
|
105
|
+
// Handle scan result
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const handleScanError = (error: PDF417ScanError) => {
|
|
109
|
+
console.error('Scan error:', error);
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const startScanning = async () => {
|
|
113
|
+
setShowScanner(true);
|
|
114
|
+
try {
|
|
115
|
+
await PDF417Scanner.startScanning({
|
|
116
|
+
enableAutoFocus: true,
|
|
117
|
+
enableTorch: torchEnabled,
|
|
118
|
+
scanTimeout: 30000,
|
|
119
|
+
enableBeep: true,
|
|
120
|
+
enableVibration: true,
|
|
121
|
+
});
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error('Failed to start scanning:', error);
|
|
124
|
+
setShowScanner(false);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const stopScanning = async () => {
|
|
129
|
+
try {
|
|
130
|
+
await PDF417Scanner.stopScanning();
|
|
131
|
+
setShowScanner(false);
|
|
132
|
+
setCameraReady(false);
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error('Failed to stop scanning:', error);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<View style={styles.container}>
|
|
140
|
+
<TouchableOpacity style={styles.scanButton} onPress={startScanning}>
|
|
141
|
+
<Text style={styles.scanButtonText}>Start Scanning</Text>
|
|
142
|
+
</TouchableOpacity>
|
|
143
|
+
|
|
144
|
+
<Modal visible={showScanner} animationType="slide">
|
|
145
|
+
<View style={styles.scannerContainer}>
|
|
146
|
+
{/* Native Camera View */}
|
|
147
|
+
<PDF417CameraView
|
|
148
|
+
style={styles.cameraView}
|
|
149
|
+
isActive={showScanner}
|
|
150
|
+
torchEnabled={torchEnabled}
|
|
151
|
+
onCameraReady={() => setCameraReady(true)}
|
|
152
|
+
onCameraError={(event) => {
|
|
153
|
+
console.error('Camera error:', event.nativeEvent.error);
|
|
154
|
+
setShowScanner(false);
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
157
|
+
|
|
158
|
+
{/* Overlay UI */}
|
|
159
|
+
<View style={styles.overlay}>
|
|
160
|
+
{/* Header */}
|
|
161
|
+
<View style={styles.header}>
|
|
162
|
+
<TouchableOpacity onPress={stopScanning}>
|
|
163
|
+
<Text style={styles.closeButton}>Close</Text>
|
|
164
|
+
</TouchableOpacity>
|
|
165
|
+
<Text style={styles.title}>Scan PDF417</Text>
|
|
166
|
+
<TouchableOpacity onPress={() => setTorchEnabled(!torchEnabled)}>
|
|
167
|
+
<Text style={styles.torchButton}>
|
|
168
|
+
{torchEnabled ? 'Flash Off' : 'Flash On'}
|
|
169
|
+
</Text>
|
|
170
|
+
</TouchableOpacity>
|
|
171
|
+
</View>
|
|
172
|
+
|
|
173
|
+
{/* Scan Frame */}
|
|
174
|
+
<View style={styles.scanFrame}>
|
|
175
|
+
<View style={styles.frameCorner} />
|
|
176
|
+
<View style={[styles.frameCorner, styles.topRight]} />
|
|
177
|
+
<View style={[styles.frameCorner, styles.bottomLeft]} />
|
|
178
|
+
<View style={[styles.frameCorner, styles.bottomRight]} />
|
|
179
|
+
</View>
|
|
180
|
+
|
|
181
|
+
{/* Instructions */}
|
|
182
|
+
<View style={styles.instructions}>
|
|
183
|
+
<Text style={styles.instructionText}>
|
|
184
|
+
{cameraReady
|
|
185
|
+
? 'Point camera at PDF417 barcode'
|
|
186
|
+
: 'Starting camera...'}
|
|
187
|
+
</Text>
|
|
188
|
+
</View>
|
|
189
|
+
</View>
|
|
190
|
+
</View>
|
|
191
|
+
</Modal>
|
|
192
|
+
</View>
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const styles = StyleSheet.create({
|
|
197
|
+
container: {
|
|
198
|
+
flex: 1,
|
|
199
|
+
justifyContent: 'center',
|
|
200
|
+
alignItems: 'center',
|
|
201
|
+
},
|
|
202
|
+
scanButton: {
|
|
203
|
+
backgroundColor: '#2196F3',
|
|
204
|
+
paddingHorizontal: 30,
|
|
205
|
+
paddingVertical: 15,
|
|
206
|
+
borderRadius: 8,
|
|
207
|
+
},
|
|
208
|
+
scanButtonText: {
|
|
209
|
+
color: '#fff',
|
|
210
|
+
fontSize: 16,
|
|
211
|
+
fontWeight: 'bold',
|
|
212
|
+
},
|
|
213
|
+
scannerContainer: {
|
|
214
|
+
flex: 1,
|
|
215
|
+
},
|
|
216
|
+
cameraView: {
|
|
217
|
+
flex: 1,
|
|
218
|
+
},
|
|
219
|
+
overlay: {
|
|
220
|
+
position: 'absolute',
|
|
221
|
+
top: 0,
|
|
222
|
+
left: 0,
|
|
223
|
+
right: 0,
|
|
224
|
+
bottom: 0,
|
|
225
|
+
},
|
|
226
|
+
header: {
|
|
227
|
+
flexDirection: 'row',
|
|
228
|
+
justifyContent: 'space-between',
|
|
229
|
+
alignItems: 'center',
|
|
230
|
+
paddingHorizontal: 20,
|
|
231
|
+
paddingTop: 50,
|
|
232
|
+
paddingBottom: 20,
|
|
233
|
+
backgroundColor: 'rgba(0,0,0,0.7)',
|
|
234
|
+
},
|
|
235
|
+
closeButton: {
|
|
236
|
+
color: '#fff',
|
|
237
|
+
fontSize: 16,
|
|
238
|
+
},
|
|
239
|
+
title: {
|
|
240
|
+
color: '#fff',
|
|
241
|
+
fontSize: 18,
|
|
242
|
+
fontWeight: 'bold',
|
|
243
|
+
},
|
|
244
|
+
torchButton: {
|
|
245
|
+
color: '#fff',
|
|
246
|
+
fontSize: 16,
|
|
247
|
+
},
|
|
248
|
+
scanFrame: {
|
|
249
|
+
position: 'absolute',
|
|
250
|
+
top: '50%',
|
|
251
|
+
left: '50%',
|
|
252
|
+
width: 250,
|
|
253
|
+
height: 150,
|
|
254
|
+
marginTop: -75,
|
|
255
|
+
marginLeft: -125,
|
|
256
|
+
},
|
|
257
|
+
frameCorner: {
|
|
258
|
+
position: 'absolute',
|
|
259
|
+
width: 20,
|
|
260
|
+
height: 20,
|
|
261
|
+
borderColor: '#2196F3',
|
|
262
|
+
borderWidth: 3,
|
|
263
|
+
borderRightColor: 'transparent',
|
|
264
|
+
borderBottomColor: 'transparent',
|
|
265
|
+
},
|
|
266
|
+
topRight: {
|
|
267
|
+
top: 0,
|
|
268
|
+
right: 0,
|
|
269
|
+
borderTopColor: '#2196F3',
|
|
270
|
+
borderRightColor: '#2196F3',
|
|
271
|
+
borderLeftColor: 'transparent',
|
|
272
|
+
borderBottomColor: 'transparent',
|
|
273
|
+
},
|
|
274
|
+
bottomLeft: {
|
|
275
|
+
bottom: 0,
|
|
276
|
+
left: 0,
|
|
277
|
+
borderBottomColor: '#2196F3',
|
|
278
|
+
borderLeftColor: '#2196F3',
|
|
279
|
+
borderTopColor: 'transparent',
|
|
280
|
+
borderRightColor: 'transparent',
|
|
281
|
+
},
|
|
282
|
+
bottomRight: {
|
|
283
|
+
bottom: 0,
|
|
284
|
+
right: 0,
|
|
285
|
+
borderBottomColor: '#2196F3',
|
|
286
|
+
borderRightColor: '#2196F3',
|
|
287
|
+
borderTopColor: 'transparent',
|
|
288
|
+
borderLeftColor: 'transparent',
|
|
289
|
+
},
|
|
290
|
+
instructions: {
|
|
291
|
+
position: 'absolute',
|
|
292
|
+
bottom: 100,
|
|
293
|
+
left: 0,
|
|
294
|
+
right: 0,
|
|
295
|
+
alignItems: 'center',
|
|
296
|
+
},
|
|
297
|
+
instructionText: {
|
|
298
|
+
color: '#fff',
|
|
299
|
+
fontSize: 16,
|
|
300
|
+
textAlign: 'center',
|
|
301
|
+
backgroundColor: 'rgba(0,0,0,0.7)',
|
|
302
|
+
paddingHorizontal: 20,
|
|
303
|
+
paddingVertical: 10,
|
|
304
|
+
borderRadius: 8,
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Method 2: Basic Implementation (Background Scanning)
|
|
69
310
|
|
|
70
311
|
```typescript
|
|
71
312
|
import React, { useEffect, useState } from 'react';
|
|
72
313
|
import { View, Button, Alert } from 'react-native';
|
|
73
314
|
import PDF417Scanner, { PDF417ScanResult, PDF417ScanError } from 'react-native-pdf417-scanner';
|
|
74
315
|
|
|
75
|
-
const
|
|
316
|
+
const BasicScannerComponent = () => {
|
|
76
317
|
const [isScanning, setIsScanning] = useState(false);
|
|
77
318
|
|
|
78
319
|
useEffect(() => {
|
|
@@ -139,6 +380,35 @@ const ScannerComponent = () => {
|
|
|
139
380
|
|
|
140
381
|
## API Reference
|
|
141
382
|
|
|
383
|
+
### Components
|
|
384
|
+
|
|
385
|
+
#### `PDF417CameraView`
|
|
386
|
+
Native camera view component that displays live camera feed.
|
|
387
|
+
|
|
388
|
+
**Props:**
|
|
389
|
+
```typescript
|
|
390
|
+
interface PDF417CameraViewProps {
|
|
391
|
+
style?: ViewStyle; // View styling
|
|
392
|
+
isActive?: boolean; // Whether camera should be active
|
|
393
|
+
torchEnabled?: boolean; // Flash/torch state
|
|
394
|
+
onCameraReady?: () => void; // Called when camera is ready
|
|
395
|
+
onCameraError?: (event: { // Called on camera errors
|
|
396
|
+
nativeEvent: { error: string }
|
|
397
|
+
}) => void;
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Example:**
|
|
402
|
+
```typescript
|
|
403
|
+
<PDF417CameraView
|
|
404
|
+
style={{ flex: 1 }}
|
|
405
|
+
isActive={true}
|
|
406
|
+
torchEnabled={false}
|
|
407
|
+
onCameraReady={() => console.log('Camera ready')}
|
|
408
|
+
onCameraError={(e) => console.log('Error:', e.nativeEvent.error)}
|
|
409
|
+
/>
|
|
410
|
+
```
|
|
411
|
+
|
|
142
412
|
### Methods
|
|
143
413
|
|
|
144
414
|
#### `startScanning(config?: PDF417ScannerConfig): Promise<void>`
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.pdf417scanner;
|
|
2
2
|
|
|
3
|
+
import android.Manifest;
|
|
3
4
|
import android.content.Context;
|
|
5
|
+
import android.content.pm.PackageManager;
|
|
4
6
|
import android.graphics.SurfaceTexture;
|
|
5
7
|
import android.hardware.camera2.CameraAccessException;
|
|
6
8
|
import android.hardware.camera2.CameraCaptureSession;
|
|
@@ -18,6 +20,7 @@ import android.view.Surface;
|
|
|
18
20
|
import android.view.TextureView;
|
|
19
21
|
|
|
20
22
|
import androidx.annotation.NonNull;
|
|
23
|
+
import androidx.core.app.ActivityCompat;
|
|
21
24
|
|
|
22
25
|
import java.util.Arrays;
|
|
23
26
|
import java.util.concurrent.Semaphore;
|
|
@@ -70,6 +73,9 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
70
73
|
startBackgroundThread();
|
|
71
74
|
if (isAvailable()) {
|
|
72
75
|
openCamera(getWidth(), getHeight());
|
|
76
|
+
} else {
|
|
77
|
+
// Surface not ready yet, will be called from onSurfaceTextureAvailable
|
|
78
|
+
Log.d(TAG, "Surface texture not available yet, waiting...");
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
|
|
@@ -118,6 +124,15 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
118
124
|
|
|
119
125
|
private void openCamera(int width, int height) {
|
|
120
126
|
try {
|
|
127
|
+
// Check camera permission first
|
|
128
|
+
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA)
|
|
129
|
+
!= PackageManager.PERMISSION_GRANTED) {
|
|
130
|
+
if (cameraReadyListener != null) {
|
|
131
|
+
cameraReadyListener.onCameraError("Camera permission not granted");
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
121
136
|
if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
|
122
137
|
throw new RuntimeException("Time out waiting to lock camera opening.");
|
|
123
138
|
}
|
|
@@ -193,6 +208,13 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
193
208
|
private void createCameraPreviewSession() {
|
|
194
209
|
try {
|
|
195
210
|
SurfaceTexture texture = getSurfaceTexture();
|
|
211
|
+
if (texture == null) {
|
|
212
|
+
if (cameraReadyListener != null) {
|
|
213
|
+
cameraReadyListener.onCameraError("Surface texture not available");
|
|
214
|
+
}
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
196
218
|
texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
|
197
219
|
Surface surface = new Surface(texture);
|
|
198
220
|
|
|
@@ -215,7 +237,7 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
215
237
|
} catch (CameraAccessException e) {
|
|
216
238
|
Log.e(TAG, "Error starting camera preview", e);
|
|
217
239
|
if (cameraReadyListener != null) {
|
|
218
|
-
cameraReadyListener.onCameraError("Failed to start preview");
|
|
240
|
+
cameraReadyListener.onCameraError("Failed to start preview: " + e.getMessage());
|
|
219
241
|
}
|
|
220
242
|
}
|
|
221
243
|
}
|
|
@@ -230,7 +252,7 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
230
252
|
} catch (CameraAccessException e) {
|
|
231
253
|
Log.e(TAG, "Error creating camera preview session", e);
|
|
232
254
|
if (cameraReadyListener != null) {
|
|
233
|
-
cameraReadyListener.onCameraError("Failed to create preview session");
|
|
255
|
+
cameraReadyListener.onCameraError("Failed to create preview session: " + e.getMessage());
|
|
234
256
|
}
|
|
235
257
|
}
|
|
236
258
|
}
|