Handle empty string as null in many cases
[zxing.git] / android / src / com / google / zxing / client / android / encode / QRCodeEncoder.java
index 0a7a395..0ba2d22 100755 (executable)
@@ -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;
@@ -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
@@ -106,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;
@@ -117,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;
@@ -146,23 +139,34 @@ 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");
-      Log.d(TAG, "Encoding share intent content: " + vcardString);
+      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;
     }
@@ -178,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);
@@ -204,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);
           }
@@ -260,23 +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[] addresses = contact.getAddresses();
     if (addresses != null) {
-      for (int x = 0; x < addresses.length; x++) {
-        if (addresses[x] != null && addresses[x].length() > 0) {
-          newContents.append("ADR:").append(addresses[x]).append(';');
-          newDisplayContents.append('\n').append(addresses[x]);
+      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));
         }
@@ -284,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);
     }
@@ -315,8 +323,14 @@ final class QRCodeEncoder {
                                BarcodeFormat format,
                                int desiredWidth,
                                int desiredHeight) throws WriterException {
-    BitMatrix result = new MultiFormatWriter().encode(contents, format,
-        desiredWidth, desiredHeight);
+    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];
@@ -333,39 +347,22 @@ final class QRCodeEncoder {
     return bitmap;
   }
 
-  private static final class EncodeThread extends Thread {
-
-    private static final String TAG = EncodeThread.class.getSimpleName();
-
-    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;
+  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;
+  }
 
-    @Override
-    public void run() {
-      try {
-        Bitmap bitmap = encodeAsBitmap(contents, format, pixelResolution, pixelResolution);
-        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 trim(String s) {
+    if (s == null) {
+      return null;
     }
+    s = s.trim();
+    return s.length() == 0 ? null : s;
   }
+
 }