X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=android%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fclient%2Fandroid%2Fencode%2FQRCodeEncoder.java;h=0ba2d22e41a942363b8bcd4f4b483cd7ebbe9424;hb=4d43caef630b41adf09431881e7d834d2c291539;hp=4e1d9fb762613acf1d853957493dd07d3e7635ad;hpb=a48f3a059a3838500650f73151134167176d5579;p=zxing.git diff --git a/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java b/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java index 4e1d9fb7..0ba2d22e 100755 --- a/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java +++ b/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java @@ -17,6 +17,7 @@ package com.google.zxing.client.android.encode; import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.Result; import com.google.zxing.WriterException; @@ -26,7 +27,7 @@ import com.google.zxing.client.android.R; import com.google.zxing.client.result.AddressBookParsedResult; import com.google.zxing.client.result.ParsedResult; import com.google.zxing.client.result.ResultParser; -import com.google.zxing.common.ByteMatrix; +import com.google.zxing.common.BitMatrix; import android.app.Activity; import android.content.Intent; @@ -34,14 +35,13 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Handler; -import android.os.Message; import android.provider.Contacts; import android.telephony.PhoneNumberUtils; import android.util.Log; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.Hashtable; /** * This class does the work of decoding the user's request and extracting all the data @@ -50,13 +50,19 @@ import java.io.InputStream; * @author dswitkin@google.com (Daniel Switkin) */ final class QRCodeEncoder { + + private static final String TAG = QRCodeEncoder.class.getSimpleName(); + + private static final int WHITE = 0xFFFFFFFF; + private static final int BLACK = 0xFF000000; + private final Activity activity; private String contents; private String displayContents; private String title; private BarcodeFormat format; - public QRCodeEncoder(Activity activity, Intent intent) { + QRCodeEncoder(Activity activity, Intent intent) { this.activity = activity; if (intent == null) { throw new IllegalArgumentException("No valid data to encode."); @@ -69,7 +75,7 @@ final class QRCodeEncoder { } } else if (action.equals(Intent.ACTION_SEND)) { if (!encodeContentsFromShareIntent(intent)) { - throw new IllegalArgumentException("No valid data to encode."); + throw new IllegalArgumentException("No valid data to encode."); } } } @@ -100,9 +106,15 @@ final class QRCodeEncoder { // but we use platform specific code like PhoneNumberUtils, so it can't. private boolean encodeContentsFromZXingIntent(Intent intent) { // Default to QR_CODE if no format given. - String format = intent.getStringExtra(Intents.Encode.FORMAT); - if (format == null || format.length() == 0 || - format.equals(Contents.Format.QR_CODE)) { + String formatString = intent.getStringExtra(Intents.Encode.FORMAT); + try { + format = BarcodeFormat.valueOf(formatString); + } catch (IllegalArgumentException iae) { + // Ignore it then + format = null; + formatString = null; + } + if (format == null || BarcodeFormat.QR_CODE.equals(format)) { String type = intent.getStringExtra(Intents.Encode.TYPE); if (type == null || type.length() == 0) { return false; @@ -111,23 +123,10 @@ final class QRCodeEncoder { encodeQRCodeContents(intent, type); } else { String data = intent.getStringExtra(Intents.Encode.DATA); - if (data != null && data.length() != 0) { + if (data != null && data.length() > 0) { contents = data; displayContents = data; title = activity.getString(R.string.contents_text); - if (format.equals(Contents.Format.CODE_128)) { - this.format = BarcodeFormat.CODE_128; - } else if (format.equals(Contents.Format.CODE_39)) { - this.format = BarcodeFormat.CODE_39; - } else if (format.equals(Contents.Format.EAN_8)) { - this.format = BarcodeFormat.EAN_8; - } else if (format.equals(Contents.Format.EAN_13)) { - this.format = BarcodeFormat.EAN_13; - } else if (format.equals(Contents.Format.UPC_A)) { - this.format = BarcodeFormat.UPC_A; - } else if (format.equals(Contents.Format.UPC_E)) { - this.format = BarcodeFormat.UPC_E; - } } } return contents != null && contents.length() > 0; @@ -140,20 +139,35 @@ final class QRCodeEncoder { Uri uri = (Uri)intent.getExtras().getParcelable(Intent.EXTRA_STREAM); InputStream stream = activity.getContentResolver().openInputStream(uri); int length = stream.available(); + if (length <= 0) { + Log.w(TAG, "Content stream is empty"); + return false; + } byte[] vcard = new byte[length]; - stream.read(vcard, 0, length); - String vcardString = new String(vcard, "utf-8"); + int bytesRead = stream.read(vcard, 0, length); + if (bytesRead < length) { + Log.w(TAG, "Unable to fully read available bytes from content stream"); + return false; + } + String vcardString = new String(vcard, 0, bytesRead, "UTF-8"); + Log.d(TAG, "Encoding share intent content:"); + Log.d(TAG, vcardString); Result result = new Result(vcardString, vcard, null, BarcodeFormat.QR_CODE); ParsedResult parsedResult = ResultParser.parseResult(result); if (!(parsedResult instanceof AddressBookParsedResult)) { + Log.d(TAG, "Result was not an address"); return false; } if (!encodeQRCodeContents((AddressBookParsedResult) parsedResult)) { + Log.d(TAG, "Unable to encode contents"); return false; } - } catch (FileNotFoundException e) { - return false; } catch (IOException e) { + Log.w(TAG, e); + return false; + } catch (NullPointerException e) { + Log.w(TAG, e); + // In case the uri was not found in the Intent. return false; } return contents != null && contents.length() > 0; @@ -168,22 +182,22 @@ final class QRCodeEncoder { title = activity.getString(R.string.contents_text); } } else if (type.equals(Contents.Type.EMAIL)) { - String data = intent.getStringExtra(Intents.Encode.DATA); - if (data != null && data.length() > 0) { + String data = trim(intent.getStringExtra(Intents.Encode.DATA)); + if (data != null) { contents = "mailto:" + data; displayContents = data; title = activity.getString(R.string.contents_email); } } else if (type.equals(Contents.Type.PHONE)) { - String data = intent.getStringExtra(Intents.Encode.DATA); - if (data != null && data.length() > 0) { + String data = trim(intent.getStringExtra(Intents.Encode.DATA)); + if (data != null) { contents = "tel:" + data; displayContents = PhoneNumberUtils.formatNumber(data); title = activity.getString(R.string.contents_phone); } } else if (type.equals(Contents.Type.SMS)) { - String data = intent.getStringExtra(Intents.Encode.DATA); - if (data != null && data.length() > 0) { + String data = trim(intent.getStringExtra(Intents.Encode.DATA)); + if (data != null) { contents = "sms:" + data; displayContents = PhoneNumberUtils.formatNumber(data); title = activity.getString(R.string.contents_sms); @@ -194,26 +208,26 @@ final class QRCodeEncoder { StringBuilder newContents = new StringBuilder(); StringBuilder newDisplayContents = new StringBuilder(); newContents.append("MECARD:"); - String name = bundle.getString(Contacts.Intents.Insert.NAME); - if (name != null && name.length() > 0) { + String name = trim(bundle.getString(Contacts.Intents.Insert.NAME)); + if (name != null) { newContents.append("N:").append(name).append(';'); newDisplayContents.append(name); } - String address = bundle.getString(Contacts.Intents.Insert.POSTAL); - if (address != null && address.length() > 0) { + String address = trim(bundle.getString(Contacts.Intents.Insert.POSTAL)); + if (address != null) { newContents.append("ADR:").append(address).append(';'); newDisplayContents.append('\n').append(address); } for (int x = 0; x < Contents.PHONE_KEYS.length; x++) { - String phone = bundle.getString(Contents.PHONE_KEYS[x]); - if (phone != null && phone.length() > 0) { + String phone = trim(bundle.getString(Contents.PHONE_KEYS[x])); + if (phone != null) { newContents.append("TEL:").append(phone).append(';'); newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone)); } } for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) { - String email = bundle.getString(Contents.EMAIL_KEYS[x]); - if (email != null && email.length() > 0) { + String email = trim(bundle.getString(Contents.EMAIL_KEYS[x])); + if (email != null) { newContents.append("EMAIL:").append(email).append(';'); newDisplayContents.append('\n').append(email); } @@ -250,19 +264,27 @@ final class QRCodeEncoder { newContents.append("MECARD:"); String[] names = contact.getNames(); if (names != null && names.length > 0) { - newContents.append("N:").append(names[0]).append(';'); - newDisplayContents.append(names[0]); + String name = trim(names[0]); + if (name != null) { + newContents.append("N:").append(name).append(';'); + newDisplayContents.append(name); + } } - String address = contact.getAddress(); - if (address != null && address.length() > 0) { - newContents.append("ADR:").append(address).append(';'); - newDisplayContents.append('\n').append(address); + String[] addresses = contact.getAddresses(); + if (addresses != null) { + for (String address : addresses) { + address = trim(address); + if (address != null) { + newContents.append("ADR:").append(address).append(';'); + newDisplayContents.append('\n').append(address); + } + } } String[] phoneNumbers = contact.getPhoneNumbers(); if (phoneNumbers != null) { - for (int x = 0; x < phoneNumbers.length; x++) { - String phone = phoneNumbers[x]; - if (phone != null && phone.length() > 0) { + for (String phone : phoneNumbers) { + phone = trim(phone); + if (phone != null) { newContents.append("TEL:").append(phone).append(';'); newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone)); } @@ -270,16 +292,16 @@ final class QRCodeEncoder { } String[] emails = contact.getEmails(); if (emails != null) { - for (int x = 0; x < emails.length; x++) { - String email = emails[x]; - if (email != null && email.length() > 0) { + for (String email : emails) { + email = trim(email); + if (email != null) { newContents.append("EMAIL:").append(email).append(';'); newDisplayContents.append('\n').append(email); } } } - String url = contact.getURL(); - if (url != null && url.length() > 0) { + String url = trim(contact.getURL()); + if (url != null) { newContents.append("URL:").append(url).append(';'); newDisplayContents.append('\n').append(url); } @@ -297,53 +319,50 @@ final class QRCodeEncoder { } } - private static final class EncodeThread extends Thread { - private static final String TAG = "EncodeThread"; - - private final String contents; - private final Handler handler; - private final int pixelResolution; - private final BarcodeFormat format; - - EncodeThread(String contents, Handler handler, int pixelResolution, - BarcodeFormat format) { - this.contents = contents; - this.handler = handler; - this.pixelResolution = pixelResolution; - this.format = format; + static Bitmap encodeAsBitmap(String contents, + BarcodeFormat format, + int desiredWidth, + int desiredHeight) throws WriterException { + Hashtable hints = null; + String encoding = guessAppropriateEncoding(contents); + if (encoding != null) { + hints = new Hashtable(2); + hints.put(EncodeHintType.CHARACTER_SET, encoding); + } + MultiFormatWriter writer = new MultiFormatWriter(); + BitMatrix result = writer.encode(contents, format, desiredWidth, desiredHeight, hints); + int width = result.getWidth(); + int height = result.getHeight(); + int[] pixels = new int[width * height]; + // All are 0, or black, by default + for (int y = 0; y < height; y++) { + int offset = y * width; + for (int x = 0; x < width; x++) { + pixels[offset + x] = result.get(x, y) ? BLACK : WHITE; + } } - @Override - public void run() { - try { - ByteMatrix result = new MultiFormatWriter().encode(contents, format, - pixelResolution, pixelResolution); - int width = result.getWidth(); - int height = result.getHeight(); - byte[][] array = result.getArray(); - int[] pixels = new int[width * height]; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int grey = array[y][x] & 0xff; - // pixels[y * width + x] = (0xff << 24) | (grey << 16) | (grey << 8) | grey; - pixels[y * width + x] = 0xff000000 | (0x00010101 * grey); - } - } + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, width, 0, 0, width, height); + return bitmap; + } - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); - Message message = Message.obtain(handler, R.id.encode_succeeded); - message.obj = bitmap; - message.sendToTarget(); - } catch (WriterException e) { - Log.e(TAG, e.toString()); - Message message = Message.obtain(handler, R.id.encode_failed); - message.sendToTarget(); - } catch (IllegalArgumentException e) { - Log.e(TAG, e.toString()); - Message message = Message.obtain(handler, R.id.encode_failed); - message.sendToTarget(); + private static String guessAppropriateEncoding(CharSequence contents) { + // Very crude at the moment + for (int i = 0; i < contents.length(); i++) { + if (contents.charAt(i) > 0xFF) { + return "UTF-8"; } } + return null; } + + private static String trim(String s) { + if (s == null) { + return null; + } + s = s.trim(); + return s.length() == 0 ? null : s; + } + }