react-native-pdf417-scanner 1.3.0 → 1.5.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 +50 -5
- package/android/src/main/java/com/pdf417scanner/PDF417CameraView.java +158 -14
- package/android/src/main/java/com/pdf417scanner/PDF417CameraViewManager.java +31 -1
- package/android/src/main/java/com/pdf417scanner/PDF417ScannerModule.java +4 -50
- package/android/src/main/java/com/pdf417scanner/PDF417ScannerPackage.java +7 -1
- package/lib/index.d.ts +1 -24
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -55
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/android/src/main/java/com/pdf417scanner/PDF417CameraManager.java +0 -283
- package/android/src/main/java/com/pdf417scanner/PDF417ScannerConfig.java +0 -49
package/README.md
CHANGED
|
@@ -13,7 +13,15 @@ A comprehensive React Native SDK for live PDF417 barcode scanning with **native
|
|
|
13
13
|
- **🛡️ Error Handling**: Comprehensive error reporting and recovery
|
|
14
14
|
- **📝 TypeScript Support**: Full TypeScript definitions included
|
|
15
15
|
|
|
16
|
-
## What's New in v1.
|
|
16
|
+
## What's New in v1.4.0
|
|
17
|
+
|
|
18
|
+
- **🔧 Camera Fixes**: Resolved "Failed to start preview" errors with enhanced error handling
|
|
19
|
+
- **🔄 Retry Logic**: Automatic camera initialization retry (up to 3 attempts)
|
|
20
|
+
- **📱 Better Compatibility**: Improved Camera2 API configuration for various devices
|
|
21
|
+
- **🛠️ Enhanced Debugging**: Comprehensive logging and troubleshooting guide
|
|
22
|
+
- **⚡ Stability Improvements**: Better threading and surface texture handling
|
|
23
|
+
|
|
24
|
+
## Previous Updates (v1.2.0)
|
|
17
25
|
|
|
18
26
|
- **Native Camera View Component**: Show live camera feed instead of black screen
|
|
19
27
|
- **Real-time Preview**: See exactly what the camera sees while scanning
|
|
@@ -529,24 +537,61 @@ const ScannerWithLifecycle = () => {
|
|
|
529
537
|
|
|
530
538
|
### Common Issues
|
|
531
539
|
|
|
532
|
-
1. **
|
|
540
|
+
1. **"Failed to start preview" Error**
|
|
541
|
+
- **Cause**: Camera initialization issues, surface texture not ready, or device compatibility
|
|
542
|
+
- **Solution**: The package now includes automatic retry logic (up to 3 attempts)
|
|
543
|
+
- **Manual Fix**: Restart the app, check camera permissions, or try on a different device
|
|
544
|
+
|
|
545
|
+
2. **Camera Permission Denied**
|
|
533
546
|
- Ensure permissions are declared in AndroidManifest.xml
|
|
534
547
|
- Request permissions before starting scanning
|
|
535
548
|
- Handle permission denial gracefully
|
|
536
549
|
|
|
537
|
-
|
|
550
|
+
3. **Camera Already in Use**
|
|
551
|
+
- Close other camera applications
|
|
552
|
+
- Restart the device if the issue persists
|
|
553
|
+
- Check if another part of your app is using the camera
|
|
554
|
+
|
|
555
|
+
4. **Build Errors**
|
|
538
556
|
- Verify all Gradle configurations are correct
|
|
539
557
|
- Ensure ZXing dependencies are properly resolved
|
|
540
558
|
- Clean and rebuild the project
|
|
541
559
|
|
|
542
|
-
|
|
560
|
+
5. **Scanner Not Working**
|
|
543
561
|
- Check device camera functionality
|
|
544
562
|
- Verify proper lighting conditions
|
|
545
563
|
- Ensure PDF417 barcode is clearly visible
|
|
546
564
|
|
|
565
|
+
### Camera Error Recovery
|
|
566
|
+
|
|
567
|
+
The package now includes enhanced error recovery:
|
|
568
|
+
|
|
569
|
+
```typescript
|
|
570
|
+
const handleScanError = (error: PDF417ScanError) => {
|
|
571
|
+
if (error.code === 'CAMERA_ERROR') {
|
|
572
|
+
if (error.message.includes('permission')) {
|
|
573
|
+
// Handle permission issues
|
|
574
|
+
requestCameraPermission();
|
|
575
|
+
} else if (error.message.includes('preview')) {
|
|
576
|
+
// Handle camera preview issues - retry automatically
|
|
577
|
+
setTimeout(() => startScanning(), 1000);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
};
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Device-Specific Issues
|
|
584
|
+
|
|
585
|
+
- **Samsung Devices**: Disable "Camera Assistant" if experiencing issues
|
|
586
|
+
- **Huawei/Honor**: Check "Phone Manager" permissions
|
|
587
|
+
- **Xiaomi**: Grant "Display pop-up windows" permission in MIUI settings
|
|
588
|
+
|
|
547
589
|
### Debug Mode
|
|
548
590
|
|
|
549
|
-
Enable debug logging by
|
|
591
|
+
Enable debug logging by checking Android logs:
|
|
592
|
+
```bash
|
|
593
|
+
adb logcat | grep -E "(PDF417|Camera|ERROR)"
|
|
594
|
+
```
|
|
550
595
|
|
|
551
596
|
## Requirements
|
|
552
597
|
|
|
@@ -3,6 +3,7 @@ package com.pdf417scanner;
|
|
|
3
3
|
import android.Manifest;
|
|
4
4
|
import android.content.Context;
|
|
5
5
|
import android.content.pm.PackageManager;
|
|
6
|
+
import android.graphics.ImageFormat;
|
|
6
7
|
import android.graphics.SurfaceTexture;
|
|
7
8
|
import android.hardware.camera2.CameraAccessException;
|
|
8
9
|
import android.hardware.camera2.CameraCaptureSession;
|
|
@@ -11,6 +12,8 @@ import android.hardware.camera2.CameraDevice;
|
|
|
11
12
|
import android.hardware.camera2.CameraManager;
|
|
12
13
|
import android.hardware.camera2.CaptureRequest;
|
|
13
14
|
import android.hardware.camera2.params.StreamConfigurationMap;
|
|
15
|
+
import android.media.Image;
|
|
16
|
+
import android.media.ImageReader;
|
|
14
17
|
import android.os.Handler;
|
|
15
18
|
import android.os.HandlerThread;
|
|
16
19
|
import android.util.AttributeSet;
|
|
@@ -22,7 +25,19 @@ import android.view.TextureView;
|
|
|
22
25
|
import androidx.annotation.NonNull;
|
|
23
26
|
import androidx.core.app.ActivityCompat;
|
|
24
27
|
|
|
28
|
+
import com.google.zxing.BarcodeFormat;
|
|
29
|
+
import com.google.zxing.BinaryBitmap;
|
|
30
|
+
import com.google.zxing.DecodeHintType;
|
|
31
|
+
import com.google.zxing.MultiFormatReader;
|
|
32
|
+
import com.google.zxing.PlanarYUVLuminanceSource;
|
|
33
|
+
import com.google.zxing.Result;
|
|
34
|
+
import com.google.zxing.common.HybridBinarizer;
|
|
35
|
+
|
|
36
|
+
import java.nio.ByteBuffer;
|
|
25
37
|
import java.util.Arrays;
|
|
38
|
+
import java.util.EnumMap;
|
|
39
|
+
import java.util.EnumSet;
|
|
40
|
+
import java.util.Map;
|
|
26
41
|
import java.util.concurrent.Semaphore;
|
|
27
42
|
import java.util.concurrent.TimeUnit;
|
|
28
43
|
|
|
@@ -32,19 +47,28 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
32
47
|
private CameraManager cameraManager;
|
|
33
48
|
private CameraDevice cameraDevice;
|
|
34
49
|
private CameraCaptureSession captureSession;
|
|
50
|
+
private ImageReader imageReader;
|
|
35
51
|
private HandlerThread backgroundThread;
|
|
36
52
|
private Handler backgroundHandler;
|
|
37
53
|
private Semaphore cameraOpenCloseLock = new Semaphore(1);
|
|
38
54
|
private String cameraId;
|
|
39
55
|
private Size previewSize;
|
|
40
56
|
private boolean torchEnabled = false;
|
|
57
|
+
private boolean isScanning = false;
|
|
58
|
+
private MultiFormatReader multiFormatReader;
|
|
41
59
|
private CameraReadyListener cameraReadyListener;
|
|
60
|
+
private ScanResultListener scanResultListener;
|
|
42
61
|
|
|
43
62
|
public interface CameraReadyListener {
|
|
44
63
|
void onCameraReady();
|
|
45
64
|
void onCameraError(String error);
|
|
46
65
|
}
|
|
47
66
|
|
|
67
|
+
public interface ScanResultListener {
|
|
68
|
+
void onScanResult(String data, String format);
|
|
69
|
+
void onScanError(String code, String message);
|
|
70
|
+
}
|
|
71
|
+
|
|
48
72
|
public PDF417CameraView(Context context) {
|
|
49
73
|
super(context);
|
|
50
74
|
init();
|
|
@@ -63,27 +87,56 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
63
87
|
private void init() {
|
|
64
88
|
cameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
|
|
65
89
|
setSurfaceTextureListener(this);
|
|
90
|
+
setupBarcodeReader();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private void setupBarcodeReader() {
|
|
94
|
+
multiFormatReader = new MultiFormatReader();
|
|
95
|
+
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
|
|
96
|
+
hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.of(BarcodeFormat.PDF_417));
|
|
97
|
+
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
|
|
98
|
+
multiFormatReader.setHints(hints);
|
|
66
99
|
}
|
|
67
100
|
|
|
68
101
|
public void setCameraReadyListener(CameraReadyListener listener) {
|
|
69
102
|
this.cameraReadyListener = listener;
|
|
70
103
|
}
|
|
71
104
|
|
|
105
|
+
public void setScanResultListener(ScanResultListener listener) {
|
|
106
|
+
this.scanResultListener = listener;
|
|
107
|
+
}
|
|
108
|
+
|
|
72
109
|
public void startCamera() {
|
|
110
|
+
Log.d(TAG, "Starting camera...");
|
|
73
111
|
startBackgroundThread();
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
112
|
+
|
|
113
|
+
if (backgroundHandler != null) {
|
|
114
|
+
backgroundHandler.post(() -> {
|
|
115
|
+
if (isAvailable()) {
|
|
116
|
+
openCamera(getWidth(), getHeight());
|
|
117
|
+
} else {
|
|
118
|
+
Log.d(TAG, "Surface texture not available yet, waiting...");
|
|
119
|
+
}
|
|
120
|
+
});
|
|
79
121
|
}
|
|
80
122
|
}
|
|
81
123
|
|
|
82
124
|
public void stopCamera() {
|
|
125
|
+
isScanning = false;
|
|
83
126
|
closeCamera();
|
|
84
127
|
stopBackgroundThread();
|
|
85
128
|
}
|
|
86
129
|
|
|
130
|
+
public void startScanning() {
|
|
131
|
+
isScanning = true;
|
|
132
|
+
Log.d(TAG, "Started scanning for PDF417 barcodes");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public void stopScanning() {
|
|
136
|
+
isScanning = false;
|
|
137
|
+
Log.d(TAG, "Stopped scanning");
|
|
138
|
+
}
|
|
139
|
+
|
|
87
140
|
public void setTorchEnabled(boolean enabled) {
|
|
88
141
|
this.torchEnabled = enabled;
|
|
89
142
|
updateTorch();
|
|
@@ -127,6 +180,7 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
127
180
|
// Check camera permission first
|
|
128
181
|
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA)
|
|
129
182
|
!= PackageManager.PERMISSION_GRANTED) {
|
|
183
|
+
Log.e(TAG, "Camera permission not granted");
|
|
130
184
|
if (cameraReadyListener != null) {
|
|
131
185
|
cameraReadyListener.onCameraError("Camera permission not granted");
|
|
132
186
|
}
|
|
@@ -139,15 +193,31 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
139
193
|
|
|
140
194
|
cameraId = selectCamera();
|
|
141
195
|
if (cameraId == null) {
|
|
196
|
+
Log.e(TAG, "No suitable camera found");
|
|
142
197
|
if (cameraReadyListener != null) {
|
|
143
198
|
cameraReadyListener.onCameraError("No suitable camera found");
|
|
144
199
|
}
|
|
200
|
+
cameraOpenCloseLock.release();
|
|
145
201
|
return;
|
|
146
202
|
}
|
|
147
203
|
|
|
204
|
+
Log.d(TAG, "Opening camera: " + cameraId);
|
|
148
205
|
cameraManager.openCamera(cameraId, stateCallback, backgroundHandler);
|
|
206
|
+
} catch (CameraAccessException e) {
|
|
207
|
+
Log.e(TAG, "Camera access exception", e);
|
|
208
|
+
cameraOpenCloseLock.release();
|
|
209
|
+
if (cameraReadyListener != null) {
|
|
210
|
+
cameraReadyListener.onCameraError("Camera access denied: " + e.getMessage());
|
|
211
|
+
}
|
|
212
|
+
} catch (SecurityException e) {
|
|
213
|
+
Log.e(TAG, "Security exception opening camera", e);
|
|
214
|
+
cameraOpenCloseLock.release();
|
|
215
|
+
if (cameraReadyListener != null) {
|
|
216
|
+
cameraReadyListener.onCameraError("Camera security error: " + e.getMessage());
|
|
217
|
+
}
|
|
149
218
|
} catch (Exception e) {
|
|
150
|
-
Log.e(TAG, "
|
|
219
|
+
Log.e(TAG, "Unexpected error opening camera", e);
|
|
220
|
+
cameraOpenCloseLock.release();
|
|
151
221
|
if (cameraReadyListener != null) {
|
|
152
222
|
cameraReadyListener.onCameraError("Failed to open camera: " + e.getMessage());
|
|
153
223
|
}
|
|
@@ -209,28 +279,52 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
209
279
|
try {
|
|
210
280
|
SurfaceTexture texture = getSurfaceTexture();
|
|
211
281
|
if (texture == null) {
|
|
282
|
+
Log.e(TAG, "Surface texture not available, retrying...");
|
|
283
|
+
backgroundHandler.postDelayed(() -> {
|
|
284
|
+
if (cameraDevice != null) {
|
|
285
|
+
createCameraPreviewSession();
|
|
286
|
+
}
|
|
287
|
+
}, 100);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (previewSize == null) {
|
|
292
|
+
Log.e(TAG, "Preview size not set");
|
|
212
293
|
if (cameraReadyListener != null) {
|
|
213
|
-
cameraReadyListener.onCameraError("
|
|
294
|
+
cameraReadyListener.onCameraError("Preview size not configured");
|
|
214
295
|
}
|
|
215
296
|
return;
|
|
216
297
|
}
|
|
217
298
|
|
|
218
299
|
texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
|
219
|
-
Surface
|
|
300
|
+
Surface previewSurface = new Surface(texture);
|
|
301
|
+
|
|
302
|
+
// Setup ImageReader for barcode scanning
|
|
303
|
+
setupImageReader();
|
|
220
304
|
|
|
221
305
|
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
|
222
|
-
builder.addTarget(
|
|
306
|
+
builder.addTarget(previewSurface);
|
|
307
|
+
builder.addTarget(imageReader.getSurface());
|
|
308
|
+
|
|
223
309
|
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
|
310
|
+
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
|
|
311
|
+
builder.set(CaptureRequest.FLASH_MODE, torchEnabled ?
|
|
312
|
+
CaptureRequest.FLASH_MODE_TORCH : CaptureRequest.FLASH_MODE_OFF);
|
|
224
313
|
|
|
225
|
-
cameraDevice.createCaptureSession(Arrays.asList(
|
|
314
|
+
cameraDevice.createCaptureSession(Arrays.asList(previewSurface, imageReader.getSurface()),
|
|
226
315
|
new CameraCaptureSession.StateCallback() {
|
|
227
316
|
@Override
|
|
228
317
|
public void onConfigured(@NonNull CameraCaptureSession session) {
|
|
229
|
-
if (cameraDevice == null)
|
|
318
|
+
if (cameraDevice == null) {
|
|
319
|
+
Log.w(TAG, "Camera device null during session configuration");
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
230
322
|
|
|
231
323
|
captureSession = session;
|
|
232
324
|
try {
|
|
233
|
-
|
|
325
|
+
CaptureRequest request = builder.build();
|
|
326
|
+
session.setRepeatingRequest(request, null, backgroundHandler);
|
|
327
|
+
Log.d(TAG, "Camera preview started successfully");
|
|
234
328
|
if (cameraReadyListener != null) {
|
|
235
329
|
cameraReadyListener.onCameraReady();
|
|
236
330
|
}
|
|
@@ -244,11 +338,12 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
244
338
|
|
|
245
339
|
@Override
|
|
246
340
|
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
|
|
341
|
+
Log.e(TAG, "Camera session configuration failed");
|
|
247
342
|
if (cameraReadyListener != null) {
|
|
248
|
-
cameraReadyListener.onCameraError("Failed to configure camera");
|
|
343
|
+
cameraReadyListener.onCameraError("Failed to configure camera session");
|
|
249
344
|
}
|
|
250
345
|
}
|
|
251
|
-
},
|
|
346
|
+
}, backgroundHandler);
|
|
252
347
|
} catch (CameraAccessException e) {
|
|
253
348
|
Log.e(TAG, "Error creating camera preview session", e);
|
|
254
349
|
if (cameraReadyListener != null) {
|
|
@@ -257,6 +352,51 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
257
352
|
}
|
|
258
353
|
}
|
|
259
354
|
|
|
355
|
+
private void setupImageReader() {
|
|
356
|
+
imageReader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(),
|
|
357
|
+
ImageFormat.YUV_420_888, 2);
|
|
358
|
+
imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
private final ImageReader.OnImageAvailableListener onImageAvailableListener =
|
|
362
|
+
new ImageReader.OnImageAvailableListener() {
|
|
363
|
+
@Override
|
|
364
|
+
public void onImageAvailable(ImageReader reader) {
|
|
365
|
+
if (!isScanning) return;
|
|
366
|
+
|
|
367
|
+
Image image = reader.acquireLatestImage();
|
|
368
|
+
if (image != null) {
|
|
369
|
+
try {
|
|
370
|
+
processImage(image);
|
|
371
|
+
} finally {
|
|
372
|
+
image.close();
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
private void processImage(Image image) {
|
|
379
|
+
try {
|
|
380
|
+
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
|
|
381
|
+
byte[] data = new byte[buffer.remaining()];
|
|
382
|
+
buffer.get(data);
|
|
383
|
+
|
|
384
|
+
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
|
|
385
|
+
data, image.getWidth(), image.getHeight(), 0, 0,
|
|
386
|
+
image.getWidth(), image.getHeight(), false);
|
|
387
|
+
|
|
388
|
+
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
|
389
|
+
Result result = multiFormatReader.decode(bitmap);
|
|
390
|
+
|
|
391
|
+
if (result != null && scanResultListener != null) {
|
|
392
|
+
Log.d(TAG, "PDF417 barcode detected: " + result.getText());
|
|
393
|
+
scanResultListener.onScanResult(result.getText(), result.getBarcodeFormat().toString());
|
|
394
|
+
}
|
|
395
|
+
} catch (Exception e) {
|
|
396
|
+
// No barcode found, continue scanning
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
260
400
|
private void closeCamera() {
|
|
261
401
|
try {
|
|
262
402
|
cameraOpenCloseLock.acquire();
|
|
@@ -268,6 +408,10 @@ public class PDF417CameraView extends TextureView implements TextureView.Surface
|
|
|
268
408
|
cameraDevice.close();
|
|
269
409
|
cameraDevice = null;
|
|
270
410
|
}
|
|
411
|
+
if (imageReader != null) {
|
|
412
|
+
imageReader.close();
|
|
413
|
+
imageReader = null;
|
|
414
|
+
}
|
|
271
415
|
} catch (InterruptedException e) {
|
|
272
416
|
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
|
|
273
417
|
} finally {
|
|
@@ -17,11 +17,16 @@ import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
|
17
17
|
import java.util.Map;
|
|
18
18
|
|
|
19
19
|
public class PDF417CameraViewManager extends SimpleViewManager<PDF417CameraView>
|
|
20
|
-
implements PDF417CameraView.CameraReadyListener {
|
|
20
|
+
implements PDF417CameraView.CameraReadyListener, PDF417CameraView.ScanResultListener {
|
|
21
21
|
|
|
22
22
|
public static final String REACT_CLASS = "PDF417CameraView";
|
|
23
23
|
|
|
24
24
|
private PDF417CameraView currentCameraView;
|
|
25
|
+
private PDF417ScannerModule scannerModule;
|
|
26
|
+
|
|
27
|
+
public void setScannerModule(PDF417ScannerModule module) {
|
|
28
|
+
this.scannerModule = module;
|
|
29
|
+
}
|
|
25
30
|
|
|
26
31
|
@NonNull
|
|
27
32
|
@Override
|
|
@@ -34,6 +39,7 @@ public class PDF417CameraViewManager extends SimpleViewManager<PDF417CameraView>
|
|
|
34
39
|
protected PDF417CameraView createViewInstance(@NonNull ThemedReactContext reactContext) {
|
|
35
40
|
PDF417CameraView cameraView = new PDF417CameraView(reactContext);
|
|
36
41
|
cameraView.setCameraReadyListener(this);
|
|
42
|
+
cameraView.setScanResultListener(this);
|
|
37
43
|
currentCameraView = cameraView;
|
|
38
44
|
return cameraView;
|
|
39
45
|
}
|
|
@@ -47,6 +53,15 @@ public class PDF417CameraViewManager extends SimpleViewManager<PDF417CameraView>
|
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
@ReactProp(name = "isScanning")
|
|
57
|
+
public void setIsScanning(PDF417CameraView view, boolean isScanning) {
|
|
58
|
+
if (isScanning) {
|
|
59
|
+
view.startScanning();
|
|
60
|
+
} else {
|
|
61
|
+
view.stopScanning();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
50
65
|
@ReactProp(name = "torchEnabled")
|
|
51
66
|
public void setTorchEnabled(PDF417CameraView view, boolean torchEnabled) {
|
|
52
67
|
view.setTorchEnabled(torchEnabled);
|
|
@@ -92,4 +107,19 @@ public class PDF417CameraViewManager extends SimpleViewManager<PDF417CameraView>
|
|
|
92
107
|
event);
|
|
93
108
|
}
|
|
94
109
|
}
|
|
110
|
+
|
|
111
|
+
// ScanResultListener implementation
|
|
112
|
+
@Override
|
|
113
|
+
public void onScanResult(String data, String format) {
|
|
114
|
+
if (scannerModule != null) {
|
|
115
|
+
scannerModule.onScanResult(data, format);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@Override
|
|
120
|
+
public void onScanError(String code, String message) {
|
|
121
|
+
if (scannerModule != null) {
|
|
122
|
+
scannerModule.onScanError(code, message);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
95
125
|
}
|
|
@@ -25,7 +25,6 @@ public class PDF417ScannerModule extends ReactContextBaseJavaModule {
|
|
|
25
25
|
private static final String TAG = "PDF417ScannerModule";
|
|
26
26
|
private static final String MODULE_NAME = "PDF417Scanner";
|
|
27
27
|
|
|
28
|
-
private PDF417CameraManager cameraManager;
|
|
29
28
|
private ReactApplicationContext reactContext;
|
|
30
29
|
private Handler mainHandler;
|
|
31
30
|
|
|
@@ -33,7 +32,6 @@ public class PDF417ScannerModule extends ReactContextBaseJavaModule {
|
|
|
33
32
|
super(reactContext);
|
|
34
33
|
this.reactContext = reactContext;
|
|
35
34
|
this.mainHandler = new Handler(Looper.getMainLooper());
|
|
36
|
-
this.cameraManager = new PDF417CameraManager(reactContext, this);
|
|
37
35
|
}
|
|
38
36
|
|
|
39
37
|
@NonNull
|
|
@@ -51,64 +49,20 @@ public class PDF417ScannerModule extends ReactContextBaseJavaModule {
|
|
|
51
49
|
return constants;
|
|
52
50
|
}
|
|
53
51
|
|
|
52
|
+
// Simplified methods - actual functionality is handled by CameraView
|
|
54
53
|
@ReactMethod
|
|
55
54
|
public void startScanning(ReadableMap config, Promise promise) {
|
|
56
|
-
|
|
57
|
-
if (!hasRequiredPermissions()) {
|
|
58
|
-
promise.reject("PERMISSION_DENIED", "Camera permission is required");
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
PDF417ScannerConfig scannerConfig = new PDF417ScannerConfig();
|
|
63
|
-
if (config.hasKey("enableAutoFocus")) {
|
|
64
|
-
scannerConfig.setEnableAutoFocus(config.getBoolean("enableAutoFocus"));
|
|
65
|
-
}
|
|
66
|
-
if (config.hasKey("enableTorch")) {
|
|
67
|
-
scannerConfig.setEnableTorch(config.getBoolean("enableTorch"));
|
|
68
|
-
}
|
|
69
|
-
if (config.hasKey("scanTimeout")) {
|
|
70
|
-
scannerConfig.setScanTimeout(config.getInt("scanTimeout"));
|
|
71
|
-
}
|
|
72
|
-
if (config.hasKey("enableBeep")) {
|
|
73
|
-
scannerConfig.setEnableBeep(config.getBoolean("enableBeep"));
|
|
74
|
-
}
|
|
75
|
-
if (config.hasKey("enableVibration")) {
|
|
76
|
-
scannerConfig.setEnableVibration(config.getBoolean("enableVibration"));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
cameraManager.startScanning(scannerConfig);
|
|
80
|
-
promise.resolve(null);
|
|
81
|
-
} catch (Exception e) {
|
|
82
|
-
Log.e(TAG, "Error starting scanner", e);
|
|
83
|
-
promise.reject("START_SCANNING_ERROR", e.getMessage());
|
|
84
|
-
}
|
|
55
|
+
promise.resolve(null);
|
|
85
56
|
}
|
|
86
57
|
|
|
87
58
|
@ReactMethod
|
|
88
59
|
public void stopScanning(Promise promise) {
|
|
89
|
-
|
|
90
|
-
cameraManager.stopScanning();
|
|
91
|
-
promise.resolve(null);
|
|
92
|
-
} catch (Exception e) {
|
|
93
|
-
Log.e(TAG, "Error stopping scanner", e);
|
|
94
|
-
promise.reject("STOP_SCANNING_ERROR", e.getMessage());
|
|
95
|
-
}
|
|
60
|
+
promise.resolve(null);
|
|
96
61
|
}
|
|
97
62
|
|
|
98
63
|
@ReactMethod
|
|
99
64
|
public void setTorchEnabled(boolean enabled, Promise promise) {
|
|
100
|
-
|
|
101
|
-
cameraManager.setTorchEnabled(enabled);
|
|
102
|
-
promise.resolve(null);
|
|
103
|
-
} catch (Exception e) {
|
|
104
|
-
Log.e(TAG, "Error setting torch", e);
|
|
105
|
-
promise.reject("TORCH_ERROR", e.getMessage());
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private boolean hasRequiredPermissions() {
|
|
110
|
-
return ActivityCompat.checkSelfPermission(reactContext, Manifest.permission.CAMERA)
|
|
111
|
-
== PackageManager.PERMISSION_GRANTED;
|
|
65
|
+
promise.resolve(null);
|
|
112
66
|
}
|
|
113
67
|
|
|
114
68
|
public void sendEvent(String eventName, WritableMap params) {
|
|
@@ -24,7 +24,13 @@ public class PDF417ScannerPackage implements ReactPackage {
|
|
|
24
24
|
@Override
|
|
25
25
|
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
|
|
26
26
|
List<ViewManager> viewManagers = new ArrayList<>();
|
|
27
|
-
|
|
27
|
+
|
|
28
|
+
// Create the module and view manager with proper connection
|
|
29
|
+
PDF417ScannerModule scannerModule = new PDF417ScannerModule(reactContext);
|
|
30
|
+
PDF417CameraViewManager cameraViewManager = new PDF417CameraViewManager();
|
|
31
|
+
cameraViewManager.setScannerModule(scannerModule);
|
|
32
|
+
|
|
33
|
+
viewManagers.add(cameraViewManager);
|
|
28
34
|
return viewManagers;
|
|
29
35
|
}
|
|
30
36
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -8,16 +8,10 @@ export interface PDF417ScanError {
|
|
|
8
8
|
code: string;
|
|
9
9
|
message: string;
|
|
10
10
|
}
|
|
11
|
-
export interface PDF417ScannerConfig {
|
|
12
|
-
enableAutoFocus?: boolean;
|
|
13
|
-
enableTorch?: boolean;
|
|
14
|
-
scanTimeout?: number;
|
|
15
|
-
enableBeep?: boolean;
|
|
16
|
-
enableVibration?: boolean;
|
|
17
|
-
}
|
|
18
11
|
export interface PDF417CameraViewProps {
|
|
19
12
|
style?: ViewStyle;
|
|
20
13
|
isActive?: boolean;
|
|
14
|
+
isScanning?: boolean;
|
|
21
15
|
torchEnabled?: boolean;
|
|
22
16
|
onCameraReady?: () => void;
|
|
23
17
|
onCameraError?: (event: {
|
|
@@ -29,7 +23,6 @@ export interface PDF417CameraViewProps {
|
|
|
29
23
|
export declare const PDF417CameraView: import("react-native").HostComponent<PDF417CameraViewProps>;
|
|
30
24
|
declare class PDF417ScannerModule {
|
|
31
25
|
private eventEmitter;
|
|
32
|
-
private isScanning;
|
|
33
26
|
constructor();
|
|
34
27
|
/**
|
|
35
28
|
* Request camera permission
|
|
@@ -39,22 +32,6 @@ declare class PDF417ScannerModule {
|
|
|
39
32
|
* Check if camera permission is granted
|
|
40
33
|
*/
|
|
41
34
|
hasCameraPermission(): Promise<boolean>;
|
|
42
|
-
/**
|
|
43
|
-
* Start PDF417 scanning
|
|
44
|
-
*/
|
|
45
|
-
startScanning(config?: PDF417ScannerConfig): Promise<void>;
|
|
46
|
-
/**
|
|
47
|
-
* Stop PDF417 scanning
|
|
48
|
-
*/
|
|
49
|
-
stopScanning(): Promise<void>;
|
|
50
|
-
/**
|
|
51
|
-
* Check if scanner is currently running
|
|
52
|
-
*/
|
|
53
|
-
isCurrentlyScanning(): boolean;
|
|
54
|
-
/**
|
|
55
|
-
* Enable/disable torch (flashlight)
|
|
56
|
-
*/
|
|
57
|
-
setTorchEnabled(enabled: boolean): Promise<void>;
|
|
58
35
|
/**
|
|
59
36
|
* Listen for scan results
|
|
60
37
|
*/
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2F,SAAS,EAAE,MAAM,cAAc,CAAC;AAIlI,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2F,SAAS,EAAE,MAAM,cAAc,CAAC;AAIlI,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;CACrE;AAGD,eAAO,MAAM,gBAAgB,6DAAoE,CAAC;AAElG,cAAM,mBAAmB;IACvB,OAAO,CAAC,YAAY,CAAqB;;IAMzC;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC;IAuBjD;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC;IAgB7C;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI;IAKtE;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAKnE;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAIhD;;AAED,wBAAyC"}
|
package/lib/index.js
CHANGED
|
@@ -7,7 +7,6 @@ const { PDF417Scanner } = react_native_1.NativeModules;
|
|
|
7
7
|
exports.PDF417CameraView = (0, react_native_1.requireNativeComponent)('PDF417CameraView');
|
|
8
8
|
class PDF417ScannerModule {
|
|
9
9
|
constructor() {
|
|
10
|
-
this.isScanning = false;
|
|
11
10
|
this.eventEmitter = new react_native_1.NativeEventEmitter(PDF417Scanner);
|
|
12
11
|
}
|
|
13
12
|
/**
|
|
@@ -48,60 +47,6 @@ class PDF417ScannerModule {
|
|
|
48
47
|
return false;
|
|
49
48
|
}
|
|
50
49
|
}
|
|
51
|
-
/**
|
|
52
|
-
* Start PDF417 scanning
|
|
53
|
-
*/
|
|
54
|
-
async startScanning(config = {}) {
|
|
55
|
-
if (this.isScanning) {
|
|
56
|
-
throw new Error('Scanner is already running');
|
|
57
|
-
}
|
|
58
|
-
const hasPermission = await this.hasCameraPermission();
|
|
59
|
-
if (!hasPermission) {
|
|
60
|
-
const granted = await this.requestCameraPermission();
|
|
61
|
-
if (!granted) {
|
|
62
|
-
throw new Error('Camera permission denied');
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
try {
|
|
66
|
-
await PDF417Scanner.startScanning(config);
|
|
67
|
-
this.isScanning = true;
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
throw new Error(`Failed to start scanning: ${error}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Stop PDF417 scanning
|
|
75
|
-
*/
|
|
76
|
-
async stopScanning() {
|
|
77
|
-
if (!this.isScanning) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
await PDF417Scanner.stopScanning();
|
|
82
|
-
this.isScanning = false;
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
throw new Error(`Failed to stop scanning: ${error}`);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Check if scanner is currently running
|
|
90
|
-
*/
|
|
91
|
-
isCurrentlyScanning() {
|
|
92
|
-
return this.isScanning;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Enable/disable torch (flashlight)
|
|
96
|
-
*/
|
|
97
|
-
async setTorchEnabled(enabled) {
|
|
98
|
-
try {
|
|
99
|
-
await PDF417Scanner.setTorchEnabled(enabled);
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
throw new Error(`Failed to set torch: ${error}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
50
|
/**
|
|
106
51
|
* Listen for scan results
|
|
107
52
|
*/
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAAkI;AAElI,MAAM,EAAE,aAAa,EAAE,GAAG,4BAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+CAAkI;AAElI,MAAM,EAAE,aAAa,EAAE,GAAG,4BAAa,CAAC;AAsBxC,+BAA+B;AAClB,QAAA,gBAAgB,GAAG,IAAA,qCAAsB,EAAwB,kBAAkB,CAAC,CAAC;AAElG,MAAM,mBAAmB;IAGvB;QACE,IAAI,CAAC,YAAY,GAAG,IAAI,iCAAkB,CAAC,aAAa,CAAC,CAAC;IAC5D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,uBAAuB;QAC3B,IAAI,uBAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,iCAAkB,CAAC,OAAO,CAC9C,iCAAkB,CAAC,WAAW,CAAC,MAAM,EACrC;gBACE,KAAK,EAAE,mBAAmB;gBAC1B,OAAO,EAAE,sDAAsD;gBAC/D,aAAa,EAAE,cAAc;gBAC7B,cAAc,EAAE,QAAQ;gBACxB,cAAc,EAAE,IAAI;aACrB,CACF,CAAC;YACF,OAAO,OAAO,KAAK,iCAAkB,CAAC,OAAO,CAAC,OAAO,CAAC;QACxD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB;QACvB,IAAI,uBAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,aAAa,GAAG,MAAM,iCAAkB,CAAC,KAAK,CAClD,iCAAkB,CAAC,WAAW,CAAC,MAAM,CACtC,CAAC;YACF,OAAO,aAAa,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;YAC7C,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAA4C;QACvD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QACjF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,QAA0C;QACpD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;QAChF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAoB;QAChC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;QAClF,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;IACrC,CAAC;CACF;AAED,kBAAe,IAAI,mBAAmB,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
package com.pdf417scanner;
|
|
2
|
-
|
|
3
|
-
import android.app.Activity;
|
|
4
|
-
import android.content.Context;
|
|
5
|
-
import android.graphics.ImageFormat;
|
|
6
|
-
import android.hardware.camera2.CameraAccessException;
|
|
7
|
-
import android.hardware.camera2.CameraCaptureSession;
|
|
8
|
-
import android.hardware.camera2.CameraCharacteristics;
|
|
9
|
-
import android.hardware.camera2.CameraDevice;
|
|
10
|
-
import android.hardware.camera2.CameraManager;
|
|
11
|
-
import android.hardware.camera2.CaptureRequest;
|
|
12
|
-
import android.hardware.camera2.params.StreamConfigurationMap;
|
|
13
|
-
import android.media.Image;
|
|
14
|
-
import android.media.ImageReader;
|
|
15
|
-
import android.os.Handler;
|
|
16
|
-
import android.os.HandlerThread;
|
|
17
|
-
import android.util.Log;
|
|
18
|
-
import android.util.Size;
|
|
19
|
-
import android.view.Surface;
|
|
20
|
-
|
|
21
|
-
import androidx.annotation.NonNull;
|
|
22
|
-
|
|
23
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
24
|
-
import com.google.zxing.BarcodeFormat;
|
|
25
|
-
import com.google.zxing.BinaryBitmap;
|
|
26
|
-
import com.google.zxing.DecodeHintType;
|
|
27
|
-
import com.google.zxing.MultiFormatReader;
|
|
28
|
-
import com.google.zxing.PlanarYUVLuminanceSource;
|
|
29
|
-
import com.google.zxing.Result;
|
|
30
|
-
import com.google.zxing.common.HybridBinarizer;
|
|
31
|
-
|
|
32
|
-
import java.nio.ByteBuffer;
|
|
33
|
-
import java.util.Arrays;
|
|
34
|
-
import java.util.EnumMap;
|
|
35
|
-
import java.util.EnumSet;
|
|
36
|
-
import java.util.Map;
|
|
37
|
-
import java.util.concurrent.Semaphore;
|
|
38
|
-
import java.util.concurrent.TimeUnit;
|
|
39
|
-
|
|
40
|
-
public class PDF417CameraManager {
|
|
41
|
-
private static final String TAG = "PDF417CameraManager";
|
|
42
|
-
|
|
43
|
-
private ReactApplicationContext reactContext;
|
|
44
|
-
private PDF417ScannerModule scannerModule;
|
|
45
|
-
private CameraManager cameraManager;
|
|
46
|
-
private CameraDevice cameraDevice;
|
|
47
|
-
private CameraCaptureSession captureSession;
|
|
48
|
-
private ImageReader imageReader;
|
|
49
|
-
private HandlerThread backgroundThread;
|
|
50
|
-
private Handler backgroundHandler;
|
|
51
|
-
private MultiFormatReader multiFormatReader;
|
|
52
|
-
private Semaphore cameraOpenCloseLock = new Semaphore(1);
|
|
53
|
-
private String cameraId;
|
|
54
|
-
private Size previewSize;
|
|
55
|
-
private boolean isScanning = false;
|
|
56
|
-
private PDF417ScannerConfig config;
|
|
57
|
-
|
|
58
|
-
public PDF417CameraManager(ReactApplicationContext reactContext, PDF417ScannerModule scannerModule) {
|
|
59
|
-
this.reactContext = reactContext;
|
|
60
|
-
this.scannerModule = scannerModule;
|
|
61
|
-
this.cameraManager = (CameraManager) reactContext.getSystemService(Context.CAMERA_SERVICE);
|
|
62
|
-
setupBarcodeReader();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private void setupBarcodeReader() {
|
|
66
|
-
multiFormatReader = new MultiFormatReader();
|
|
67
|
-
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
|
|
68
|
-
hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.of(BarcodeFormat.PDF_417));
|
|
69
|
-
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
|
|
70
|
-
multiFormatReader.setHints(hints);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
public void startScanning(PDF417ScannerConfig config) throws Exception {
|
|
74
|
-
this.config = config;
|
|
75
|
-
startBackgroundThread();
|
|
76
|
-
openCamera();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
public void stopScanning() {
|
|
80
|
-
isScanning = false;
|
|
81
|
-
closeCamera();
|
|
82
|
-
stopBackgroundThread();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
public void setTorchEnabled(boolean enabled) throws CameraAccessException {
|
|
86
|
-
if (captureSession != null && cameraDevice != null) {
|
|
87
|
-
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
|
88
|
-
builder.addTarget(imageReader.getSurface());
|
|
89
|
-
builder.set(CaptureRequest.FLASH_MODE, enabled ?
|
|
90
|
-
CaptureRequest.FLASH_MODE_TORCH : CaptureRequest.FLASH_MODE_OFF);
|
|
91
|
-
captureSession.setRepeatingRequest(builder.build(), null, backgroundHandler);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
private void startBackgroundThread() {
|
|
96
|
-
backgroundThread = new HandlerThread("CameraBackground");
|
|
97
|
-
backgroundThread.start();
|
|
98
|
-
backgroundHandler = new Handler(backgroundThread.getLooper());
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
private void stopBackgroundThread() {
|
|
102
|
-
if (backgroundThread != null) {
|
|
103
|
-
backgroundThread.quitSafely();
|
|
104
|
-
try {
|
|
105
|
-
backgroundThread.join();
|
|
106
|
-
backgroundThread = null;
|
|
107
|
-
backgroundHandler = null;
|
|
108
|
-
} catch (InterruptedException e) {
|
|
109
|
-
Log.e(TAG, "Error stopping background thread", e);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private void openCamera() throws Exception {
|
|
115
|
-
if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
|
116
|
-
throw new RuntimeException("Time out waiting to lock camera opening.");
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
cameraId = selectCamera();
|
|
121
|
-
if (cameraId == null) {
|
|
122
|
-
throw new RuntimeException("No suitable camera found");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
setupImageReader();
|
|
126
|
-
cameraManager.openCamera(cameraId, stateCallback, backgroundHandler);
|
|
127
|
-
} catch (CameraAccessException e) {
|
|
128
|
-
throw new RuntimeException("Failed to open camera", e);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
private String selectCamera() throws CameraAccessException {
|
|
133
|
-
for (String cameraId : cameraManager.getCameraIdList()) {
|
|
134
|
-
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
|
|
135
|
-
Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
|
136
|
-
if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
|
|
137
|
-
StreamConfigurationMap map = characteristics.get(
|
|
138
|
-
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
|
139
|
-
if (map != null) {
|
|
140
|
-
previewSize = chooseOptimalSize(map.getOutputSizes(ImageFormat.YUV_420_888));
|
|
141
|
-
return cameraId;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private Size chooseOptimalSize(Size[] choices) {
|
|
149
|
-
for (Size size : choices) {
|
|
150
|
-
if (size.getWidth() <= 1920 && size.getHeight() <= 1080) {
|
|
151
|
-
return size;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
return choices[0];
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private void setupImageReader() {
|
|
158
|
-
imageReader = ImageReader.newInstance(previewSize.getWidth(), previewSize.getHeight(),
|
|
159
|
-
ImageFormat.YUV_420_888, 2);
|
|
160
|
-
imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
|
|
164
|
-
@Override
|
|
165
|
-
public void onOpened(@NonNull CameraDevice camera) {
|
|
166
|
-
cameraOpenCloseLock.release();
|
|
167
|
-
cameraDevice = camera;
|
|
168
|
-
createCameraPreviewSession();
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
@Override
|
|
172
|
-
public void onDisconnected(@NonNull CameraDevice camera) {
|
|
173
|
-
cameraOpenCloseLock.release();
|
|
174
|
-
camera.close();
|
|
175
|
-
cameraDevice = null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
@Override
|
|
179
|
-
public void onError(@NonNull CameraDevice camera, int error) {
|
|
180
|
-
cameraOpenCloseLock.release();
|
|
181
|
-
camera.close();
|
|
182
|
-
cameraDevice = null;
|
|
183
|
-
scannerModule.onScanError("CAMERA_ERROR", "Camera error: " + error);
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
private void createCameraPreviewSession() {
|
|
188
|
-
try {
|
|
189
|
-
CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
|
|
190
|
-
builder.addTarget(imageReader.getSurface());
|
|
191
|
-
|
|
192
|
-
if (config.isEnableAutoFocus()) {
|
|
193
|
-
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
cameraDevice.createCaptureSession(Arrays.asList(imageReader.getSurface()),
|
|
197
|
-
new CameraCaptureSession.StateCallback() {
|
|
198
|
-
@Override
|
|
199
|
-
public void onConfigured(@NonNull CameraCaptureSession session) {
|
|
200
|
-
if (cameraDevice == null) return;
|
|
201
|
-
|
|
202
|
-
captureSession = session;
|
|
203
|
-
try {
|
|
204
|
-
session.setRepeatingRequest(builder.build(), null, backgroundHandler);
|
|
205
|
-
isScanning = true;
|
|
206
|
-
scannerModule.onCameraReady();
|
|
207
|
-
} catch (CameraAccessException e) {
|
|
208
|
-
Log.e(TAG, "Error starting camera preview", e);
|
|
209
|
-
scannerModule.onScanError("CAMERA_ERROR", "Failed to start preview");
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
@Override
|
|
214
|
-
public void onConfigureFailed(@NonNull CameraCaptureSession session) {
|
|
215
|
-
scannerModule.onScanError("CAMERA_ERROR", "Failed to configure camera");
|
|
216
|
-
}
|
|
217
|
-
}, null);
|
|
218
|
-
} catch (CameraAccessException e) {
|
|
219
|
-
Log.e(TAG, "Error creating camera preview session", e);
|
|
220
|
-
scannerModule.onScanError("CAMERA_ERROR", "Failed to create preview session");
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
private final ImageReader.OnImageAvailableListener onImageAvailableListener =
|
|
225
|
-
new ImageReader.OnImageAvailableListener() {
|
|
226
|
-
@Override
|
|
227
|
-
public void onImageAvailable(ImageReader reader) {
|
|
228
|
-
if (!isScanning) return;
|
|
229
|
-
|
|
230
|
-
Image image = reader.acquireLatestImage();
|
|
231
|
-
if (image != null) {
|
|
232
|
-
try {
|
|
233
|
-
processImage(image);
|
|
234
|
-
} finally {
|
|
235
|
-
image.close();
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
private void processImage(Image image) {
|
|
242
|
-
try {
|
|
243
|
-
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
|
|
244
|
-
byte[] data = new byte[buffer.remaining()];
|
|
245
|
-
buffer.get(data);
|
|
246
|
-
|
|
247
|
-
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
|
|
248
|
-
data, image.getWidth(), image.getHeight(), 0, 0,
|
|
249
|
-
image.getWidth(), image.getHeight(), false);
|
|
250
|
-
|
|
251
|
-
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
|
252
|
-
Result result = multiFormatReader.decode(bitmap);
|
|
253
|
-
|
|
254
|
-
if (result != null) {
|
|
255
|
-
scannerModule.onScanResult(result.getText(), result.getBarcodeFormat().toString());
|
|
256
|
-
}
|
|
257
|
-
} catch (Exception e) {
|
|
258
|
-
// No barcode found, continue scanning
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
private void closeCamera() {
|
|
263
|
-
try {
|
|
264
|
-
cameraOpenCloseLock.acquire();
|
|
265
|
-
if (captureSession != null) {
|
|
266
|
-
captureSession.close();
|
|
267
|
-
captureSession = null;
|
|
268
|
-
}
|
|
269
|
-
if (cameraDevice != null) {
|
|
270
|
-
cameraDevice.close();
|
|
271
|
-
cameraDevice = null;
|
|
272
|
-
}
|
|
273
|
-
if (imageReader != null) {
|
|
274
|
-
imageReader.close();
|
|
275
|
-
imageReader = null;
|
|
276
|
-
}
|
|
277
|
-
} catch (InterruptedException e) {
|
|
278
|
-
throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
|
|
279
|
-
} finally {
|
|
280
|
-
cameraOpenCloseLock.release();
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
package com.pdf417scanner;
|
|
2
|
-
|
|
3
|
-
public class PDF417ScannerConfig {
|
|
4
|
-
private boolean enableAutoFocus = true;
|
|
5
|
-
private boolean enableTorch = false;
|
|
6
|
-
private int scanTimeout = 30000; // 30 seconds
|
|
7
|
-
private boolean enableBeep = true;
|
|
8
|
-
private boolean enableVibration = true;
|
|
9
|
-
|
|
10
|
-
public boolean isEnableAutoFocus() {
|
|
11
|
-
return enableAutoFocus;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
public void setEnableAutoFocus(boolean enableAutoFocus) {
|
|
15
|
-
this.enableAutoFocus = enableAutoFocus;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
public boolean isEnableTorch() {
|
|
19
|
-
return enableTorch;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public void setEnableTorch(boolean enableTorch) {
|
|
23
|
-
this.enableTorch = enableTorch;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public int getScanTimeout() {
|
|
27
|
-
return scanTimeout;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public void setScanTimeout(int scanTimeout) {
|
|
31
|
-
this.scanTimeout = scanTimeout;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
public boolean isEnableBeep() {
|
|
35
|
-
return enableBeep;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
public void setEnableBeep(boolean enableBeep) {
|
|
39
|
-
this.enableBeep = enableBeep;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public boolean isEnableVibration() {
|
|
43
|
-
return enableVibration;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
public void setEnableVibration(boolean enableVibration) {
|
|
47
|
-
this.enableVibration = enableVibration;
|
|
48
|
-
}
|
|
49
|
-
}
|