Encoding and decoding byte [] with ZXing

I am developing an Android application, and I need to encode and decode an array of bytes in the QRCode generated by the ZXing application. My problem is that my message decoded does not exactly match the generated byte array. I tried to create a QRCode based on an array of bytes containing incremental indices, i.e.

input = [0, 1, 2, ..., 124, 125, 126, 127, -128, -127,... -3, -2, -1, 0, 1, 2, ...] 

And after encoding the message in QRCode and decoding it on the responder side, I get the following output of the byte array:

 output = [0, 1, 2, ..., 124, 125, 126, 127, 63, 63,... 63, 63, 63, 0, 1, 2, ...] 

All "negative" byte values ​​are rotated to ASCII char 63: '?' question mark. I assume that something is wrong with the encoding of the encoding, but since I use ISO-8859-1, which everyone claims to be a solution to this kind of problem ( another topic, considering the same kind of question or here ), I do not see where is my mistake, or if I skip a step during instanciation encoding or decoding. Here is the code that I am executing to encode a given byte array:

 String text = ""; byte[] res = new byte[272]; for (int i = 0; i < res.length; i++) { res[i] = (byte) (i%256); } try { text = new String(res, "ISO8859_1"); } catch (UnsupportedEncodingException e) { // TODO } Intent intent = new Intent(Intents.Encode.ACTION); Intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); intent.putExtra(Intents.Encode.TYPE, Contents.Type.TEXT); intent.putExtra(Intents.Encode.FORMAT, "ISO8859_1"); intent.putExtra(Intents.Encode.DATA, text); intent.putExtra(Intents.Encode.FORMAT, BarcodeFormat.QR_CODE.toString()); boolean useVCard = intent.getBooleanExtra(USE_VCARD_KEY, false); QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(activity, intent, dimension, useVCard); Bitmap bitmap = qrCodeEncoder.encodeAsBitmap(); 

And to decode the QRCode, I send the next Intent

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.qrcodeDecoding); Intent intent = new Intent(Intents.Scan.ACTION); intent.putExtra(Intents.Scan.MODE, Intents.Scan.QR_CODE_MODE); startActivityForResult(intent, 0); } 

And wait for the result:

 @Override protected void onActivityResult(int request, int result, Intent data) { if(request == 0) { //action if(result == RESULT_OK) { String res = data.getStringExtra(Intents.Scan.RESULT); byte[] dat = null; try{ dat = res.getBytes("ISO8859_1"); } catch(UnsopportedEncodingException e) { //TODO } } else if(result == RESULT_CANCELED) { //TODO } } } 

Could you tell me where are my mistakes, or where should I look?

Many thanks,

Franc

+7
source share
3 answers

You make a mistake thinking that you can turn arbitrary binary data into a valid string without using any kind of armor. This does not work. Binary β†’ text β†’ binary is lossy using any of the standard character / encoding sets. (Hint: Using UTF-8 will also not work.)

You should use something like base64 encoding or hexadecimal encoding to ensure that binary data is not corrupted.

+2
source

In one of my applications, I needed to encode and decode an array of bytes in the QRCode generated by the ZXing application. Since the byte array contained compressed text data, I wanted to avoid base64 encoding. This can be done, but since I still have not seen the full set of code snippets, I will post them here.

Encoding:

 public void showQRCode(Activity activity, byte[] data){ Intent intent = new Intent("com.google.zxing.client.android.ENCODE"); intent.putExtra("ENCODE_TYPE", "TEXT_TYPE"); intent.putExtra("ENCODE_SHOW_CONTENTS", false); intent.putExtra("ENCODE_DATA", new String(data, "ISO-8859-1")); activity.startActivity(intent); } 

Start Scan:

 public static void startQRCodeScan(Activity activity){ Intent intent = new Intent(com.google.zxing.client.android.SCAN); intent.putExtra("SCAN_MODE", "QR_CODE_MODE"); intent.putExtra("CHARACTER_SET", "ISO-8859-1"); activity.startActivityForResult(intent, 0); } 

Scan Result Handler:

 public void onActivityResult(int requestCode, int resultCode, Intent intent) { byte[] result = intent.getStringExtra("SCAN_RESULT").getBytes("ISO-8859-1"); ... } 

I think that not setting CHARACTER_SET in ISO-8859-1 in the intent data to start scanning is the point where the source question code does not work. It took me quite a while to dig it out, since I didn’t see it clearly posted anywhere, and Latin 1 encoding is the standard QR code encoding in Xzing. It is especially difficult to note the fact that the Xzing online decoder http://zxing.org/w/decode.jspx also does not set CHARACTER_SET, so the generated QR code appears to be malfunctioning when decoding to this site.

+4
source

Conceptually, QR codes encode text, not bytes. Inside, of course, they translate the input into a series of bytes, although this is not transparent to the caller. You are right that when this happens, choosing the right encoding will allow you to sneak through bytes, and here will be the right choice of ISO-8859-1. It really works.

ASCII is not possible because it does not define characters for> = 128, and UTF-8 will definitely not work

The problem here is probably in your code. I'm not sure what you are trying here ... it looks like you configured to send Intent somewhere (to a barcode scanner?), But then you won’t do this, you just do Intent and send it to some kind of code, which you copied from the project? I assume that something went wrong as you install additional functions in Intent .

It should be a lot easier if you do this in your application. Just reuse QRCodeEncoder.encodeAsBitmap() and remove the rest.

+1
source

All Articles