2012-06-16 11 views
7

Sto sviluppando un'applicazione Android e ho bisogno di codificare e decodificare una matrice di byte in un QRCode generato con l'app ZXing. Il mio problema è che il mio messaggio decodificato non corrisponde esattamente alla matrice di byte generata. Ho cercato di creare un QRCode basato su una matrice di byte contenente indici di incremento, cioèCodifica e decodifica byte [] con ZXing

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

E dopo che codifica il messaggio nel QRCode e decodifica sul lato risponditore, ottengo il seguente output byte:

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

Tutti i valori di byte "negativi" vengono convertiti in caratteri ASCII 63: '?' caratteri del punto interrogativo. Suppongo che qualcosa stia funzionando male con il set di caratteri di codifica, ma dal momento che sto usando ISO-8859-1 che tutti sostengono essere la soluzione di questo tipo di problema (other topic treating the same kind of issue o here), non vedo dove sia il mio errore , o se sto saltando un passo durante l'instanciazione della codifica o della decodifica. Ecco il codice che eseguo per codificare un dato array di byte:

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

E per decodificare un QRCode, mando il seguente intenti

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

e attendere Risultato:

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

} 

Potresti dirmi dove sono i miei errori, o dove dovrei guardare?

Grazie molto,

Franck

+0

Solo per "giocare" (non ne ho idea) cosa succede se usi la codifica UTF-8 come esempio? – Ixx

+0

UTF-8 sicuramente non funzionerà. Non tutte le sequenze di byte sono una sequenza UTF-8 valida, per iniziare. Quindi non è nemmeno possibile ottenere una stringa dalla maggior parte degli input in questo modo. –

risposta

2

Stai facendo l'errore di pensare che si può trasformare i dati binari arbitrari in una stringa valida senza l'utilizzo di un qualche tipo di armatura. Non funziona. Binary -> text -> binary è lossy utilizzando uno qualsiasi dei set di caratteri standard/codifica. (Suggerimento: l'utilizzo di UTF-8 non funzionerà neanche.)

È necessario utilizzare qualcosa come codifica base64 o codifica esadecimale per garantire che i dati binari non vengano manomessi.

+1

Sono d'accordo con il sentimento generale; Tuttavia, ISO-8559-1 funziona in questo modo in Java. –

+0

@StephenC Grazie mille, l'uso della codifica base64 nella mia implementazione ha risolto il problema! – franckysnow

+1

@SeanOwen Sono d'accordo con te, codifica e decodifica byte [] su String ISO-8859-1 e vice-versa funziona. Il problema potrebbe trovarsi sul livello ZXing. Tuttavia, base64 ha risolto il caso. – franckysnow

1

Concettualmente, i codici QR codificano il testo, non i byte. All'interno, naturalmente, traducono l'input in una serie di byte, anche se è opaco per il chiamante. Hai ragione che, come accade, scegliere la giusta codifica ti permetterebbe di far passare di nascosto i byte, e ISO-8859-1 è la scelta giusta qui. Funziona, in realtà.

ASCII non è possibile in quanto non definisce caratteri per> = 128, e UTF-8 non è sicuramente andare a lavorare

Il problema qui è probabilmente il vostro codice. Non sono sicuro di cosa stai tentando qui ... sembra che tu stia preparando per inviare uno Intent da qualche parte (a Barcode Scanner?) Ma poi non lo fai, stai solo facendo uno Intent e invialo a codice che hai copiato dal progetto? Immagino che qualcosa non abbia funzionato nel modo in cui imposti gli extra allo Intent.

Questo dovrebbe essere molto più semplice se lo stai facendo all'interno della tua app. È sufficiente riutilizzare direttamente QRCodeEncoder.encodeAsBitmap() ed eliminare il resto.

+0

L'unico costruttore di 'QRCodeEncoder' accetta argomenti' QRCodeEncoder (Attività attività, Intento intento, dimensione int, uso booleanoVCard) '. E poiché non ci sono metodi setter, mi sembra che sia l'unica via da percorrere. Se potessi essere un po 'più specifico su cosa potrebbe "andare storto" con gli extra? Sembra che la codifica base64 e il passaggio di una stringa ISO8859-1 al 'QRCodeEncoder' abbiano fatto il trucco. Grazie! – franckysnow

+0

Voglio dire che non hai affatto bisogno del corso - copia semplicemente il metodo che ho indicato. Il codice in 'android /' non è inteso come una libreria; è la nostra app. Il problema principale è che stai facendo qualcosa di superfluo qui - ascoltando un 'Intento 'quando non ne hai mandato uno a cui rispondere. Leggete javadoc per i tasti - 'FORMAT' non ha nulla a che fare con la codifica dei caratteri e la impostate due volte. –

4

In una delle mie app avevo bisogno di codificare e decodificare una matrice di byte in un QRCode generato con l'app ZXing.Poiché la matrice di byte conteneva dati di testo compressi, volevo evitare la codifica base64. È possibile farlo, ma poiché finora non ho visto un set completo di frammenti di codice, li posterò qui.

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

iniziare la scansione:

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

gestore di risultati di scansione:

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

Credo che non l'impostazione CHARACTER_SET a ISO-8859-1 nei dati intenti per l'avvio della scansione è il punto che ha reso il codice della domanda originale fallito. Mi ci è voluto un po 'di tempo per capire come non ho visto questo chiaramente pubblicato ovunque e la codifica Latin 1 è la codifica standard per il codice QR in Xzing. Particolarmente difficile è il fatto che il decodificatore online Xzing http://zxing.org/w/decode.jspx non imposti anche CHARACTER_SET in modo che il codice QR generato appaia difettoso quando viene decodificato su questo sito.

Problemi correlati