Search code examples
javaandroidreact-nativegoogle-mlkit

Java map.putString not working within listener


I am working on a program in Java that is reading QR codes from images. I have the following code:

@Override
    public Object callback(ImageProxy imageProxy, Object[] params) {
        WritableNativeMap writableNativeMap = new WritableNativeMap();

        BarcodeScannerOptions options =
                new BarcodeScannerOptions.Builder()
                        .setBarcodeFormats(Barcode.FORMAT_QR_CODE)
                        .build();

        Image mediaImage = imageProxy.getImage();

        final List<Barcode>[] barcodesList = new List[]{Collections.<Barcode>emptyList()};

        if (mediaImage != null) {
            InputImage image =
                    InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());

            BarcodeScanner scanner = BarcodeScanning.getClient(options);

            Task < List < Barcode >> result = scanner.process(image);

            result.addOnSuccessListener(new OnSuccessListener < List < Barcode >> () {
                @Override
                public void onSuccess(List < Barcode > barcodes) {
                    for (Barcode barcode: barcodes) {
                        int valueType = barcode.getValueType();

                        switch (valueType) {
                            case Barcode.TYPE_TEXT:
                                // TODO
                            case Barcode.TYPE_URL:
                                Log.d(TAG, barcode.getUrl().getUrl());
                                writableNativeMap.putString("URL", barcode.getUrl().getUrl());
                                // TODO
                                break;
                        }
                    }
                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    // ...
                }
            })
            .addOnCompleteListener(results -> imageProxy.close());
        }

        return writableNativeMap;
    }

When I call this function it will return {}. Even when it reached the Log.d statement in the Barcode.TYPE_URL case. So I know that it is putting stuff in the writableNativeMap. When I do a .putString just before the return statement then it works. Can someone help me with this?


Solution

  • Okay so to solve the problem I used a notifier as following:

        @Override
        public Object callback(ImageProxy imageProxy, Object[] params) {
            // Added this
            final AtomicReference<WritableNativeMap> notifier = new AtomicReference();
    
            WritableNativeMap writableNativeMap = new WritableNativeMap();
    
            BarcodeScannerOptions options =
                    new BarcodeScannerOptions.Builder()
                            .setBarcodeFormats(Barcode.FORMAT_QR_CODE)
                            .build();
    
            Image mediaImage = imageProxy.getImage();
    
            final List<Barcode>[] barcodesList = new List[]{Collections.<Barcode>emptyList()};
    
            if (mediaImage != null) {
                InputImage image =
                        InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees());
    
                BarcodeScanner scanner = BarcodeScanning.getClient(options);
    
                Task < List < Barcode >> result = scanner.process(image);
    
                result.addOnSuccessListener(new OnSuccessListener < List < Barcode >> () {
                    @Override
                    public void onSuccess(List < Barcode > barcodes) {
                        if (barcodes.size() > 0){
                            Barcode barcode = barcodes.get(0);
    
                            int valueType = barcode.getValueType();
    
                            switch (valueType) {
                                case Barcode.TYPE_TEXT:
                                    writableNativeMap.putString("type", "TEXT");
                                    writableNativeMap.putString("value", barcode.getRawValue());
                                    break;
                                case Barcode.TYPE_URL:
                                    writableNativeMap.putString("type", "URL");
                                    writableNativeMap.putString("value", barcode.getUrl().getUrl());
                                    break;
                                default:
                                    writableNativeMap.putString("type", "OTHER");
                                    writableNativeMap.putString("value", barcode.getRawValue());
                            }
                        }
    
                        // Added this
                        synchronized (notifier) {
                            notifier.set(writableNativeMap);
                            notifier.notify();
                        }
                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        // Added this
                        synchronized (notifier) {
                            notifier.set(writableNativeMap);
                            notifier.notify();
                        }
                    }
                })
                .addOnCompleteListener(results -> imageProxy.close());
            }
    
            // Added this
            synchronized (notifier) {
                while (notifier.get() == null) {
                    try {
                        notifier.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
    
            return notifier.get();
        }