Skip to content

Instantly share code, notes, and snippets.

@wakim
Created September 1, 2015 12:24
Show Gist options
  • Select an option

  • Save wakim/de952e72cc0e3270c7c6 to your computer and use it in GitHub Desktop.

Select an option

Save wakim/de952e72cc0e3270c7c6 to your computer and use it in GitHub Desktop.
QRCodeManager
package br.com.foca.util;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.AsyncTask;
import android.util.LruCache;
import android.view.View;
import android.widget.ImageView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import org.androidannotations.annotations.EBean;
import java.lang.ref.WeakReference;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import br.com.foca.application.App4yApplication_;
@EBean(scope = EBean.Scope.Singleton)
public class QRCodeManager {
private static final Map<EncodeHintType, Object> HINTS = new EnumMap<>(EncodeHintType.class);
final Object lock = new Object();
LruCache<String, Bitmap> mBitmapCache;
HashMap<Integer, QRCodeTask> mTasks = new HashMap<>();
static {
HINTS.put(EncodeHintType.CHARACTER_SET, "UTF-8");
HINTS.put(EncodeHintType.MARGIN, 2); /* default = 4 */
}
public void initCacheIfNeeded(Context context) {
if(mBitmapCache != null) {
return;
}
int memClass = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
int cacheSize = 1024 * 1024 * memClass / 8;
mBitmapCache = new LruCache<String, Bitmap>(cacheSize) {
protected int sizeOf(String key, Bitmap value) {
// The cache size will be measured in kilobytes rather than number of items.
return value.getByteCount() / 1024;
}
};
}
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
synchronized (lock) {
if (getBitmapFromMemCache(key) == null) {
mBitmapCache.put(key, bitmap);
}
}
}
public Bitmap getBitmapFromMemCache(String key) {
return mBitmapCache.get(key);
}
public void loadQRCodeInto(LoadRequest request) {
Bitmap cachedBitmap = mBitmapCache.get(request.mQRCode);
if(cachedBitmap != null) {
request.mImageView.get().setImageBitmap(cachedBitmap);
hideIfPossible(request.mPlaceholder.get());
showIfPossible(request.mImageView.get());
return;
}
scheduleTaskFor(request);
}
// Naive implementation
void scheduleTaskFor(LoadRequest request) {
QRCodeTask task = new QRCodeTask(request);
int imageViewHashCode = request.mImageView.hashCode();
if(mTasks.containsKey(imageViewHashCode)) {
QRCodeTask oldTask = mTasks.get(imageViewHashCode);
oldTask.cancel(false);
}
mTasks.remove(imageViewHashCode);
mTasks.put(imageViewHashCode, task);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
void showIfPossible(View view) {
if(view != null) {
view.setVisibility(View.VISIBLE);
}
}
void hideIfPossible(View view) {
if(view != null) {
view.setVisibility(View.GONE);
}
}
public static class LoadRequest {
private WeakReference<ImageView> mImageView;
private WeakReference<View> mPlaceholder;
private String mQRCode;
private int mWidth = 400, mHeight = 400;
private LoadRequest(){}
public static LoadRequest load(String qrCode) {
LoadRequest request = new LoadRequest();
request.mQRCode = qrCode;
return request;
}
public LoadRequest withDimension(int width, int height) {
mWidth = width;
mHeight = height;
return this;
}
public LoadRequest withPlaceholder(View placeholder) {
mPlaceholder = new WeakReference<>(placeholder);
return this;
}
public LoadRequest into(ImageView imageView) {
mImageView = new WeakReference<>(imageView);
return this;
}
}
public static class QRCodeTask extends AsyncTask<Void, Void, Bitmap> {
LoadRequest mRequest;
QRCodeManager mManager;
QRCodeTask(LoadRequest request) {
mRequest = request;
mManager = QRCodeManager_.getInstance_(App4yApplication_.getInstance());
}
@Override
protected void onPreExecute() {
super.onPreExecute();
mManager.showIfPossible(mRequest.mPlaceholder.get());
mManager.hideIfPossible(mRequest.mImageView.get());
}
@Override
protected Bitmap doInBackground(Void... params) {
QRCodeWriter writer = new QRCodeWriter();
try {
BitMatrix matrix = writer.encode(mRequest.mQRCode, BarcodeFormat.QR_CODE, mRequest.mWidth, mRequest.mHeight, HINTS);
int height = matrix.getHeight();
int width = matrix.getWidth();
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
for (int x = 0; x < width; x++){
if(isCancelled() || mRequest.mImageView.get() == null) {
return null;
}
for (int y = 0; y < height; y++){
bmp.setPixel(x, y, matrix.get(x, y) ? Color.BLACK : Color.WHITE);
}
}
mManager.addBitmapToMemoryCache(mRequest.mQRCode, bmp);
return bmp;
} catch (WriterException e) {
return null;
}
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if(bitmap == null) {
return;
}
if(mRequest.mImageView.get() != null && ! isCancelled()) {
mRequest.mImageView.get().setImageBitmap(bitmap);
}
mManager.showIfPossible(mRequest.mImageView.get());
mManager.hideIfPossible(mRequest.mPlaceholder.get());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment