2012-06-16 24 views
7

Rozwijam aplikację dla systemu Android i muszę zakodować i odkodować tablicę bajtów w QRCode wygenerowanym przy pomocy aplikacji ZXing. Mój problem polega na tym, że moja dekodowana wiadomość nie pasuje dokładnie do wygenerowanej tablicy bajtów. że próba utworzenia Qrcode na podstawie tablicy bajtów zawierających wskaźniki inkrementację, tjKodowanie i dekodowanie bajtu [] z ZXingiem

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

i po zakodowaniu komunikatu w Qrcode i dekoduje go z boku reagujących, to otrzymuje się następujące dane wyjściowe tablicy bajt:

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

Wszystkie wartości "ujemnego" bajtu są zamieniane na znak ASCII 63: "?" znaki zapytania. Zakładam, że coś jest nie tak z kodowaniem kodu, ale ponieważ używam ISO-8859-1, który wszyscy uważają za rozwiązanie tego rodzaju problemu (other topic treating the same kind of issue lub here), nie widzę, gdzie jest mój błąd lub jeśli pomijam krok podczas wprowadzania kodowania lub dekodowania. Oto kod, który wykona kodować daną tablicę bajtów:

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

I zdekodować QRCode, wyślę następujące 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); 
} 

I czekać na wynik:

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

} 

Czy możesz mi powiedzieć, gdzie są moje błędy lub gdzie powinienem patrzeć?

Dziękuję dużo,

Franck

+0

Po prostu "baw się" (nie mam pojęcia o tym), co się stanie, jeśli użyjesz kodowania UTF-8 na przykład? – Ixx

+0

UTF-8 na pewno nie zadziała. Nie każda sekwencja bajtów jest prawidłową sekwencją UTF-8, aby rozpocząć. Tak więc nie jest możliwe uzyskanie ciągu z większości wejść w ten sposób. –

Odpowiedz

2

robisz błąd myśląc, że można włączyć dowolne dane binarne do ważnego łańcucha bez użycia jakiegoś opancerzenia. To nie działa. Binarny -> tekst -> binarny jest stratny przy użyciu dowolnego ze standardowych zestawów znaków/kodowania. (Podpowiedź: używanie UTF-8 również nie będzie działać.)

Powinieneś użyć czegoś takiego jak kodowanie base64 lub kodowanie szesnastkowe, aby zapewnić, że dane binarne nie zostaną zmazane.

+1

Zgadzam się z ogólnymi odczuciami; ISO-8559-1 działa jednak w tym celu w Javie. –

+0

@StephenC Dziękuję bardzo, używając kodowania base64 w mojej implementacji rozwiązałem problem! – franckysnow

+1

@SeanOwen Zgadzam się z Tobą, kodowanie i dekodowanie bajtu [] do String ISO-8859-1 i na odwrót działa. Problem może znajdować się na warstwie ZXing. Jednak base64 rozwiązał sprawę. – franckysnow

1

Koncepcyjnie, kody QR kodują tekst, a nie bajty. Wewnątrz oczywiście tłumaczą dane wejściowe na serię bajtów, ale jest to nieprzejrzyste dla osoby dzwoniącej. Masz rację, że tak, jak to się dzieje, wybór właściwego kodowania pozwoliłby zakraść bajty, a ISO-8859-1 jest właściwym wyborem. W rzeczywistości działa.

ASCII nie jest możliwe, ponieważ nie definiuje znaki dla> = 128, i UTF-8 nie jest na pewno będzie działać

Chodzi tu prawdopodobnie Twój kod. Nie jestem pewien, co tutaj próbujesz ... wygląda na to, że masz gdzieś wysłać (do skanera kodów kreskowych?) Intent, ale nie robisz tego, po prostu robisz Intent i przesyłasz do jakiś kod skopiowany z projektu? Wyobrażam sobie, że coś poszło nie tak z tym, jak ustawiasz dodatki do Intent.

To powinno być znacznie prostsze, jeśli robisz to w swojej aplikacji. Po prostu ponownie użyj QRCodeEncoder.encodeAsBitmap() bezpośrednio i usuń resztę.

+0

Jedyny konstruktor 'QRCodeEncoder' pobiera dla argumentów' QRCodeEncoder (Activity activity, Intent intent, int wymiar, boolean useVCard) '. A ponieważ nie ma metod setera, przyszło mi do głowy, że to jedyny sposób, aby przejść. Jeśli mógłbyś być bardziej konkretny o tym, co może "pójść nie tak" z dodatkami? Wygląda na to, że kodowanie base64 i przekazywanie do niego kodu ISO8859-1 do 'QRCodeEncoder' sprawiło, że udało się. Dzięki! – franckysnow

+0

Mam na myśli, że w ogóle nie potrzebujesz tej klasy - po prostu skopiuj wskazaną przeze mnie metodę. Kod w 'android /' nie jest przeznaczony jako biblioteka; to nasza aplikacja. Głównym problemem jest to, że robisz coś zbędnego tutaj - słuchając "intencji", kiedy nie wysłałeś odpowiedzi. Przeczytaj javadoc dla kluczy - "FORMAT" nie ma nic wspólnego z kodowaniem znaków i ustawiasz go dwukrotnie. –

4

W jednej z moich aplikacji musiałem zakodować i odkodować tablicę bajtów w QRCode wygenerowanym przy pomocy aplikacji ZXing.Ponieważ tablica bajtów zawierała dane skompresowanego tekstu, chciałem uniknąć kodowania base64. Możliwe jest to zrobić, ale jak dotąd nie widziałem kompletnego zestawu fragmentów kodu, które opublikuję tutaj.

Kodowanie:

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

skanowanie Start:

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

obsługi skanowania wynik:

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

I nie myśl ustawienie zestaw_znaków do ISO-8859-1 w danych intencyjny Rozpoczęcie skanowania jest punktem, który sprawił, że kod oryginalnego pytania nie powiódł się. Zajęło mi to trochę czasu, aby to wykopać, ponieważ nie widziałem tego wyraźnie w dowolnym miejscu, a kodowanie Latin 1 jest standardowym kodowaniem kodu QR w Xzing. Szczególnie trudne jest to, że dekoder online Xzing http://zxing.org/w/decode.jspx nie ustawia również funkcji CHARACTER_SET, aby wygenerowany kod QR wyglądał wadliwie po odkodowaniu na tej stronie.