/* * Copyright (C) 2009 Muthu Ramadoss. All rights reserved. * * Modified from Zxing project to suit Books-Exchange requirements. * Original source from Zxing - http://code.google.com/p/zxing/ */ /* * Copyright (C) 2008 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.androidrocks.bex.zxing.client.android; import com.androidrocks.bex.R; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.Contacts; import android.util.Log; import android.telephony.PhoneNumberUtils; import com.google.zxing.BarcodeFormat; import com.google.zxing.MultiFormatWriter; import com.google.zxing.WriterException; import com.google.zxing.common.ByteMatrix; public final class QRCodeEncoder { private final Activity mActivity; private String mContents; private String mDisplayContents; private String mTitle; private BarcodeFormat mFormat; public QRCodeEncoder(Activity activity, Intent intent) { mActivity = activity; if (!encodeContents(intent)) { throw new IllegalArgumentException("No valid data to encode."); } } public void requestBarcode(Handler handler, int pixelResolution) { Thread encodeThread = new EncodeThread(mContents, handler, pixelResolution, mFormat); encodeThread.start(); } public String getContents() { return mContents; } public String getDisplayContents() { return mDisplayContents; } public String getTitle() { return mTitle; } public String getFormat() { return mFormat.toString(); } // It would be nice if the string encoding lived in the core ZXing library, // but we use platform specific code like PhoneNumberUtils, so it can't. private boolean encodeContents(Intent intent) { if (intent == null) { return false; } // default to QR_CODE if no format given String format = intent.getStringExtra(Intents.Encode.FORMAT); if (format == null || format.length() == 0 || format.equals(Contents.Format.QR_CODE)) { String type = intent.getStringExtra(Intents.Encode.TYPE); if (type == null || type.length() == 0) { return false; } mFormat = BarcodeFormat.QR_CODE; encodeQRCodeContents(intent, type); } else { String data = intent.getStringExtra(Intents.Encode.DATA); if (data != null && data.length() != 0) { mContents = data; mDisplayContents = data; mTitle = mActivity.getString(R.string.contents_text); if (format.equals(Contents.Format.CODE_128)) mFormat = BarcodeFormat.CODE_128; else if (format.equals(Contents.Format.CODE_39)) mFormat = BarcodeFormat.CODE_39; else if (format.equals(Contents.Format.EAN_8)) mFormat = BarcodeFormat.EAN_8; else if (format.equals(Contents.Format.EAN_13)) mFormat = BarcodeFormat.EAN_13; else if (format.equals(Contents.Format.UPC_A)) mFormat = BarcodeFormat.UPC_A; else if (format.equals(Contents.Format.UPC_E)) mFormat = BarcodeFormat.UPC_E; } } return mContents != null && mContents.length() > 0; } private void encodeQRCodeContents(Intent intent, String type) { if (type.equals(Contents.Type.TEXT)) { String data = intent.getStringExtra(Intents.Encode.DATA); if (data != null && data.length() > 0) { mContents = data; mDisplayContents = data; mTitle = mActivity.getString(R.string.contents_text); } } else if (type.equals(Contents.Type.EMAIL)) { String data = intent.getStringExtra(Intents.Encode.DATA); if (data != null && data.length() > 0) { mContents = "mailto:" + data; mDisplayContents = data; mTitle = mActivity.getString(R.string.contents_email); } } else if (type.equals(Contents.Type.PHONE)) { String data = intent.getStringExtra(Intents.Encode.DATA); if (data != null && data.length() > 0) { mContents = "tel:" + data; mDisplayContents = PhoneNumberUtils.formatNumber(data); mTitle = mActivity.getString(R.string.contents_phone); } } else if (type.equals(Contents.Type.SMS)) { String data = intent.getStringExtra(Intents.Encode.DATA); if (data != null && data.length() > 0) { mContents = "sms:" + data; mDisplayContents = PhoneNumberUtils.formatNumber(data); mTitle = mActivity.getString(R.string.contents_sms); } } else if (type.equals(Contents.Type.CONTACT)) { Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA); if (bundle != null) { StringBuilder newContents = new StringBuilder(); StringBuilder newDisplayContents = new StringBuilder(); newContents.append("MECARD:"); String name = bundle.getString(Contacts.Intents.Insert.NAME); if (name != null && name.length() > 0) { newContents.append("N:").append(name).append(';'); newDisplayContents.append(name); } String address = bundle.getString(Contacts.Intents.Insert.POSTAL); if (address != null && address.length() > 0) { newContents.append("ADR:").append(address).append(';'); newDisplayContents.append('\n').append(address); } for (int x = 0; x < Contents.PHONE_KEYS.length; x++) { String phone = bundle.getString(Contents.PHONE_KEYS[x]); if (phone != null && phone.length() > 0) { newContents.append("TEL:").append(phone).append(';'); newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone)); } } for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) { String email = bundle.getString(Contents.EMAIL_KEYS[x]); if (email != null && email.length() > 0) { newContents.append("EMAIL:").append(email).append(';'); newDisplayContents.append('\n').append(email); } } // Make sure we've encoded at least one field. if (newDisplayContents.length() > 0) { newContents.append(';'); mContents = newContents.toString(); mDisplayContents = newDisplayContents.toString(); mTitle = mActivity.getString(R.string.contents_contact); } else { mContents = null; mDisplayContents = null; } } } else if (type.equals(Contents.Type.LOCATION)) { Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA); if (bundle != null) { // These must use Bundle.getFloat(), not getDouble(), it's part of the API. float latitude = bundle.getFloat("LAT", Float.MAX_VALUE); float longitude = bundle.getFloat("LONG", Float.MAX_VALUE); if (latitude != Float.MAX_VALUE && longitude != Float.MAX_VALUE) { mContents = "geo:" + latitude + ',' + longitude; mDisplayContents = latitude + "," + longitude; mTitle = mActivity.getString(R.string.contents_location); } } } } private static final class EncodeThread extends Thread { private static final String TAG = "EncodeThread"; private final String mContents; private final Handler mHandler; private final int mPixelResolution; private final BarcodeFormat mFormat; EncodeThread(String contents, Handler handler, int pixelResolution, BarcodeFormat format) { mContents = contents; mHandler = handler; mPixelResolution = pixelResolution; mFormat = format; } @Override public void run() { try { ByteMatrix result = new MultiFormatWriter().encode(mContents, mFormat, mPixelResolution, mPixelResolution); int width = result.getWidth(); int height = result.getHeight(); byte[][] array = result.getArray(); int[] pixels = new int[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int grey = array[y][x] & 0xff; // pixels[y * width + x] = (0xff << 24) | (grey << 16) | (grey << 8) | grey; pixels[y * width + x] = 0xff000000 | (0x00010101 * grey); } } Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); bitmap.setPixels(pixels, 0, width, 0, 0, width, height); Message message = Message.obtain(mHandler, R.id.encode_succeeded); message.obj = bitmap; message.sendToTarget(); } catch (WriterException e) { Log.e(TAG, e.toString()); Message message = Message.obtain(mHandler, R.id.encode_failed); message.sendToTarget(); } catch (IllegalArgumentException e) { Log.e(TAG, e.toString()); Message message = Message.obtain(mHandler, R.id.encode_failed); message.sendToTarget(); } } } }