From b91d4c934a664e06f4b5c41a1b198d56f0c8e1b9 Mon Sep 17 00:00:00 2001 From: Branden Archer Date: Sat, 21 May 2016 18:21:53 -0400 Subject: [PATCH] Generate barcode in an AsyncTask This change moves the generation of the barcode into its own async task. In addition, the size of the ImageView is used to determine the barcode size to use. There will be cases when the size of the ImageView will not be known when the barcode generation starts. This will be resolved in a future commit. --- .../card_locker/BarcodeImageWriterTask.java | 91 +++++++++++++++++++ .../card_locker/LoyaltyCardViewActivity.java | 56 ++---------- 2 files changed, 98 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/protect/card_locker/BarcodeImageWriterTask.java diff --git a/app/src/main/java/protect/card_locker/BarcodeImageWriterTask.java b/app/src/main/java/protect/card_locker/BarcodeImageWriterTask.java new file mode 100644 index 000000000..cd32e0f35 --- /dev/null +++ b/app/src/main/java/protect/card_locker/BarcodeImageWriterTask.java @@ -0,0 +1,91 @@ +package protect.card_locker; + +import android.graphics.Bitmap; +import android.os.AsyncTask; +import android.util.Log; +import android.widget.ImageView; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; + +import java.lang.ref.WeakReference; + +/** + * This task will generate a barcode and load it into an ImageView. + * Only a weak reference of the ImageView is kept, so this class will not + * prevent the ImageView from being garbage collected. + */ +class BarcodeImageWriterTask extends AsyncTask +{ + private static final String TAG = "LoyaltyCardLocker"; + + private final WeakReference imageViewReference; + private final String cardId; + private final BarcodeFormat format; + private final int imageHeight; + private final int imageWidth; + + public BarcodeImageWriterTask(ImageView imageView, String cardIdString, + BarcodeFormat barcodeFormat) + { + // Use a WeakReference to ensure the ImageView can be garbage collected + imageViewReference = new WeakReference<>(imageView); + + cardId = cardIdString; + format = barcodeFormat; + imageHeight = imageView.getHeight(); + imageWidth = imageView.getWidth(); + } + + public Bitmap doInBackground(Void... params) + { + MultiFormatWriter writer = new MultiFormatWriter(); + BitMatrix bitMatrix; + try + { + bitMatrix = writer.encode(cardId, format, imageWidth, imageHeight, null); + + final int WHITE = 0xFFFFFFFF; + final int BLACK = 0xFF000000; + + int bitMatrixWidth = bitMatrix.getWidth(); + int bitMatrixHeight = bitMatrix.getHeight(); + + int[] pixels = new int[bitMatrixWidth * bitMatrixHeight]; + + for (int y = 0; y < bitMatrixHeight; y++) + { + int offset = y * bitMatrixWidth; + for (int x = 0; x < bitMatrixWidth; x++) + { + int color = bitMatrix.get(x, y) ? BLACK : WHITE; + pixels[offset + x] = color; + } + } + Bitmap bitmap = Bitmap.createBitmap(bitMatrixWidth, bitMatrixHeight, + Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, bitMatrixWidth, 0, 0, bitMatrixWidth, bitMatrixHeight); + return bitmap; + } + catch (WriterException | IllegalArgumentException e) + { + Log.e(TAG, "Failed to generate barcode", e); + } + + return null; + } + + protected void onPostExecute(Bitmap result) + { + ImageView imageView = imageViewReference.get(); + if(imageView == null) + { + // The ImageView no longer exists, nothing to do + return; + } + + imageView.setImageBitmap(result); + } +} \ No newline at end of file diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java index 015a76d7d..3cf30d3ae 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardViewActivity.java @@ -2,7 +2,6 @@ package protect.card_locker; import android.content.Intent; -import android.graphics.Bitmap; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v7.app.ActionBar; @@ -17,9 +16,6 @@ import android.widget.EditText; import android.widget.ImageView; import com.google.zxing.BarcodeFormat; -import com.google.zxing.MultiFormatWriter; -import com.google.zxing.WriterException; -import com.google.zxing.common.BitMatrix; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; @@ -149,52 +145,14 @@ public class LoyaltyCardViewActivity extends AppCompatActivity if(cardIdField.getText().length() > 0 && barcodeTypeField.getText().length() > 0) { - MultiFormatWriter writer = new MultiFormatWriter(); - BitMatrix result; - try - { - String formatString = barcodeTypeField.getText().toString(); - BarcodeFormat format = BarcodeFormat.valueOf(formatString); - if(format == null) - { - throw new IllegalArgumentException("Unrecognized barcode format: " + formatString); - } + String formatString = barcodeTypeField.getText().toString(); + final BarcodeFormat format = BarcodeFormat.valueOf(formatString); + final String cardIdString = cardIdField.getText().toString(); - int generateWidth = 100; - int generateHeight = 100; + new BarcodeImageWriterTask(barcodeImage, cardIdString, format).execute(); - String cardIdString = cardIdField.getText().toString(); - - Log.i(TAG, "Card: " + cardIdString); - - result = writer.encode(cardIdString, format, generateWidth, generateHeight, null); - - final int WHITE = 0xFFFFFFFF; - final int BLACK = 0xFF000000; - - int width = result.getWidth(); - int height = result.getHeight(); - int[] pixels = new int[width * height]; - 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; - } - } - Bitmap bitmap = Bitmap.createBitmap(width, height, - Bitmap.Config.ARGB_8888); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); - barcodeImage.setImageBitmap(bitmap); - - barcodeIdLayout.setVisibility(View.VISIBLE); - barcodeImageLayout.setVisibility(View.VISIBLE); - } - catch (WriterException | IllegalArgumentException e) - { - Log.e(TAG, "Failed to generate barcode", e); - } + barcodeIdLayout.setVisibility(View.VISIBLE); + barcodeImageLayout.setVisibility(View.VISIBLE); } View.OnClickListener captureCallback = new View.OnClickListener() @@ -332,4 +290,4 @@ public class LoyaltyCardViewActivity extends AppCompatActivity } } } -} +} \ No newline at end of file