Make sure cancel is handled properly in a few cases, where app must exit after dialog
[zxing.git] / android / src / com / google / zxing / client / android / encode / EncodeActivity.java
index de5527c..13fbe6f 100755 (executable)
@@ -16,6 +16,9 @@
 
 package com.google.zxing.client.android.encode;
 
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.WriterException;
+import com.google.zxing.client.android.FinishListener;
 import com.google.zxing.client.android.Intents;
 import com.google.zxing.client.android.R;
 
@@ -27,14 +30,24 @@ import android.content.DialogInterface.OnCancelListener;
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Environment;
 import android.os.Message;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
 /**
  * This class encodes data from an Intent into a QR code, and then displays it full screen so that
  * another person can scan it with their device.
@@ -42,6 +55,12 @@ import android.widget.TextView;
  * @author dswitkin@google.com (Daniel Switkin)
  */
 public final class EncodeActivity extends Activity {
+
+  private static final String TAG = EncodeActivity.class.getSimpleName();
+
+  private static final int SHARE_BARCODE_DIMENSION = 300;
+  private static final int MAX_BARCODE_FILENAME_LENGTH = 24;
+
   private QRCodeEncoder qrCodeEncoder;
   private ProgressDialog progressDialog;
   private boolean firstLayout;
@@ -65,7 +84,7 @@ public final class EncodeActivity extends Activity {
           setTitle(getString(R.string.app_name) + " - " + qrCodeEncoder.getTitle());
           qrCodeEncoder.requestBarcode(handler, smallerDimension);
           progressDialog = ProgressDialog.show(EncodeActivity.this, null,
-              getString(R.string.msg_encode_in_progress), true, true, cancelListener);
+              getString(R.string.msg_encode_in_progress), true, true, new FinishListener(EncodeActivity.this));
         } catch (IllegalArgumentException e) {
           showErrorMessage(R.string.msg_encode_contents_failed);
         }
@@ -86,7 +105,7 @@ public final class EncodeActivity extends Activity {
           view.setImageBitmap(image);
           TextView contents = (TextView) findViewById(R.id.contents_text_view);
           contents.setText(qrCodeEncoder.getDisplayContents());
-          qrCodeEncoder = null;
+          //qrCodeEncoder = null;
           break;
         case R.id.encode_failed:
           showErrorMessage(R.string.msg_encode_barcode_failed);
@@ -96,18 +115,6 @@ public final class EncodeActivity extends Activity {
     }
   };
 
-  private final OnClickListener clickListener = new OnClickListener() {
-    public void onClick(DialogInterface dialog, int which) {
-      finish();
-    }
-  };
-
-  private final OnCancelListener cancelListener = new OnCancelListener() {
-    public void onCancel(DialogInterface dialog) {
-      finish();
-    }
-  };
-
   @Override
   public void onCreate(Bundle icicle) {
     super.onCreate(icicle);
@@ -123,6 +130,82 @@ public final class EncodeActivity extends Activity {
     finish();
   }
 
+  @Override
+  public boolean onCreateOptionsMenu(Menu menu) {
+    super.onCreateOptionsMenu(menu);
+    menu.add(0, Menu.FIRST, 0, R.string.menu_share).setIcon(android.R.drawable.ic_menu_share);
+    return true;
+  }
+
+  @Override
+  public boolean onOptionsItemSelected(MenuItem item) {
+    if (qrCodeEncoder == null) { // Odd
+      Log.w(TAG, "No existing barcode to send?");
+      return true;
+    }
+
+    String contents = qrCodeEncoder.getContents();
+    Bitmap bitmap;
+    try {
+      bitmap = QRCodeEncoder.encodeAsBitmap(contents, BarcodeFormat.QR_CODE,
+          SHARE_BARCODE_DIMENSION, SHARE_BARCODE_DIMENSION);
+    } catch (WriterException we) {
+      Log.w(TAG, we);
+      return true;
+    }
+
+    File bsRoot = new File(Environment.getExternalStorageDirectory(), "BarcodeScanner");
+    File barcodesRoot = new File(bsRoot, "Barcodes");
+    if (!barcodesRoot.exists() && !barcodesRoot.mkdirs()) {
+      Log.w(TAG, "Couldn't make dir " + barcodesRoot);
+      showErrorMessage(R.string.msg_unmount_usb);
+      return true;
+    }
+    File barcodeFile = new File(barcodesRoot, makeBarcodeFileName(contents) + ".png");
+    barcodeFile.delete();
+    FileOutputStream fos = null;
+    try {
+      fos = new FileOutputStream(barcodeFile);
+      bitmap.compress(Bitmap.CompressFormat.PNG, 0, fos);
+    } catch (FileNotFoundException fnfe) {
+      Log.w(TAG, "Couldn't access file " + barcodeFile + " due to " + fnfe);
+      showErrorMessage(R.string.msg_unmount_usb);
+      return true;
+    } finally {
+      if (fos != null) {
+        try {
+          fos.close();
+        } catch (IOException ioe) {
+          // do nothing
+        }
+      }
+    }
+
+    Intent intent = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
+    intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name) + " - " +
+        qrCodeEncoder.getTitle());
+    intent.putExtra(Intent.EXTRA_TEXT, qrCodeEncoder.getContents());
+    intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + barcodeFile.getAbsolutePath()));
+    intent.setType("image/png");
+    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+    startActivity(Intent.createChooser(intent, null));
+    return true;
+  }
+
+  private static CharSequence makeBarcodeFileName(CharSequence contents) {
+    int fileNameLength = Math.min(MAX_BARCODE_FILENAME_LENGTH, contents.length());
+    StringBuilder fileName = new StringBuilder(fileNameLength);
+    for (int i = 0; i < fileNameLength; i++) {
+      char c = contents.charAt(i);
+      if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) {
+        fileName.append(c);
+      } else {
+        fileName.append('_');
+      }
+    }
+    return fileName;
+  }
+
   @Override
   protected void onResume() {
     super.onResume();
@@ -139,7 +222,8 @@ public final class EncodeActivity extends Activity {
     }
     AlertDialog.Builder builder = new AlertDialog.Builder(this);
     builder.setMessage(message);
-    builder.setPositiveButton(R.string.button_ok, clickListener);
+    builder.setPositiveButton(R.string.button_ok, new FinishListener(this));
+    builder.setOnCancelListener(new FinishListener(this));
     builder.show();
   }
 }