Generate barcode image in Android application - android

I need to generate 1D barcode image and set it to ImageView according to given 13-character code. Can anyone help me with this please?

You can use zxing library to generate barcode easily.
first, locate core.jar under libs folder.
libs/core.jar
You can download ZXing-2.1.zip from here.
http://repo1.maven.org/maven2/com/google/zxing/ (source)
After unzipping the file, find the jar file.
\ZXing-2.1\zxing-2.1\core\core.jar
And then write your own code like below.
import java.util.EnumMap;
import java.util.Map;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
public class BarcodeExampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout l = new LinearLayout(this);
l.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
l.setOrientation(LinearLayout.VERTICAL);
setContentView(l);
// barcode data
String barcode_data = "123456";
// barcode image
Bitmap bitmap = null;
ImageView iv = new ImageView(this);
try {
bitmap = encodeAsBitmap(barcode_data, BarcodeFormat.CODE_128, 600, 300);
iv.setImageBitmap(bitmap);
} catch (WriterException e) {
e.printStackTrace();
}
l.addView(iv);
//barcode text
TextView tv = new TextView(this);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
tv.setText(barcode_data);
l.addView(tv);
}
/**************************************************************
* getting from com.google.zxing.client.android.encode.QRCodeEncoder
*
* See the sites below
* http://code.google.com/p/zxing/
* http://code.google.com/p/zxing/source/browse/trunk/android/src/com/google/zxing/client/android/encode/EncodeActivity.java
* http://code.google.com/p/zxing/source/browse/trunk/android/src/com/google/zxing/client/android/encode/QRCodeEncoder.java
*/
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int img_width, int img_height) throws WriterException {
String contentsToEncode = contents;
if (contentsToEncode == null) {
return null;
}
Map<EncodeHintType, Object> hints = null;
String encoding = guessAppropriateEncoding(contentsToEncode);
if (encoding != null) {
hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result;
try {
result = writer.encode(contentsToEncode, format, img_width, img_height, hints);
} catch (IllegalArgumentException iae) {
// Unsupported format
return null;
}
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);
return bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) {
return "UTF-8";
}
}
return null;
}
}

Thanks for your answers guys... In the meantime I found solution so here is what I used: http://www.onbarcode.com/products/android_barcode/barcodes/ean13.html
It's a library that worked fine for me so if anyone has the same issue I suggest using it.
Thanks again!

public Bitmap Ean13_Encode(String qrData, int qrCodeDimention) {
Bitmap bitmap= Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrData, null,
Contents.Type.TEXT, BarcodeFormat.EAN_13.toString(), qrCodeDimention);
try {
bitmap = qrCodeEncoder.encodeAsBitmap();
} catch (WriterException e) {
e.printStackTrace();
};
return bitmap;
};
public final class QRCodeEncoder {
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
private int dimension = Integer.MIN_VALUE;
private String contents = null;
private String displayContents = null;
private String title = null;
private BarcodeFormat format = null;
private boolean encoded = false;
public QRCodeEncoder(String data, Bundle bundle, String type, String format, int dimension) {
this.dimension = dimension;
encoded = encodeContents(data, bundle, type, format);
}
public String getContents() {
return contents;
}
public String getDisplayContents() {
return displayContents;
}
public String getTitle() {
return title;
}
private boolean encodeContents(String data, Bundle bundle, String type, String formatString) {
// Default to QR_CODE if no format given.
format = null;
if (formatString != null) {
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
}
}
if (format == null || format == BarcodeFormat.QR_CODE) {
this.format = BarcodeFormat.QR_CODE;
encodeQRCodeContents(data, bundle, type);
} else if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
return contents != null && contents.length() > 0;
}
private void encodeQRCodeContents(String data, Bundle bundle, String type) {
if (type.equals(Contents.Type.TEXT)) {
if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
} else if (type.equals(Contents.Type.EMAIL)) {
data = trim(data);
if (data != null) {
contents = "mailto:" + data;
displayContents = data;
title = "E-Mail";
}
} else if (type.equals(Contents.Type.PHONE)) {
data = trim(data);
if (data != null) {
contents = "tel:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "Phone";
}
} else if (type.equals(Contents.Type.SMS)) {
data = trim(data);
if (data != null) {
contents = "sms:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "SMS";
}
} else if (type.equals(Contents.Type.CONTACT)) {
if (bundle != null) {
StringBuilder newContents = new StringBuilder(100);
StringBuilder newDisplayContents = new StringBuilder(100);
newContents.append("MECARD:");
String name = trim(bundle.getString(ContactsContract.Intents.Insert.NAME));
if (name != null) {
newContents.append("N:").append(escapeMECARD(name)).append(';');
newDisplayContents.append(name);
}
String address = trim(bundle.getString(ContactsContract.Intents.Insert.POSTAL));
if (address != null) {
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
newDisplayContents.append('\n').append(address);
}
Collection<String> uniquePhones = new HashSet<String>(Contents.PHONE_KEYS.length);
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
String phone = trim(bundle.getString(Contents.PHONE_KEYS[x]));
if (phone != null) {
uniquePhones.add(phone);
}
}
for (String phone : uniquePhones) {
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
}
Collection<String> uniqueEmails = new HashSet<String>(Contents.EMAIL_KEYS.length);
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
String email = trim(bundle.getString(Contents.EMAIL_KEYS[x]));
if (email != null) {
uniqueEmails.add(email);
}
}
for (String email : uniqueEmails) {
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
newDisplayContents.append('\n').append(email);
}
String url = trim(bundle.getString(Contents.URL_KEY));
if (url != null) {
// escapeMECARD(url) -> wrong escape e.g. http\://zxing.google.com
newContents.append("URL:").append(url).append(';');
newDisplayContents.append('\n').append(url);
}
String note = trim(bundle.getString(Contents.NOTE_KEY));
if (note != null) {
newContents.append("NOTE:").append(escapeMECARD(note)).append(';');
newDisplayContents.append('\n').append(note);
}
// Make sure we've encoded at least one field.
if (newDisplayContents.length() > 0) {
newContents.append(';');
contents = newContents.toString();
displayContents = newDisplayContents.toString();
title = "Contact";
} else {
contents = null;
displayContents = null;
}
}
} else if (type.equals(Contents.Type.LOCATION)) {
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) {
contents = "geo:" + latitude + ',' + longitude;
displayContents = latitude + "," + longitude;
title = "Location";
}
}
}
}
public Bitmap encodeAsBitmap() throws WriterException {
if (!encoded) return null;
Map<EncodeHintType, Object> hints = null;
String encoding = guessAppropriateEncoding(contents);
if (encoding != null) {
hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result = writer.encode(contents, format, dimension, dimension, hints);
int width = result.getWidth();
int height = result.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
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);
return bitmap;
}
private String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) { return "UTF-8"; }
}
return null;
}
private String trim(String s) {
if (s == null) { return null; }
String result = s.trim();
return result.length() == 0 ? null : result;
}
private String escapeMECARD(String input) {
if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) { return input; }
int length = input.length();
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == ':' || c == ';') {
result.append('\\');
}
result.append(c);
}
return result.toString();
}
}

Check out the answer on: Generate 1D barcode in Android
They suggest using IText which is a java PDF manipulation library. That also has the capability to generate barcode images.
You can find sample code in that question that I linked and also here

Related

How do I build an app that scans QR codes and uses their data on Android? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Please be advised I am a total novice at Android development, and have only progressed as far as "Hello world".
I don't actually want to build a QR code scanner, I would rather use a third party component, but I need an app that will scan a QR code, display some data from the code, and send some data to a web service.
Please can someone give me a real beginner's outline on the process and structure U should use in my application. I am an experienced C# developer, so the actual Java coding won't be a problem, and I'm certainly not asking how to do that, just how to set up the basic app architecture and process flow, e.g. how to show a dialogue, contact a web service, and use a third party component.
What I need is to scan a QR code, extract some text code from it, send those codes to a web service.
ZXing is a pretty good library which you can integrate in your application.Refer this class CaptureActivity
first you need zxing library for creating QR Codes and an installed application for reading QR codes like BarcodeScanner and a Encoder class like:
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.ByteMatrix;
public final class QRCodeEncoder {
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
private int dimension = Integer.MIN_VALUE;
private String contents = null;
private String displayContents = null;
private String title = null;
private BarcodeFormat format = null;
private boolean encoded = false;
public QRCodeEncoder(String data, Bundle bundle, String type, String format, int dimension) {
this.dimension = dimension;
encoded = encodeContents(data, bundle, type, format);
}
public String getContents() {
return contents;
}
public String getDisplayContents() {
return displayContents;
}
public String getTitle() {
return title;
}
private boolean encodeContents(String data, Bundle bundle, String type, String formatString) {
// Default to QR_CODE if no format given.
format = null;
if (formatString != null) {
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
}
}
if (format == null || format == BarcodeFormat.QR_CODE) {
this.format = BarcodeFormat.QR_CODE;
encodeQRCodeContents(data, bundle, type);
} else if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
return contents != null && contents.length() > 0;
}
private void encodeQRCodeContents(String data, Bundle bundle, String type) {
if (type.equals(Contents.Type.TEXT)) {
if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
} else if (type.equals(Contents.Type.EMAIL)) {
data = trim(data);
if (data != null) {
contents = "mailto:" + data;
displayContents = data;
title = "E-Mail";
}
} else if (type.equals(Contents.Type.PHONE)) {
data = trim(data);
if (data != null) {
contents = "tel:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "Phone";
}
} else if (type.equals(Contents.Type.SMS)) {
data = trim(data);
if (data != null) {
contents = "sms:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "SMS";
}
} else if (type.equals(Contents.Type.CONTACT)) {
if (bundle != null) {
StringBuilder newContents = new StringBuilder(100);
StringBuilder newDisplayContents = new StringBuilder(100);
newContents.append("MECARD:");
String name = trim(bundle.getString(ContactsContract.Intents.Insert.NAME));
if (name != null) {
newContents.append("N:").append(escapeMECARD(name)).append(';');
newDisplayContents.append(name);
}
String address = trim(bundle.getString(ContactsContract.Intents.Insert.POSTAL));
if (address != null) {
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
newDisplayContents.append('\n').append(address);
}
Collection<String> uniquePhones = new HashSet<String>(Contents.PHONE_KEYS.length);
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
String phone = trim(bundle.getString(Contents.PHONE_KEYS[x]));
if (phone != null) {
uniquePhones.add(phone);
}
}
for (String phone : uniquePhones) {
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
}
Collection<String> uniqueEmails = new HashSet<String>(Contents.EMAIL_KEYS.length);
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
String email = trim(bundle.getString(Contents.EMAIL_KEYS[x]));
if (email != null) {
uniqueEmails.add(email);
}
}
for (String email : uniqueEmails) {
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
newDisplayContents.append('\n').append(email);
}
String url = trim(bundle.getString(Contents.URL_KEY));
if (url != null) {
// escapeMECARD(url) -> wrong escape e.g. http\://zxing.google.com
newContents.append("URL:").append(url).append(';');
newDisplayContents.append('\n').append(url);
}
String note = trim(bundle.getString(Contents.NOTE_KEY));
if (note != null) {
newContents.append("NOTE:").append(escapeMECARD(note)).append(';');
newDisplayContents.append('\n').append(note);
}
// Make sure we've encoded at least one field.
if (newDisplayContents.length() > 0) {
newContents.append(';');
contents = newContents.toString();
displayContents = newDisplayContents.toString();
title = "Contact";
} else {
contents = null;
displayContents = null;
}
}
} else if (type.equals(Contents.Type.LOCATION)) {
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) {
contents = "geo:" + latitude + ',' + longitude;
displayContents = latitude + "," + longitude;
title = "Location";
}
}
}
}
public Bitmap encodeAsBitmap() throws WriterException {
if (!encoded) return null;
Hashtable hints = null;
String encoding = guessAppropriateEncoding(contents);
if (encoding != null) {
hints = new Hashtable();
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
ByteMatrix result =writer.encode(contents, format, dimension, dimension, hints);
int width = result.getWidth();
int height =result.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
if(result.get(x, y)== 0)
{
pixels[offset + x] = BLACK ;
}
else
pixels[offset + x] = WHITE ;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) { return "UTF-8"; }
}
return null;
}
private static String trim(String s) {
if (s == null) { return null; }
String result = s.trim();
return result.length() == 0 ? null : result;
}
private static String escapeMECARD(String input) {
if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) { return input; }
int length = input.length();
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == ':' || c == ';') {
result.append('\\');
}
result.append(c);
}
return result.toString();
}
}
hope this help you:)
You can also consider using manateework sdk which is very fast, cost effective. I has SDK available for mobile applications which supports different platform ie. iOS, Android etc and code symbology. Pl. refer to https://manateeworks.com/ for more details on this sdk

Error in creating image of barcode in Android Studio

I want to create the image of the barcode/QR code etc on my app. I have searched a lot and have found different libraries to do this task but since I am already using Zxing so i would like to work in it.
Following is the code that I have writen:
This is my Scanner Activity class:
public void handleResult(Result rawResult) {
// Do something with the result here
Log.v(TAG, rawResult.getText()); // Prints scan results
Toast.makeText(SimpleScannerActivity.this, rawResult.toString() + " WOW scanned", Toast.LENGTH_LONG).show();
Toast.makeText(SimpleScannerActivity.this, rawResult.getBarcodeFormat().toString(), Toast.LENGTH_LONG).show();
Log.v(TAG, rawResult.getBarcodeFormat().toString()); // Prints the scan format (qrcode, pdf417 etc.)
//Intent scanScreenResult= new Intent("com.aaa.fyp.ScanResultScreen");
setFormat(rawResult);
Intent nextScreen = new Intent("com.aaa.fyp.ScanResultScreen");
nextScreen.putExtra("barcode",rawResult.toString());
nextScreen.putExtra("format", rawResult.getBarcodeFormat().toString());
finish();
startActivity(nextScreen);
}
public void setFormat(Result result){
r=result.getBarcodeFormat();
System.out.println("============================== setformat main"+ r);
}
public BarcodeFormat getFormat(){
System.out.println("============================== getformat main"+ r);
return r;
}
Using the results from the above activity in ScanResultScreen activity.
public class ScanResultScreen extends SimpleScannerActivity {
ImageView scanned;
TextView bc;
TextView f;
String Barcode;
String format;
BarcodeFormat form;
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.scan_screen_with_button);
ViewGroup layout = (ViewGroup) findViewById(R.id.scanScreenWithButton);
setContentView(layout);
Intent prevScreen = getIntent(); // gets the previously created intent
Barcode=prevScreen.getStringExtra("barcode");
bc= (TextView)findViewById(R.id.barcode_label);
bc.setText(Barcode);
format=prevScreen.getStringExtra("format");
f=(TextView) findViewById(R.id.format_label);
f.setText(prevScreen.getStringExtra("format").toString());
SimpleScannerActivity obj=new SimpleScannerActivity();
form=obj.getFormat();
d=(TextView)findViewById(R.id.date_label);
String formattedDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());
d.setText(formattedDate);
Bitmap bitmap = null;
ImageView iv = new ImageView(this);
try {
bitmap = encodeAsBitmap(Barcode, form, 600, 300);
iv.setImageBitmap(bitmap);
} catch (WriterException e) {
e.printStackTrace();
}
layout.addView(iv);
}
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int img_width, int img_height) throws WriterException {
String contentsToEncode = contents;
if (contentsToEncode == null) {
return null;
}
Map<EncodeHintType, Object> hints = null;
String encoding = guessAppropriateEncoding(contentsToEncode);
if (encoding != null) {
hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result;
try {
result = writer.encode(contentsToEncode, format, img_width, img_height, hints);
} catch (IllegalArgumentException iae) {
// Unsupported format
return null;
}
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);
return bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) {
return "UTF-8";
}
}
return null;
}
Now I am getting a Null value in the variable "form". Even though I am able to get the barcodeFormat in my second activity by passing it through intent but it's in the type String. Whereas the built-in methods that I am using here requires it in BarcodeFormat that is available in Zxing.
Help!!
BarcodeFormat is an enum type. If you want to pass a String value, you have to convert it to BarcodeFormat.
For example, passing a barcode format "AZTEC":
BarcodeFormat format = Enum.valueOf(BarcodeFormat.class, "AZTEC");

Error while converting text to QR code

I am trying to create a text to QR code converter.
I used the core2.2.jar from http://code.google.com/p/zxing/downloads/list and the code as told in Integrating the ZXing library directly into my Android application.
My Main.Activity is as shown below
package com.example.qr_androidone;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.view.Menu;
import android.widget.ImageView;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
//super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
ImageView imageView = (ImageView) findViewById(R.id.qrCode);
String qrData = "Data I want to encode in QR code";
int qrCodeDimention = 500;
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrData, null,
Contents.Type.TEXT, BarcodeFormat.QR_CODE.toString(), qrCodeDimention);
try {
Bitmap bitmap = qrCodeEncoder.encodeAsBitmap();
imageView.setImageBitmap(bitmap);
} catch (WriterException e) {
e.printStackTrace();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I used the "Contents.java" and "QRCodeEncoder.java" as shown in link Integrating the ZXing library directly into my Android application. I changed "activity_main.xml" also , as shown in above link
There are no errors in compiling, but there is error when the app runs
Could not find class 'com.google.zxing.EncodeHintType', referenced
from method com.example.qr_androidone.QRCodeEncoder.encodeAsBitmap
Could not find class 'com.google.zxing.MultiFormatWriter', referenced
from method com.example.qr_androidone.QRCodeEncoder.encodeAsBitmap
java.lang.NoClassDefFoundError: com.google.zxing.BarcodeFormat
Please help me solve the error
Download de JAR file, go to your Build Path and Import it from External JARs.
http://repo1.maven.org/maven2/com/google/zxing/core/2.2/
Then import it in your project.
you need the class of QRCodeEncoder.java..
public class QRCodeEncoder {
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
// private int dimension = Integer.MAX_VALUE;
private String contents = null;
private String displayContents = null;
private String title = null;
private BarcodeFormat format = null;
private boolean encoded = false;
public QRCodeEncoder(String data, Bundle bundle, String type, String format) {
// this.dimension = dimension;
encoded = encodeContents(data, bundle, type, format);
}
public String getContents() {
return contents;
}
public String getDisplayContents() {
return displayContents;
}
public String getTitle() {
return title;
}
private boolean encodeContents(String data, Bundle bundle, String type, String formatString) {
// Default to QR_CODE if no format given.
format = null;
if (formatString != null) {
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
}
}
if (format == null || format == BarcodeFormat.QR_CODE) {
this.format = BarcodeFormat.QR_CODE;
encodeQRCodeContents(data, bundle, type);
} else if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
return contents != null && contents.length() > 0;
}
private void encodeQRCodeContents(String data, Bundle bundle, String type) {
if (type.equals(Contents.Type.TEXT)) {
if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
} else if (type.equals(Contents.Type.EMAIL)) {
data = trim(data);
if (data != null) {
contents = "mailto:" + data;
displayContents = data;
title = "E-Mail";
}
} else if (type.equals(Contents.Type.PHONE)) {
data = trim(data);
if (data != null) {
contents = "tel:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "Phone";
}
} else if (type.equals(Contents.Type.SMS)) {
data = trim(data);
if (data != null) {
contents = "sms:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "SMS";
}
} else if (type.equals(Contents.Type.CONTACT)) {
if (bundle != null) {
StringBuilder newContents = new StringBuilder(100);
StringBuilder newDisplayContents = new StringBuilder(100);
newContents.append("MECARD:");
String name = trim(bundle.getString(ContactsContract.Intents.Insert.NAME));
if (name != null) {
newContents.append("N:").append(escapeMECARD(name)).append(';');
newDisplayContents.append(name);
}
String address = trim(bundle.getString(ContactsContract.Intents.Insert.POSTAL));
if (address != null) {
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
newDisplayContents.append('\n').append(address);
}
Collection<String> uniquePhones = new HashSet<String>(Contents.PHONE_KEYS.length);
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
String phone = trim(bundle.getString(Contents.PHONE_KEYS[x]));
if (phone != null) {
uniquePhones.add(phone);
}
}
for (String phone : uniquePhones) {
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
}
Collection<String> uniqueEmails = new HashSet<String>(Contents.EMAIL_KEYS.length);
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
String email = trim(bundle.getString(Contents.EMAIL_KEYS[x]));
if (email != null) {
uniqueEmails.add(email);
}
}
for (String email : uniqueEmails) {
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
newDisplayContents.append('\n').append(email);
}
String url = trim(bundle.getString(Contents.URL_KEY));
if (url != null) {
// escapeMECARD(url) -> wrong escape e.g. http\://zxing.google.com
newContents.append("URL:").append(url).append(';');
newDisplayContents.append('\n').append(url);
}
String note = trim(bundle.getString(Contents.NOTE_KEY));
if (note != null) {
newContents.append("NOTE:").append(escapeMECARD(note)).append(';');
newDisplayContents.append('\n').append(note);
}
// Make sure we've encoded at least one field.
if (newDisplayContents.length() > 0) {
newContents.append(';');
contents = newContents.toString();
displayContents = newDisplayContents.toString();
title = "Contact";
} else {
contents = null;
displayContents = null;
}
}
} else if (type.equals(Contents.Type.LOCATION)) {
if (bundle != null) {
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) {
contents = "geo:" + latitude + ',' + longitude;
displayContents = latitude + "," + longitude;
title = "Location";
}
}
}
}
public Bitmap encodeAsBitmap() throws WriterException {
if (!encoded) return null;
Hashtable<EncodeHintType, String> hints = null;
String encoding = guessAppropriateEncoding(contents);
if (encoding != null) {
hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result =writer.encode(contents, format, 300, 300, hints);
int width = result.getWidth();
int height =result.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
if(result.get(x, y) )
{
pixels[offset + x] = BLACK ;
}
else
pixels[offset + x] = WHITE ;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) { return "UTF-8"; }
}
return null;
}
private static String trim(String s) {
if (s == null) { return null; }
String result = s.trim();
return result.length() == 0 ? null : result;
}
private static String escapeMECARD(String input) {
if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) { return input; }
int length = input.length();
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == ':' || c == ';') {
result.append('\\');
}
result.append(c);
}
return result.toString();
}
}
and also need content.java class..
public class Contents {
private Contents() {
}
public static final class Type {
public static final String TEXT = "TEXT_TYPE";
public static final String EMAIL = "EMAIL_TYPE";
public static final String PHONE = "PHONE_TYPE";
public static final String SMS = "SMS_TYPE";
public static final String CONTACT = "CONTACT_TYPE";
public static final String LOCATION = "LOCATION_TYPE";
private Type() {
}
}
public static final String URL_KEY = "URL_KEY";
public static final String NOTE_KEY = "NOTE_KEY";
public static final String[] PHONE_KEYS = {
ContactsContract.Intents.Insert.PHONE, ContactsContract.Intents.Insert.SECONDARY_PHONE,
ContactsContract.Intents.Insert.TERTIARY_PHONE
};
public static final String[] PHONE_TYPE_KEYS = {
ContactsContract.Intents.Insert.PHONE_TYPE,
ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE,
ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE
};
public static final String[] EMAIL_KEYS = {
ContactsContract.Intents.Insert.EMAIL, ContactsContract.Intents.Insert.SECONDARY_EMAIL,
ContactsContract.Intents.Insert.TERTIARY_EMAIL
};
public static final String[] EMAIL_TYPE_KEYS = {
ContactsContract.Intents.Insert.EMAIL_TYPE,
ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE,
ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE
};
}
also need the core.jar file..
its perfectly work...

How to save the Scanned QR code images into image view in Android?

I am use Zxing code for QR code reading. It's working fine.
My problem is how to display the scanned QR code into the image view.
please help me.
Thanks in Advance.
Android Manifest:
<uses-sdk android:minSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo.Light">
<activity
android:name=".GenerateQRCodeActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
Android Layout - main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<TextView android:id="#+id/textView1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Input some text here ..."
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText android:id="#+id/qrInput" android:layout_width="match_parent"
android:layout_height="wrap_content" android:ems="10">
<requestFocus />
</EditText>
<Button android:id="#+id/button1" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="Generate QR Code" />
<ImageView android:id="#+id/imageView1" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Android Activity - GenerateQRCodeActivity.java
package com.as400samplecode;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
public class GenerateQRCodeActivity extends Activity implements OnClickListener{
private String LOG_TAG = "GenerateQRCode";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button1 = (Button) findViewById(R.id.button1);
button1.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
EditText qrInput = (EditText) findViewById(R.id.qrInput);
String qrInputText = qrInput.getText().toString();
Log.v(LOG_TAG, qrInputText);
//Find screen size
WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
Point point = new Point();
display.getSize(point);
int width = point.x;
int height = point.y;
int smallerDimension = width < height ? width : height;
smallerDimension = smallerDimension * 3/4;
//Encode with a QR Code image
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(qrInputText,
null,
Contents.Type.TEXT,
BarcodeFormat.QR_CODE.toString(),
smallerDimension);
try {
Bitmap bitmap = qrCodeEncoder.encodeAsBitmap();
ImageView myImage = (ImageView) findViewById(R.id.imageView1);
myImage.setImageBitmap(bitmap);
} catch (WriterException e) {
e.printStackTrace();
}
break;
// More buttons go here (if any) ...
}
}
}
Source for QRCodeEncoder.java
package com.as400samplecode;
import android.provider.ContactsContract;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.telephony.PhoneNumberUtils;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
public final class QRCodeEncoder {
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
private int dimension = Integer.MIN_VALUE;
private String contents = null;
private String displayContents = null;
private String title = null;
private BarcodeFormat format = null;
private boolean encoded = false;
public QRCodeEncoder(String data, Bundle bundle, String type, String format, int dimension) {
this.dimension = dimension;
encoded = encodeContents(data, bundle, type, format);
}
public String getContents() {
return contents;
}
public String getDisplayContents() {
return displayContents;
}
public String getTitle() {
return title;
}
private boolean encodeContents(String data, Bundle bundle, String type, String formatString) {
// Default to QR_CODE if no format given.
format = null;
if (formatString != null) {
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
}
}
if (format == null || format == BarcodeFormat.QR_CODE) {
this.format = BarcodeFormat.QR_CODE;
encodeQRCodeContents(data, bundle, type);
} else if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
return contents != null && contents.length() > 0;
}
private void encodeQRCodeContents(String data, Bundle bundle, String type) {
if (type.equals(Contents.Type.TEXT)) {
if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "Text";
}
} else if (type.equals(Contents.Type.EMAIL)) {
data = trim(data);
if (data != null) {
contents = "mailto:" + data;
displayContents = data;
title = "E-Mail";
}
} else if (type.equals(Contents.Type.PHONE)) {
data = trim(data);
if (data != null) {
contents = "tel:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "Phone";
}
} else if (type.equals(Contents.Type.SMS)) {
data = trim(data);
if (data != null) {
contents = "sms:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "SMS";
}
} else if (type.equals(Contents.Type.CONTACT)) {
if (bundle != null) {
StringBuilder newContents = new StringBuilder(100);
StringBuilder newDisplayContents = new StringBuilder(100);
newContents.append("MECARD:");
String name = trim(bundle.getString(ContactsContract.Intents.Insert.NAME));
if (name != null) {
newContents.append("N:").append(escapeMECARD(name)).append(';');
newDisplayContents.append(name);
}
String address = trim(bundle.getString(ContactsContract.Intents.Insert.POSTAL));
if (address != null) {
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
newDisplayContents.append('\n').append(address);
}
Collection<String> uniquePhones = new HashSet<String>(Contents.PHONE_KEYS.length);
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
String phone = trim(bundle.getString(Contents.PHONE_KEYS[x]));
if (phone != null) {
uniquePhones.add(phone);
}
}
for (String phone : uniquePhones) {
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
}
Collection<String> uniqueEmails = new HashSet<String>(Contents.EMAIL_KEYS.length);
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
String email = trim(bundle.getString(Contents.EMAIL_KEYS[x]));
if (email != null) {
uniqueEmails.add(email);
}
}
for (String email : uniqueEmails) {
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
newDisplayContents.append('\n').append(email);
}
String url = trim(bundle.getString(Contents.URL_KEY));
if (url != null) {
// escapeMECARD(url) -> wrong escape e.g. http\://zxing.google.com
newContents.append("URL:").append(url).append(';');
newDisplayContents.append('\n').append(url);
}
String note = trim(bundle.getString(Contents.NOTE_KEY));
if (note != null) {
newContents.append("NOTE:").append(escapeMECARD(note)).append(';');
newDisplayContents.append('\n').append(note);
}
// Make sure we've encoded at least one field.
if (newDisplayContents.length() > 0) {
newContents.append(';');
contents = newContents.toString();
displayContents = newDisplayContents.toString();
title = "Contact";
} else {
contents = null;
displayContents = null;
}
}
} else if (type.equals(Contents.Type.LOCATION)) {
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) {
contents = "geo:" + latitude + ',' + longitude;
displayContents = latitude + "," + longitude;
title = "Location";
}
}
}
}
public Bitmap encodeAsBitmap() throws WriterException {
if (!encoded) return null;
Map<EncodeHintType, Object> hints = null;
String encoding = guessAppropriateEncoding(contents);
if (encoding != null) {
hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result = writer.encode(contents, format, dimension, dimension, hints);
int width = result.getWidth();
int height = result.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
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);
return bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) { return "UTF-8"; }
}
return null;
}
private static String trim(String s) {
if (s == null) { return null; }
String result = s.trim();
return result.length() == 0 ? null : result;
}
private static String escapeMECARD(String input) {
if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) { return input; }
int length = input.length();
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == ':' || c == ';') {
result.append('\\');
}
result.append(c);
}
return result.toString();
}
}
Source for Contents.java
package com.as400samplecode;
import android.provider.ContactsContract;
public final class Contents {
private Contents() {
}
public static final class Type {
// Plain text. Use Intent.putExtra(DATA, string). This can be used for URLs too, but string
// must include "http://" or "https://".
public static final String TEXT = "TEXT_TYPE";
// An email type. Use Intent.putExtra(DATA, string) where string is the email address.
public static final String EMAIL = "EMAIL_TYPE";
// Use Intent.putExtra(DATA, string) where string is the phone number to call.
public static final String PHONE = "PHONE_TYPE";
// An SMS type. Use Intent.putExtra(DATA, string) where string is the number to SMS.
public static final String SMS = "SMS_TYPE";
// A contact. Send a request to encode it as follows:
// <p/>
// import android.provider.Contacts;
// <p/>
// Intent intent = new Intent(Intents.Encode.ACTION); intent.putExtra(Intents.Encode.TYPE,
// CONTACT); Bundle bundle = new Bundle(); bundle.putString(Contacts.Intents.Insert.NAME,
// "Jenny"); bundle.putString(Contacts.Intents.Insert.PHONE, "8675309");
// bundle.putString(Contacts.Intents.Insert.EMAIL, "jenny#the80s.com");
// bundle.putString(Contacts.Intents.Insert.POSTAL, "123 Fake St. San Francisco, CA 94102");
// intent.putExtra(Intents.Encode.DATA, bundle);
public static final String CONTACT = "CONTACT_TYPE";
public static final String LOCATION = "LOCATION_TYPE";
private Type() {
}
}
public static final String URL_KEY = "URL_KEY";
public static final String NOTE_KEY = "NOTE_KEY";
// When using Type.CONTACT, these arrays provide the keys for adding or retrieving multiple
// phone numbers and addresses.
public static final String[] PHONE_KEYS = {
ContactsContract.Intents.Insert.PHONE, ContactsContract.Intents.Insert.SECONDARY_PHONE,
ContactsContract.Intents.Insert.TERTIARY_PHONE
};
public static final String[] PHONE_TYPE_KEYS = {
ContactsContract.Intents.Insert.PHONE_TYPE,
ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE,
ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE
};
public static final String[] EMAIL_KEYS = {
ContactsContract.Intents.Insert.EMAIL, ContactsContract.Intents.Insert.SECONDARY_EMAIL,
ContactsContract.Intents.Insert.TERTIARY_EMAIL
};
public static final String[] EMAIL_TYPE_KEYS = {
ContactsContract.Intents.Insert.EMAIL_TYPE,
ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE,
ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE
};
}
Here is your answer you are looking for may be.
Try this tutorial. you will get the QR-CODE/BAR-CODE in the imageview residing in your app. http://www.mysamplecode.com/2012/09/android-generate-qr-code-using-zxing.html
after getting your Bar-Code in the imageview, you can convert this as a bitmap as
ImageView v1 = (ImageView)findViewById(R.id.mImage);
v1.setDrawingCacheEnabled(true);
Bitmap bm = v1.getDrawingCache();
now you have your bitmap, you can play with it now.
Hope this helps you.
also see my question I have asked the same How to store the Generated QR-Code as an image in SDCard (ZXing library)
After scanned you have some result, from camera. This code is code for display ImageView
bitmap = encodeAsBitmap(qrInput.getText().toString(), BarcodeFormat.CODE_128, 600, 300);
final ImageView myImage = (ImageView) findViewById(R.id.imageView1);
myImage.setImageBitmap(bitmap);
Replace qrInput with your result, and BarcodeFormat.QR_CODE.TEXT to your format of QR code
and add this for encode image.
Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int img_width, int img_height) throws WriterException {
String contentsToEncode = contents;
if (contentsToEncode == null) {
return null;
}
Map<EncodeHintType, Object> hints = null;
String encoding = guessAppropriateEncoding(contentsToEncode);
if (encoding != null) {
hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result;
try {
result = writer.encode(contentsToEncode, format, img_width, img_height, hints);
} catch (IllegalArgumentException iae) {
// Unsupported format
Log.d("XXX4", "Unsupported format -" + iae);
Toast.makeText(this, iae.getLocalizedMessage(), Toast.LENGTH_LONG).show();
return null;
} catch (Exception e) {
Toast.makeText(this, "Sorry - Try Changing Content", Toast.LENGTH_LONG).show();
return null;
}
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;
}
}
int img_widths = 400;
int img_heights = 400;
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
if (format == BarcodeFormat.DATA_MATRIX) {
bitmap = drawScaledBitmap(bitmap, img_widths, img_heights);
}
return bitmap;
}
public Bitmap drawScaledBitmap(Bitmap bitmap, int img_widths, int img_heights) {
final int bmWidth = bitmap.getWidth();
final int bmHeight = bitmap.getHeight();
final int wScalingFactor = img_widths / bmWidth;
final int hScalingFactor = img_heights / bmHeight;
final int scalingFactor = Math.min(wScalingFactor, hScalingFactor);
return scalingFactor > 1 ? Bitmap.createScaledBitmap(bitmap, bmWidth * scalingFactor, bmHeight * scalingFactor, false) : bitmap;
}
private static String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) {
return "UTF-8";
}
}
return null;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}

Android - decryption issues with AES encrypted string in QR code

I've built a QR code generator and a QR code scanner for passing data about phones and their users between phones (the phones are being loaned out so there will be a master phone with the scanner app and the rest with the generator app). The QR code generated is a JSON format string containing a persons name/number/imei of their phone but for security I have tried to encrypt the string before encoding to QR, but the scanned QR code throws up a 'pad block corrupted' error.
The JSON data encodes into QR/decodes from QR fine as plain text, and I checked the encryption/decryption before encoding to QR and the data encrypts/decrypts fine, so it's something to do with when the encrypted text is encoded into QR but I've no idea where to begin with it!
Does anyone know how i can sort the issue? Or if theres any QR friendly encryption methods?!!
I took the QRCodeEncoder straight from ZXings source and placed it into my activity:
/**QR ENCODER CLASS****************************************************/
public class QRCodeEncoder
{
private final String TAG = QRCodeEncoder.class.getSimpleName();
private static final int WHITE = 0xFFFFFFFF;
private static final int BLACK = 0xFF000000;
private final Activity activity;
private String contents;
private String displayContents;
private String title;
private BarcodeFormat format;
private final int dimension;
QRCodeEncoder(Activity activity, Intent intent, int dimension) {
this.activity = activity;
if (intent == null) {
throw new IllegalArgumentException("No valid data to encode. intent is null");
}
String action = intent.getAction();
if (action.equals(Intents.Encode.ACTION)) {
if (!encodeContentsFromZXingIntent(intent)) {
throw new IllegalArgumentException("No valid data to encode. Zxing intent returned false");
}
} else if (action.equals(Intent.ACTION_SEND)) {
if (!encodeContentsFromShareIntent(intent)) {
throw new IllegalArgumentException("No valid data to encode. Share Intent returned false");
}
}
this.dimension = dimension;
}
public String getContents() {
return contents;
}
public String getDisplayContents() {
return displayContents;
}
public String getTitle() {
return title;
}
// 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 encodeContentsFromZXingIntent(Intent intent) {
// Default to QR_CODE if no format given.
String formatString = intent.getStringExtra(Intents.Encode.FORMAT);
try {
format = BarcodeFormat.valueOf(formatString);
} catch (IllegalArgumentException iae) {
// Ignore it then
format = null;
}
if (format == null || BarcodeFormat.QR_CODE.equals(format)) {
String type = intent.getStringExtra(Intents.Encode.TYPE);
if (type == null || type.length() == 0) {
return false;
}
this.format = BarcodeFormat.QR_CODE;
encodeQRCodeContents(intent, type);
} else {
String data = intent.getStringExtra(Intents.Encode.DATA);
if (data != null && data.length() > 0) {
contents = data;
displayContents = data;
title = "QR Encoder";
}
}
return contents != null && contents.length() > 0;
}
// Handles send intents from multitude of Android applications
private boolean encodeContentsFromShareIntent(Intent intent) {
// Check if this is a plain text encoding, or contact
if (intent.hasExtra(Intent.EXTRA_TEXT)) {
return encodeContentsFromShareIntentPlainText(intent);
}
// Attempt default sharing.
return encodeContentsFromShareIntentDefault(intent);
}
private boolean encodeContentsFromShareIntentPlainText(Intent intent) {
// Notice: Google Maps shares both URL and details in one text, bummer!
contents = intent.getStringExtra(Intent.EXTRA_TEXT);
Toast.makeText(getApplicationContext(),"contents read = "+contents,Toast.LENGTH_SHORT).show();
// We only support non-empty and non-blank texts.
// Trim text to avoid URL breaking.
if (contents == null) {
return false;
}
contents = contents.trim();
if (contents.length() == 0) {
return false;
}
// We only do QR code.
format = BarcodeFormat.QR_CODE;
if (intent.hasExtra(Intent.EXTRA_SUBJECT)) {
displayContents = intent.getStringExtra(Intent.EXTRA_SUBJECT);
} else if (intent.hasExtra(Intent.EXTRA_TITLE)) {
displayContents = intent.getStringExtra(Intent.EXTRA_TITLE);
} else {
displayContents = contents;
}
title = "QR Encoder";
return true;
}
// Handles send intents from the Contacts app, retrieving a contact as a VCARD.
// Note: Does not work on HTC devices due to broken custom Contacts application.
private boolean encodeContentsFromShareIntentDefault(Intent intent) {
format = BarcodeFormat.QR_CODE;
try {
Uri uri = (Uri)intent.getExtras().getParcelable(Intent.EXTRA_STREAM);
InputStream stream = activity.getContentResolver().openInputStream(uri);
int length = stream.available();
if (length <= 0) {
Log.w(TAG, "Content stream is empty");
return false;
}
byte[] vcard = new byte[length];
int bytesRead = stream.read(vcard, 0, length);
if (bytesRead < length) {
Log.w(TAG, "Unable to fully read available bytes from content stream");
return false;
}
String vcardString = new String(vcard, 0, bytesRead, "UTF-8");
Log.d(TAG, "Encoding share intent content:");
Log.d(TAG, vcardString);
Result result = new Result(vcardString, vcard, null, BarcodeFormat.QR_CODE);
ParsedResult parsedResult = ResultParser.parseResult(result);
if (!(parsedResult instanceof AddressBookParsedResult)) {
Log.d(TAG, "Result was not an address");
return false;
}
if (!encodeQRCodeContents((AddressBookParsedResult) parsedResult)) {
Log.d(TAG, "Unable to encode contents");
return false;
}
} catch (IOException e) {
Log.w(TAG, e);
return false;
} catch (NullPointerException e) {
Log.w(TAG, e);
// In case the uri was not found in the Intent.
return false;
}
return contents != null && contents.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) {
contents = data;
displayContents = data;
title = "QR Encoder";
}
} else if (type.equals(Contents.Type.EMAIL)) {
String data = trim(intent.getStringExtra(Intents.Encode.DATA));
if (data != null) {
contents = "mailto:" + data;
displayContents = data;
title = "QR Encoder";
}
} else if (type.equals(Contents.Type.PHONE)) {
String data = trim(intent.getStringExtra(Intents.Encode.DATA));
if (data != null) {
contents = "tel:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "QR Encoder";
}
} else if (type.equals(Contents.Type.SMS)) {
String data = trim(intent.getStringExtra(Intents.Encode.DATA));
if (data != null) {
contents = "sms:" + data;
displayContents = PhoneNumberUtils.formatNumber(data);
title = "QR Encoder";
}
} else if (type.equals(Contents.Type.CONTACT)) {
Bundle bundle = intent.getBundleExtra(Intents.Encode.DATA);
if (bundle != null) {
StringBuilder newContents = new StringBuilder(100);
StringBuilder newDisplayContents = new StringBuilder(100);
newContents.append("MECARD:");
String name = trim(bundle.getString(Contacts.Intents.Insert.NAME));
if (name != null) {
newContents.append("N:").append(escapeMECARD(name)).append(';');
newDisplayContents.append(name);
}
String address = trim(bundle.getString(Contacts.Intents.Insert.POSTAL));
if (address != null) {
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
newDisplayContents.append('\n').append(address);
}
for (int x = 0; x < Contents.PHONE_KEYS.length; x++) {
String phone = trim(bundle.getString(Contents.PHONE_KEYS[x]));
if (phone != null) {
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
}
}
for (int x = 0; x < Contents.EMAIL_KEYS.length; x++) {
String email = trim(bundle.getString(Contents.EMAIL_KEYS[x]));
if (email != null) {
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
newDisplayContents.append('\n').append(email);
}
}
// Make sure we've encoded at least one field.
if (newDisplayContents.length() > 0) {
newContents.append(';');
contents = newContents.toString();
displayContents = newDisplayContents.toString();
title = "QR Encoder";
} else {
contents = null;
displayContents = 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) {
contents = "geo:" + latitude + ',' + longitude;
displayContents = latitude + "," + longitude;
title = "QR Encoder";
}
}
}
}
private boolean encodeQRCodeContents(AddressBookParsedResult contact) {
StringBuilder newContents = new StringBuilder(100);
StringBuilder newDisplayContents = new StringBuilder(100);
newContents.append("MECARD:");
String[] names = contact.getNames();
if (names != null && names.length > 0) {
String name = trim(names[0]);
if (name != null) {
newContents.append("N:").append(escapeMECARD(name)).append(';');
newDisplayContents.append(name);
}
}
String[] addresses = contact.getAddresses();
if (addresses != null) {
for (String address : addresses) {
address = trim(address);
if (address != null) {
newContents.append("ADR:").append(escapeMECARD(address)).append(';');
newDisplayContents.append('\n').append(address);
}
}
}
String[] phoneNumbers = contact.getPhoneNumbers();
if (phoneNumbers != null) {
for (String phone : phoneNumbers) {
phone = trim(phone);
if (phone != null) {
newContents.append("TEL:").append(escapeMECARD(phone)).append(';');
newDisplayContents.append('\n').append(PhoneNumberUtils.formatNumber(phone));
}
}
}
String[] emails = contact.getEmails();
if (emails != null) {
for (String email : emails) {
email = trim(email);
if (email != null) {
newContents.append("EMAIL:").append(escapeMECARD(email)).append(';');
newDisplayContents.append('\n').append(email);
}
}
}
String url = trim(contact.getURL());
if (url != null) {
newContents.append("URL:").append(escapeMECARD(url)).append(';');
newDisplayContents.append('\n').append(url);
}
// Make sure we've encoded at least one field.
if (newDisplayContents.length() > 0) {
newContents.append(';');
contents = newContents.toString();
displayContents = newDisplayContents.toString();
title = "QR Encoder";
return true;
} else {
contents = null;
displayContents = null;
return false;
}
}
Bitmap encodeAsBitmap() throws WriterException {
Hashtable<EncodeHintType,Object> hints = null;
String encoding = guessAppropriateEncoding(contents);
if (encoding != null) {
hints = new Hashtable<EncodeHintType,Object>(2);
hints.put(EncodeHintType.CHARACTER_SET, encoding);
}
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result = writer.encode(contents, format, dimension, dimension, hints);
int width = result.getWidth();
int height = result.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
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);
return bitmap;
}
private String guessAppropriateEncoding(CharSequence contents) {
// Very crude at the moment
for (int i = 0; i < contents.length(); i++) {
if (contents.charAt(i) > 0xFF) {
return "UTF-8";
}
}
return null;
}
private String trim(String s) {
if (s == null) {
return null;
}
s = s.trim();
return s.length() == 0 ? null : s;
}
private String escapeMECARD(String input) {
if (input == null || (input.indexOf(':') < 0 && input.indexOf(';') < 0)) {
return input;
}
int length = input.length();
StringBuilder result = new StringBuilder(length);
for (int i = 0; i < length; i++) {
char c = input.charAt(i);
if (c == ':' || c == ';') {
result.append('\\');
}
result.append(c);
}
return result.toString();
}
}
And the encryption/decryption class from this website (unedited)
Here's a snippet of the onCreate() method in my activity:
QRCodeEncoder myQRCodeEncoder;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.qr_view);
ImageView imageView = (ImageView)findViewById(R.id.qr_image);
extStorageDirectory = Environment.getExternalStorageDirectory().toString();
try
{
//JSON data is passed from another activity to this one
qrMessage = getIntent().getStringExtra("QR_JSON");
Intent encode = new Intent(Intents.Encode.ACTION);
encode.putExtra(Intents.Encode.TYPE, Contents.Type.TEXT);
encode.putExtra(Intents.Encode.FORMAT, "QR_CODE");
//This is the original plain text way that works:
//encode.putExtra(Intents.Encode.DATA, qrMessage);
//This is the encyption way
String encMessage = SimpleCrypto.encrypt("my s3cr3t k3y", qrMessage);
encode.putExtra(Intents.Encode.DATA,encMessage);
myQRCodeEncoder = new QRCodeEncoder(this, encode, 200);
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(),"Could not encode:"+e.getMessage(),Toast.LENGTH_SHORT).show();
}
catch(Error e)
{
Toast.makeText(getApplicationContext(),"Could not encode:"+e.getMessage(),Toast.LENGTH_SHORT).show();
}
try {
Bitmap qrBitmap = myQRCodeEncoder.encodeAsBitmap();
imageView.setImageBitmap(qrBitmap);
} catch (Exception e) {
Toast.makeText(getApplicationContext(),"Could not set image:"+e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
And here's the onActivityResult method from the scanner (I use ZXing's barcode scanner to retrieve the data)
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");//contents of the scan
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
// Handle successful scan
/* display the scanned persons info*/
try {
String decryptedcontents = SimpleCrypto.decrypt("my s3cr3t k3y",contents);
String result = getJSONFromScanData(decryptedcontents);
} catch (Exception e) {
// TODO Auto-generated catch block
Toast.makeText(this, "Scanned data could not be decrypted:"+e.getMessage(), Toast.LENGTH_SHORT).show();//says 'pad block corrupted' as the message
}
} else if (resultCode == RESULT_CANCELED) {
// Handle cancel
Toast.makeText(this, "Scan cancelled", Toast.LENGTH_SHORT).show();
}
}
}
EDIT: after some further investigation it seems that the encyption/decyption process seems to 'shave off' part of the data:
JSONObject example = new JSONObject("{\"user_firstname\":\"Ben\",\"user_lastname\":\" Ten\",\"user_login\":\"benten\",\"user_pass\":\"password\",\"user_email\":\"benten#domain.com\"}");
String mess = SimpleCrypto.encrypt("my s3cr3t k3y",example.toString());
String decrmess = SimpleCrypto.decrypt("my s3cr3t k3y",mess));
//decypts as:{"user_pass":"password","user_email":"benten#domain.com","user_login":"benten","user_lastname":"
as you can see only 96 characters are decrypted, theres no user_firstname or the users actual last name, the data is missing, but this number is inconsistent, I changed the user_email to "benbenten#domain.com" and the user_firstname to "benben" and 112 characters were decrypted...I am completely stumped
EDIT 2: Yngve Ã…dlandsvik has kindly pointed me in the right direction (many thanks again!) that the string length needed to be a multiple of 16, so I set the Cipher.getInstance in both the encrypt and decrypt methods to:
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding","BC");
and in my main activity set a loop to add 0's on the end of my string as custom padding before encrypting:
boolean carryOn = true;
while(carryOn)
{
int paddedLength = qrMessage.getBytes().length;
int checkMultiple16 = paddedLength%16;
if(checkMultiple16==0)
{
carryOn = false;
}
else
qrMessage+="0";
}
EDIT 3: It looks like QR encoding still screws with the encryption, I can't decrypt the scanned in data properly, looks like QR encoding does something with strings before it encodes to QR which seems to break the thing, guess I'll have to stick to unencrypted text in the QR...
I haven't read the code closely, but I assume this happens because AES only operates on blocks of 16 bytes at once. So my guess is you need to manually apply some form of reversible padding to your string before encryption so it becomes a multiple of 16, and then reverse the padding after decryption.
You could also change the Cipher.getInstance() strings in the crypto code so the encryption will support padding natively, though I don't know which padding types and cipher modes are available on Android.

Categories

Resources