Created
September 1, 2015 12:24
-
-
Save wakim/de952e72cc0e3270c7c6 to your computer and use it in GitHub Desktop.
QRCodeManager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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