Break out click listener class and make duplicate scans always result in new entry...
[zxing.git] / android / src / com / google / zxing / client / android / history / HistoryManager.java
index 8e861dd..f57726c 100644 (file)
@@ -19,17 +19,24 @@ package com.google.zxing.client.android.history;
 import android.app.AlertDialog;
 import android.content.ContentValues;
 import android.content.DialogInterface;
-import android.content.Intent;
 import android.content.res.Resources;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.Cursor;
 import android.net.Uri;
-import android.os.Message;
-
+import android.os.Environment;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.nio.charset.Charset;
+import java.text.DateFormat;
+import java.util.Date;
 import java.util.List;
 import java.util.ArrayList;
 
+import android.util.Log;
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.client.android.Intents;
 import com.google.zxing.client.android.R;
@@ -43,10 +50,23 @@ import com.google.zxing.Result;
  */
 public final class HistoryManager {
 
+  private static final String TAG = HistoryManager.class.getSimpleName();
+
   private static final int MAX_ITEMS = 50;
   private static final String[] TEXT_COL_PROJECTION = { DBHelper.TEXT_COL };
-  private static final String[] TEXT_FORMAT_COL_PROJECTION = { DBHelper.TEXT_COL, DBHelper.FORMAT_COL };
+  private static final String[] GET_ITEM_COL_PROJECTION = {
+      DBHelper.TEXT_COL,
+      DBHelper.FORMAT_COL,
+      DBHelper.TIMESTAMP_COL,
+  };
+  private static final String[] EXPORT_COL_PROJECTION = {
+      DBHelper.TEXT_COL,
+      DBHelper.DISPLAY_COL,
+      DBHelper.FORMAT_COL,
+      DBHelper.TIMESTAMP_COL,
+  };
   private static final String[] ID_COL_PROJECTION = { DBHelper.ID_COL };
+  private static final DateFormat EXPORT_DATE_TIME_FORMAT = DateFormat.getDateTimeInstance();
 
   private final CaptureActivity activity;
 
@@ -61,11 +81,15 @@ public final class HistoryManager {
     Cursor cursor = null;
     try {
       cursor = db.query(DBHelper.TABLE_NAME,
-                        TEXT_FORMAT_COL_PROJECTION,
+                        GET_ITEM_COL_PROJECTION,
                         null, null, null, null,
                         DBHelper.TIMESTAMP_COL + " DESC");
       while (cursor.moveToNext()) {
-        Result result = new Result(cursor.getString(0), null, null, BarcodeFormat.valueOf(cursor.getString(1)));
+        Result result = new Result(cursor.getString(0),
+                                   null,
+                                   null,
+                                   BarcodeFormat.valueOf(cursor.getString(1)),
+                                   cursor.getLong(2));
         items.add(result);
       }
     } finally {
@@ -78,33 +102,16 @@ public final class HistoryManager {
   }
 
   public AlertDialog buildAlert() {
-    final List<Result> items = getHistoryItems();
-    final String[] dialogItems = new String[items.size() + 2];
-    for (int i = 0; i < items.size(); i++) {
+    List<Result> items = getHistoryItems();
+    int size = items.size();
+    String[] dialogItems = new String[size + 2];
+    for (int i = 0; i < size; i++) {
       dialogItems[i] = items.get(i).getText();
     }
-    final Resources res = activity.getResources();
+    Resources res = activity.getResources();
     dialogItems[dialogItems.length - 2] = res.getString(R.string.history_send);
     dialogItems[dialogItems.length - 1] = res.getString(R.string.history_clear_text);
-    DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() {
-      public void onClick(DialogInterface dialogInterface, int i) {
-        if (i == dialogItems.length - 1) {
-          clearHistory();
-        } else if (i == dialogItems.length - 2) {
-          String history = buildHistory();
-          Intent intent = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
-          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);          
-          intent.putExtra(Intent.EXTRA_SUBJECT, res.getString(R.string.history_email_title));
-          intent.putExtra(Intent.EXTRA_TEXT, history);
-          intent.setType("text/plain");
-          activity.startActivity(intent);
-        } else {
-          Result result = items.get(i);
-          Message message = Message.obtain(activity.getHandler(), R.id.decode_succeeded, result);
-          message.sendToTarget();
-        }
-      }
-    };
+    DialogInterface.OnClickListener clickListener = new HistoryClickListener(this, activity, dialogItems, items);
     AlertDialog.Builder builder = new AlertDialog.Builder(activity);
     builder.setTitle(R.string.history_title);
     builder.setItems(dialogItems, clickListener);
@@ -119,16 +126,10 @@ public final class HistoryManager {
 
     SQLiteOpenHelper helper = new DBHelper(activity);
     SQLiteDatabase db = helper.getWritableDatabase();
-    Cursor cursor = null;
     try {
-      cursor = db.query(DBHelper.TABLE_NAME,
-                        TEXT_COL_PROJECTION,
-                        DBHelper.TEXT_COL + "=?",
-                        new String[] { result.getText() },
-                        null, null, null, null);
-      if (cursor.moveToNext()) {
-        return;
-      }
+      // Delete if already exists
+      db.delete(DBHelper.TABLE_NAME, DBHelper.TEXT_COL + "=?", new String[] { result.getText() });
+      // Insert
       ContentValues values = new ContentValues();
       values.put(DBHelper.TEXT_COL, result.getText());
       values.put(DBHelper.FORMAT_COL, result.getBarcodeFormat().toString());
@@ -136,9 +137,6 @@ public final class HistoryManager {
       values.put(DBHelper.TIMESTAMP_COL, System.currentTimeMillis());
       db.insert(DBHelper.TABLE_NAME, DBHelper.TIMESTAMP_COL, values);
     } finally {
-      if (cursor != null) {
-        cursor.close();
-      }
       db.close();
     }
   }
@@ -167,18 +165,38 @@ public final class HistoryManager {
     }
   }
 
-  private String buildHistory() {
-    StringBuilder historyText = new StringBuilder();
+  /**
+   * <p>Builds a text representation of the scanning history. Each scan is encoded on one
+   * line, terminated by a line break (\r\n). The values in each line are comma-separated,
+   * and double-quoted. Double-quotes within values are escaped with a sequence of two
+   * double-quotes. The fields output are:</p>
+   *
+   * <ul>
+   *  <li>Raw text</li>
+   *  <li>Display text</li>
+   *  <li>Format (e.g. QR_CODE)</li>
+   *  <li>Timestamp</li>
+   *  <li>Formatted version of timestamp</li>
+   * </ul>
+   */
+  CharSequence buildHistory() {
+    StringBuilder historyText = new StringBuilder(1000);
     SQLiteOpenHelper helper = new DBHelper(activity);
     SQLiteDatabase db = helper.getReadableDatabase();
     Cursor cursor = null;
     try {
       cursor = db.query(DBHelper.TABLE_NAME,
-                        TEXT_COL_PROJECTION,
+                        EXPORT_COL_PROJECTION,
                         null, null, null, null,
                         DBHelper.TIMESTAMP_COL + " DESC");
       while (cursor.moveToNext()) {
-        historyText.append(cursor.getString(0)).append('\n');
+        for (int col = 0; col < EXPORT_COL_PROJECTION.length; col++) {
+          historyText.append('"').append(massageHistoryField(cursor.getString(col))).append("\",");
+        }
+        // Add timestamp again, formatted
+        long timestamp = cursor.getLong(EXPORT_COL_PROJECTION.length - 1);
+        historyText.append('"').append(massageHistoryField(
+            EXPORT_DATE_TIME_FORMAT.format(new Date(timestamp)))).append("\"\r\n");
       }
     } finally {
       if (cursor != null) {
@@ -186,7 +204,38 @@ public final class HistoryManager {
       }
       db.close();
     }
-    return historyText.toString();
+    return historyText;
+  }
+
+  static Uri saveHistory(String history) {
+    File bsRoot = new File(Environment.getExternalStorageDirectory(), "BarcodeScanner");
+    File historyRoot = new File(bsRoot, "History");
+    if (!historyRoot.exists() && !historyRoot.mkdirs()) {
+      Log.w(TAG, "Couldn't make dir " + historyRoot);
+      return null;
+    }
+    File historyFile = new File(historyRoot, "history-" + System.currentTimeMillis() + ".csv");
+    OutputStreamWriter out = null;
+    try {
+      out = new OutputStreamWriter(new FileOutputStream(historyFile), Charset.forName("UTF-8"));
+      out.write(history);
+      return Uri.parse("file://" + historyFile.getAbsolutePath());
+    } catch (IOException ioe) {
+      Log.w(TAG, "Couldn't access file " + historyFile + " due to " + ioe);
+      return null;
+    } finally {
+      if (out != null) {
+        try {
+          out.close();
+        } catch (IOException ioe) {
+          // do nothing
+        }
+      }
+    }
+  }
+
+  private static String massageHistoryField(String value) {
+    return value.replace("\"","\"\"");
   }
 
   void clearHistory() {