2 * Copyright (C) 2009 ZXing authors
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.google.zxing.client.android.history;
19 import android.app.AlertDialog;
20 import android.content.ContentValues;
21 import android.content.DialogInterface;
22 import android.content.res.Resources;
23 import android.database.sqlite.SQLiteDatabase;
24 import android.database.sqlite.SQLiteOpenHelper;
25 import android.database.Cursor;
26 import android.net.Uri;
27 import android.os.Environment;
30 import java.io.FileOutputStream;
31 import java.io.IOException;
32 import java.io.OutputStreamWriter;
33 import java.nio.charset.Charset;
34 import java.text.DateFormat;
35 import java.util.Date;
36 import java.util.List;
37 import java.util.ArrayList;
39 import android.util.Log;
40 import com.google.zxing.BarcodeFormat;
41 import com.google.zxing.client.android.Intents;
42 import com.google.zxing.client.android.R;
43 import com.google.zxing.client.android.CaptureActivity;
44 import com.google.zxing.Result;
47 * <p>Manages functionality related to scan history.</p>
51 public final class HistoryManager {
53 private static final String TAG = HistoryManager.class.getSimpleName();
55 private static final int MAX_ITEMS = 50;
56 private static final String[] TEXT_COL_PROJECTION = { DBHelper.TEXT_COL };
57 private static final String[] GET_ITEM_COL_PROJECTION = {
60 DBHelper.TIMESTAMP_COL,
62 private static final String[] EXPORT_COL_PROJECTION = {
66 DBHelper.TIMESTAMP_COL,
68 private static final String[] ID_COL_PROJECTION = { DBHelper.ID_COL };
69 private static final DateFormat EXPORT_DATE_TIME_FORMAT = DateFormat.getDateTimeInstance();
71 private final CaptureActivity activity;
73 public HistoryManager(CaptureActivity activity) {
74 this.activity = activity;
77 List<Result> getHistoryItems() {
78 SQLiteOpenHelper helper = new DBHelper(activity);
79 List<Result> items = new ArrayList<Result>();
80 SQLiteDatabase db = helper.getReadableDatabase();
83 cursor = db.query(DBHelper.TABLE_NAME,
84 GET_ITEM_COL_PROJECTION,
85 null, null, null, null,
86 DBHelper.TIMESTAMP_COL + " DESC");
87 while (cursor.moveToNext()) {
88 Result result = new Result(cursor.getString(0),
91 BarcodeFormat.valueOf(cursor.getString(1)),
104 public AlertDialog buildAlert() {
105 List<Result> items = getHistoryItems();
106 int size = items.size();
107 String[] dialogItems = new String[size + 2];
108 for (int i = 0; i < size; i++) {
109 dialogItems[i] = items.get(i).getText();
111 Resources res = activity.getResources();
112 dialogItems[dialogItems.length - 2] = res.getString(R.string.history_send);
113 dialogItems[dialogItems.length - 1] = res.getString(R.string.history_clear_text);
114 DialogInterface.OnClickListener clickListener = new HistoryClickListener(this, activity, dialogItems, items);
115 AlertDialog.Builder builder = new AlertDialog.Builder(activity);
116 builder.setTitle(R.string.history_title);
117 builder.setItems(dialogItems, clickListener);
118 return builder.create();
121 public void addHistoryItem(Result result) {
123 if (!activity.getIntent().getBooleanExtra(Intents.Scan.SAVE_HISTORY, true)) {
124 return; // Do not save this item to the history.
127 SQLiteOpenHelper helper = new DBHelper(activity);
128 SQLiteDatabase db = helper.getWritableDatabase();
130 // Delete if already exists
131 db.delete(DBHelper.TABLE_NAME, DBHelper.TEXT_COL + "=?", new String[] { result.getText() });
133 ContentValues values = new ContentValues();
134 values.put(DBHelper.TEXT_COL, result.getText());
135 values.put(DBHelper.FORMAT_COL, result.getBarcodeFormat().toString());
136 values.put(DBHelper.DISPLAY_COL, result.getText()); // TODO use parsed result display value?
137 values.put(DBHelper.TIMESTAMP_COL, System.currentTimeMillis());
138 db.insert(DBHelper.TABLE_NAME, DBHelper.TIMESTAMP_COL, values);
144 public void trimHistory() {
145 SQLiteOpenHelper helper = new DBHelper(activity);
146 SQLiteDatabase db = helper.getWritableDatabase();
147 Cursor cursor = null;
149 cursor = db.query(DBHelper.TABLE_NAME,
151 null, null, null, null,
152 DBHelper.TIMESTAMP_COL + " DESC");
154 while (count < MAX_ITEMS && cursor.moveToNext()) {
157 while (cursor.moveToNext()) {
158 db.delete(DBHelper.TABLE_NAME, DBHelper.ID_COL + '=' + cursor.getString(0), null);
161 if (cursor != null) {
169 * <p>Builds a text representation of the scanning history. Each scan is encoded on one
170 * line, terminated by a line break (\r\n). The values in each line are comma-separated,
171 * and double-quoted. Double-quotes within values are escaped with a sequence of two
172 * double-quotes. The fields output are:</p>
176 * <li>Display text</li>
177 * <li>Format (e.g. QR_CODE)</li>
179 * <li>Formatted version of timestamp</li>
182 CharSequence buildHistory() {
183 StringBuilder historyText = new StringBuilder(1000);
184 SQLiteOpenHelper helper = new DBHelper(activity);
185 SQLiteDatabase db = helper.getReadableDatabase();
186 Cursor cursor = null;
188 cursor = db.query(DBHelper.TABLE_NAME,
189 EXPORT_COL_PROJECTION,
190 null, null, null, null,
191 DBHelper.TIMESTAMP_COL + " DESC");
192 while (cursor.moveToNext()) {
193 for (int col = 0; col < EXPORT_COL_PROJECTION.length; col++) {
194 historyText.append('"').append(massageHistoryField(cursor.getString(col))).append("\",");
196 // Add timestamp again, formatted
197 long timestamp = cursor.getLong(EXPORT_COL_PROJECTION.length - 1);
198 historyText.append('"').append(massageHistoryField(
199 EXPORT_DATE_TIME_FORMAT.format(new Date(timestamp)))).append("\"\r\n");
202 if (cursor != null) {
210 static Uri saveHistory(String history) {
211 File bsRoot = new File(Environment.getExternalStorageDirectory(), "BarcodeScanner");
212 File historyRoot = new File(bsRoot, "History");
213 if (!historyRoot.exists() && !historyRoot.mkdirs()) {
214 Log.w(TAG, "Couldn't make dir " + historyRoot);
217 File historyFile = new File(historyRoot, "history-" + System.currentTimeMillis() + ".csv");
218 OutputStreamWriter out = null;
220 out = new OutputStreamWriter(new FileOutputStream(historyFile), Charset.forName("UTF-8"));
222 return Uri.parse("file://" + historyFile.getAbsolutePath());
223 } catch (IOException ioe) {
224 Log.w(TAG, "Couldn't access file " + historyFile + " due to " + ioe);
230 } catch (IOException ioe) {
237 private static String massageHistoryField(String value) {
238 return value.replace("\"","\"\"");
241 void clearHistory() {
242 SQLiteOpenHelper helper = new DBHelper(activity);
243 SQLiteDatabase db = helper.getWritableDatabase();
245 db.delete(DBHelper.TABLE_NAME, null, null);