Skip to content
This repository has been archived by the owner on Oct 10, 2020. It is now read-only.

Binary data in QR codes on iOS #201

Open
djlegge opened this issue Apr 1, 2020 · 3 comments
Open

Binary data in QR codes on iOS #201

djlegge opened this issue Apr 1, 2020 · 3 comments

Comments

@djlegge
Copy link

djlegge commented Apr 1, 2020

Hi
I'm using QR codes to transfer binary data. This does generally work if the encoding is set to ISO8859-1 in the QR code and the code reading library respects this (not all do).
Using barcode_scan on Android, the returned string is an exact binary copy of the QR code and the bytes can be accessed with .codeUnits which is perfect.
On iOS however, the returned string is truncated at the first null byte as if at some point it is being treated as a 'C' string where 0x00 terminates the string.
The current git master branch behaves the same.
It's not a normal use case I know but it would be great if the behaviour was the same on iOS as Android.
I'm happy to look into the source code but could do with some pointers about where to look. Also, I have no idea how to debug the calls into the iOS code from AndroidStudio...
Any help would be much appreciated !

@djlegge
Copy link
Author

djlegge commented Apr 1, 2020

In case it helps anybody else, the binary data is available, at least in iOS 11 or later but not in the normal stringValue of the scanned code.
void startScan() in Classes/BarcodeScannerViewController.m needs to be modified if the full QR code is to be returned.

In older ios versions, the data may be available but it is probably a bad idea to access it this way.
There seems to be a 4 byte header and 20 bytes extra at the end. I've stripped off the header but left the 20 bytes at the end.

By the way, I know C but not ObjectiveC so excuse any messiness...

- (void)startScan {
    NSError *error;
    [self.scanner startScanningWithResultBlock:^(NSArray<AVMetadataMachineReadableCodeObject *> *codes) {
        [self.scanner stopScanning];
         AVMetadataMachineReadableCodeObject *code = codes.firstObject;
        if (code) {
            char buffer[4096];
            NSData *data;
            if (@available(iOS 11.0, *)) {
                CIQRCodeDescriptor *test1 = (CIQRCodeDescriptor*)code.descriptor;
                data = test1.errorCorrectedPayload;
                [data getBytes:buffer range:NSMakeRange(0, data.length)];
                // Skip the first 4 bytes and the data starts there...
            } else {
                // Fallback on earlier versions. Not sure I can test this...
                AVMetadataMachineReadableCodeObject *test2;
                data = [test2 valueForKeyPath:@"_internal.basicDescriptor"][@"BarcodeRawData"];  // ios8, 9, 10. Dodgy.
                [data getBytes:buffer range:NSMakeRange(0, data.length)];
            }
            //[self.delegate barcodeScannerViewController:self didScanBarcodeWithResult:code.stringValue];      // Original return value.
            NSString* myString = [[NSString alloc] initWithBytes:(buffer + 4) length:(data.length - 4) encoding:NSISOLatin1StringEncoding];
            [self.delegate barcodeScannerViewController:self didScanBarcodeWithResult:myString];
            [self dismissViewControllerAnimated:NO completion:nil];
        }
    } error:&error];
}

@devtronic
Copy link
Member

Can you please provide an QR code which contains data with causes the problem?

@djlegge
Copy link
Author

djlegge commented Apr 21, 2020

No problem - see attached PNG.
With version 3.0.0 barcode.rawContent.codeUnits gives :
Android : [120, 218, 237, 210, 61, 106, 2, 81, 16, 0, 224, 183, 26, 127, 42, 211, 164, 22, 47, 176, 242, 246, 41, 145, 180, 166, 73, 44, 9......(length 194 bytes)
IOS : = [120, 218, 237, 210, 61, 106, 2, 81, 16] (length 9 bytes).

Mine is a pretty unusual use case so thanks for looking at it anyway.
combackQR

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants