2012-06-16 5 views
7

Ich developping eine Android app, und ich brauche ein Byte-Array in einem QRCode mit der ZXing app erzeugt zu kodieren und dekodieren. Mein Problem ist, dass meine decodierte Nachricht nicht genau mit dem generierten Byte-Array übereinstimmt. ich versuchte, eine QRCode basierend auf einem Byte-Array, das Inkrementieren Indizes zu erzeugen, dhCodierung und Decodierung byte [] mit ZXing

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

und nach der Nachricht im QRCode Codierungs- und es auf den Responder-Seiten Dekodieren I den folgenden Byte-Array-Ausgang erhalten:

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

All "negative" Byte-Werte werden in ASCII-Zeichen 63 gedreht: '?' Fragezeichen. Ich gehe davon aus, dass etwas nicht stimmt mit der Codierung charset wird, aber da ich ISO-8859-1 bin mit der jeder die Lösung dieser Art von Problem zu sein behauptet (other topic treating the same kind of issue oder here), ich sehe nicht, wo mein Fehler ist oder wenn ich einen Schritt während der Einführung der Kodierung oder der Dekodierung überspringe. Hier ist der Code, den ich ausführen ein gegebenes Byte-Array zu kodieren:

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(); 

Und ein QRCode zu dekodieren, schicke ich die folgende 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); 
} 

und warten auf Ergebnis:

@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 
     } 
    } 

} 

Können Sie mir bitte sagen, wo meine Fehler liegen, oder wo soll ich hinschauen?

Danke viel,

Franck

+0

Nur um "herumspielen" (ich habe keine Ahnung davon) was passiert, wenn Sie UTF-8 als Codierung zum Beispiel verwenden? – Ixx

+0

UTF-8 wird sicherlich nicht funktionieren. Nicht jede Byte-Sequenz ist eine gültige UTF-8-Sequenz, um zu starten. Es ist also nicht einmal möglich, die meisten Eingaben auf diese Weise zu ersetzen. –

Antwort

2

Sie machen den Fehler zu denken, dass Sie, ohne irgendeine Art von Panzerungen beliebige binäre Daten in eine gültige Zeichenfolge drehen kann. Es funktioniert nicht. Binär -> Text -> Binär ist verlustbehaftet mit einem der Standard-Zeichensätze/Codierung. (Hinweis: UTF-8 wird nicht funktionieren.)

Sie sollten so etwas wie Base64-Kodierung oder hexadezimale Codierung verwenden, um sicherzustellen, dass die Binärdaten nicht verstümmelt bekommen.

+1

Ich stimme der Gesamtstimmung zu; Allerdings funktioniert ISO-8559-1 in Java für diesen Zweck. –

+0

@StephenC Vielen Dank, mit Base64 Encoding in meiner Implementierung löste das Problem! – franckysnow

+1

@SeanOwen Ich stimme dir zu, Codierung und Decodierung Byte [] zu String ISO-8859-1 und umgekehrt funktioniert. Das Problem befindet sich möglicherweise auf der ZXing-Ebene. Base64 löste den Fall jedoch. – franckysnow

1

Konzeptionell kodieren QR-Codes Text, nicht Bytes. Natürlich übersetzen sie Eingaben in eine Reihe von Bytes, obwohl das für den Aufrufer undurchsichtig ist. Sie haben recht, wenn Sie die richtige Kodierung wählen, können Sie die Bytes durchschleichen und ISO-8859-1 ist die richtige Wahl. Es funktioniert tatsächlich.

ASCII ist nicht möglich, da es für> = 128 nicht Zeichen zu definieren, und UTF-8 ist definitiv nicht

Die Frage ist hier arbeiten wahrscheinlich Code ist. Ich bin mir nicht sicher, was du hier versuchst ... es sieht so aus, als würdest du einen Intent irgendwo anstellen (zum Barcode Scanner?), Aber dann tust du es nicht, du machst nur einen Intent und schickst es an Code, den Sie aus dem Projekt kopiert haben? Ich kann mir vorstellen, dass mit der Einstellung der Extras für die Intent etwas falsch läuft.

Dies sollte viel einfacher sein, wenn Sie es in Ihrer App tun. Einfach QRCodeEncoder.encodeAsBitmap() direkt wiederverwenden und den Rest löschen.

+0

Der einzige Konstruktor von 'QRCodeEncoder' benötigt Argumente' QRCodeEncoder (Aktivität Aktivität, Intent Intent, int Dimension, boolean useVCard) '. Und da es keine Setter-Methoden gibt, fiel mir auf, dass dies der einzige Weg war. Wenn du etwas genauer sagen könntest, was mit den Extras "schiefgehen" könnte? Es scheint, dass die base64-Kodierung und die Übergabe einer ISO8859-1-Zeichenfolge an den 'QRCodeEncoder' den Trick gemacht haben. Vielen Dank! – franckysnow

+0

Ich meine, dass Sie die Klasse überhaupt nicht brauchen - kopieren Sie einfach die Methode, die ich angegeben habe. Der Code in 'android /' ist nicht als Bibliothek gedacht; Es ist unsere App. Das Hauptproblem besteht darin, dass Sie hier etwas überflüssiges tun - indem Sie auf eine "Absicht" warten, wenn Sie keine Antwort gesendet haben. Lies das Javadoc für die Schlüssel - 'FORMAT' ist nichts mit Zeichencodierung und du hast es zweimal eingestellt. –

4

In einer meiner Apps musste ich ein Byte-Array in einem mit der ZXing App generierten QRCode codieren und dekodieren.Da das Byte-Array komprimierte Textdaten enthielt, wollte ich die base64-Codierung vermeiden. Es ist möglich, dies zu tun, aber da ich bisher noch keinen vollständigen Code-Schnipsel gesehen habe, werde ich sie hier veröffentlichen.

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); 
} 

starten Scannen:

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 Ergebnis Handler:

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

Ich denke nicht CHARACTER_SET ISO-8859-1 in der Absicht Einstelldaten für Das Starten des Scans ist der Punkt, der den Code der ursprünglichen Frage fehlgeschlagen hat. Es hat einige Zeit gedauert, das herauszufinden, da ich das nirgendwo deutlich gesehen habe und Latin 1-Codierung ist die Standardcodierung für QR-Code in Xzing. Besonders heikel ist die Tatsache, dass der Xzing Online-Decoder http://zxing.org/w/decode.jspx auch CHARACTER_SET nicht gesetzt hat, so dass der erzeugte QR-Code beim Dekodieren auf dieser Seite fehlerhaft aussieht.