32

I was having some problem when trying to generate QR code in Android Programming. Here is the Tutorial I followed. When my generate button on click, I am calling this method:

private void generateQR(){
    String qrInputText = "test";

    //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.ivImage);
        myImage.setImageBitmap(bitmap);
    } catch (WriterException e) {
        e.printStackTrace();
    }
}

And then for the QRCodeEncoder and Contents classes, I followed the one in the tutorial. However, when I click on generate, I am getting the error message as:

01-30 16:37:03.093: I/dalvikvm(1069): Could not find method com.google.zxing.BarcodeFormat.valueOf, referenced from method com.example.qrcodescan.QRCodeEncoder.encodeContents
01-30 16:37:03.093: W/dalvikvm(1069): VFY: unable to resolve static method 338: Lcom/google/zxing/BarcodeFormat;.valueOf (Ljava/lang/String;)Lcom/google/zxing/BarcodeFormat;
01-30 16:37:03.093: D/dalvikvm(1069): VFY: replacing opcode 0x71 at 0x0005
01-30 16:37:03.093: W/dalvikvm(1069): VFY: unable to resolve static field 287 (QR_CODE) in Lcom/google/zxing/BarcodeFormat;
01-30 16:37:03.093: D/dalvikvm(1069): VFY: replacing opcode 0x62 at 0x0011
01-30 16:37:03.093: W/dalvikvm(1069): VFY: unable to resolve static field 287 (QR_CODE) in Lcom/google/zxing/BarcodeFormat;
01-30 16:37:03.093: D/dalvikvm(1069): VFY: replacing opcode 0x62 at 0x0015
01-30 16:37:03.093: W/dalvikvm(1069): VFY: unable to resolve static field 294 (CHARACTER_SET) in Lcom/google/zxing/EncodeHintType;
01-30 16:37:03.093: D/dalvikvm(1069): VFY: replacing opcode 0x62 at 0x0018
01-30 16:37:03.093: E/dalvikvm(1069): Could not find class 'com.google.zxing.MultiFormatWriter', referenced from method com.example.qrcodescan.QRCodeEncoder.encodeAsBitmap
01-30 16:37:03.093: W/dalvikvm(1069): VFY: unable to resolve new-instance 150 (Lcom/google/zxing/MultiFormatWriter;) in Lcom/example/qrcodescan/QRCodeEncoder;
01-30 16:37:03.093: D/dalvikvm(1069): VFY: replacing opcode 0x22 at 0x001d
01-30 16:37:03.093: D/dalvikvm(1069): DexOpt: unable to opt direct call 0x0159 at 0x1f in Lcom/example/qrcodescan/QRCodeEncoder;.encodeAsBitmap
01-30 16:37:03.093: D/AndroidRuntime(1069): Shutting down VM
01-30 16:37:03.093: W/dalvikvm(1069): threadid=1: thread exiting with uncaught exception (group=0x40c341f8)
01-30 16:37:03.101: E/AndroidRuntime(1069): FATAL EXCEPTION: main
01-30 16:37:03.101: E/AndroidRuntime(1069): java.lang.NoClassDefFoundError: com.google.zxing.BarcodeFormat
01-30 16:37:03.101: E/AndroidRuntime(1069):     at com.example.qrcodescan.MainActivity.generateQR(MainActivity.java:95)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at com.example.qrcodescan.MainActivity.access$0(MainActivity.java:77)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at com.example.qrcodescan.MainActivity$2.onClick(MainActivity.java:54)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at android.view.View.performClick(View.java:3620)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at android.view.View$PerformClick.run(View.java:14292)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at android.os.Handler.handleCallback(Handler.java:605)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at android.os.Handler.dispatchMessage(Handler.java:92)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at android.os.Looper.loop(Looper.java:137)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at android.app.ActivityThread.main(ActivityThread.java:4512)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at java.lang.reflect.Method.invokeNative(Native Method)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at java.lang.reflect.Method.invoke(Method.java:511)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:982)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:749)
01-30 16:37:03.101: E/AndroidRuntime(1069):     at dalvik.system.NativeStart.main(Native Method)

I did added the core.jar under libs folder. Any ideas? Thanks in advance.

Giulio Biagini
  • 935
  • 5
  • 8

5 Answers5

74

I have updated my small demo project at Github and my answer below for the year 2022:

screenshot

Add the ZXing library to your app/build.gradle file:

implementation 'com.google.zxing:core:3.4.1'

And then use the following function in your MainActivity.java to generate a QR code image out of a string:

Bitmap encodeAsBitmap(String str) throws WriterException {
    QRCodeWriter writer = new QRCodeWriter();
    BitMatrix bitMatrix = writer.encode(str, BarcodeFormat.QR_CODE, 400, 400);

    int w = bitMatrix.getWidth();
    int h = bitMatrix.getHeight();
    int[] pixels = new int[w * h];
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            pixels[y * w + x] = bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE;
        }
    }

    Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
    return bitmap;
}
Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
  • Will this technique work without GooglePlayService installed on the users device? In your other answer: http://stackoverflow.com/a/30572168/2371425. It almost implies that the user will need GooglePlayServices. Also when I use this answer to generate QRcode, there's a brief popup about needing GooglePlayServices and a Log statement. – Sakiboy Nov 12 '15 at 18:29
  • 1
    FOR SCANNING: If you detect, that BOTH Google Play is missing (on Amazon or Blackberry or Cyanogen device) AND Barcode Scanner app is not installed, then you could redirect the user to alternative "app store" manually. FOR JUST GENERATING QR CODE: I don't know - try it yourself and report here. – Alexander Farber Nov 12 '15 at 18:55
  • FOR JUST GENERATING: I've run it on an emulator without GooglePlay, we receive an alert for a split second saying "This app won't run without Google Play Services which are missing from your phone." With a button that says "Get Google Play services". The alert isn't there long enough for the user to take action or let alone read it. BUT the QRcode is still generated. When I run on a device with GooglePlay, we receive no error. – Sakiboy Nov 12 '15 at 19:00
  • 2
    Strange - as you can see in my screenshot I used emulator too - and it never asked me about Google Play – Alexander Farber Nov 12 '15 at 19:01
  • 1
    The alert isn't able to be seen for long. It's only on the screen for a split second, so there's really not enough time for the user to even read it. I had to screen shot it to read the text, it was tough to screenshot because it was only on the screen for less than a second. But anyway, it appears to be working without GooglePlayServices. – Sakiboy Nov 12 '15 at 19:03
  • Great answer by the way. Thank you. – Sakiboy Nov 12 '15 at 19:06
  • You can use this tutorial also http://smartandroiddeveloper.com/2016/01/29/how-to-generate-qrcode-in-10-minutes-using-zxing-library-in-android-studio/ – Sagar Devanga Jul 30 '16 at 15:32
  • 4
    Do we really need to copy-paste that Bitmap creation from BitMatrix? Isn't there utility method for this somewher in zxing lib? – ernazm Nov 08 '17 at 14:53
  • 1
    Perfect! helpful answer – Nininea Oct 18 '18 at 14:40
9
public static int white = 0xFFFFFFFF;
public static int black = 0xFF000000;
public final static int WIDTH = 500;


try
    {
        Bitmap bmp =  encodeAsBitmap("Life is a bitch");
        imgView.setImageBitmap(bmp);
    } catch (Exception e) {
        e.printStackTrace();
    }


Bitmap encodeAsBitmap(String str) throws WriterException {
    BitMatrix result;
    Bitmap bitmap=null;
    try
    {
        result = new MultiFormatWriter().encode(str,
                BarcodeFormat.QR_CODE, WIDTH, WIDTH, null);

        int w = result.getWidth();
        int h = result.getHeight();
        int[] pixels = new int[w * h];
        for (int y = 0; y < h; y++) {
            int offset = y * w;
            for (int x = 0; x < w; x++) {
                pixels[offset + x] = result.get(x, y) ? black:white;
            }
        }
        bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        bitmap.setPixels(pixels, 0, WIDTH, 0, 0, w, h);
    } catch (Exception iae) {
        iae.printStackTrace();
        return null;
    }
    return bitmap;
}
Harpreet
  • 2,990
  • 3
  • 38
  • 52
Anirudh
  • 2,767
  • 5
  • 69
  • 119
8

ZXing library can help here.

Origin is: Generate QRCode Android Example

Add in dependencies

compile 'com.google.zxing:core:3.2.1'

Here is the method to convert string into QR Image

private Bitmap TextToImageEncode(String Value) throws WriterException {
        BitMatrix bitMatrix;
        try {
            bitMatrix = new MultiFormatWriter().encode(
                    Value,
                    BarcodeFormat.DATA_MATRIX.QR_CODE,
                    QRcodeWidth, QRcodeWidth, null
            );
 
        } catch (IllegalArgumentException Illegalargumentexception) {
 
            return null;
        }
        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++) {
 
                pixels[offset + x] = bitMatrix.get(x, y) ?
                        getResources().getColor(R.color.black):getResources().getColor(R.color.white);
            }
        }
        Bitmap bitmap = Bitmap.createBitmap(bitMatrixWidth, bitMatrixHeight, Bitmap.Config.ARGB_4444);
 
        bitmap.setPixels(pixels, 0, 500, 0, 0, bitMatrixWidth, bitMatrixHeight);
        return bitmap;
    }

Save generated QR image

 public String saveImage(Bitmap myBitmap) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
        File wallpaperDirectory = new File(
                Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
        // have the object build the directory structure, if needed.
 
        if (!wallpaperDirectory.exists()) {
            Log.d("dirrrrrr", "" + wallpaperDirectory.mkdirs());
            wallpaperDirectory.mkdirs();
        }
 
        try {
            File f = new File(wallpaperDirectory, Calendar.getInstance()
                    .getTimeInMillis() + ".jpg");
            f.createNewFile();   //give read write permission
            FileOutputStream fo = new FileOutputStream(f);
            fo.write(bytes.toByteArray());
            MediaScannerConnection.scanFile(this,
                    new String[]{f.getPath()},
                    new String[]{"image/jpeg"}, null);
            fo.close();
            Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());
 
            return f.getAbsolutePath();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return "";
 
    }
Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
user6017633
  • 483
  • 7
  • 9
  • this part of code works extremely slow `getResources().getColor(R.color.black):getResources().getColor(R.color.white);` need to replace it to - `colorBlack:colorWhite` where define `colorBlack` and `colorWhite` outside `for` statement. Also maybe will be faster fill all bitmap white and put only black pixels – w201 Jan 21 '19 at 17:24
2

Following code worked for me:

...
String QRcode = "...";
new generateQrcode(qrcodeImageview).execute(QRcode);
...
private class generateQrcode extends AsyncTask<String, Void, Bitmap> {
        public final static int WIDTH = 400;
        ImageView bmImage;

        public generateQrcode(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {
            String Value = urls[0];
            com.google.zxing.Writer writer = new QRCodeWriter();
            Bitmap bitmap = null;
            BitMatrix bitMatrix = null;
            try {
                bitMatrix = writer.encode(Value, com.google.zxing.BarcodeFormat.QR_CODE, WIDTH, WIDTH,
                        ImmutableMap.of(EncodeHintType.MARGIN, 1));
                bitmap = Bitmap.createBitmap(400, 400, Bitmap.Config.ARGB_8888);
                for (int i = 0; i < 400; i++) {
                    for (int j = 0; j < 400; j++) {
                        bitmap.setPixel(i, j, bitMatrix.get(i, j) ? Color.BLACK
                                : Color.WHITE);
                    }
                }
            } catch (WriterException e) {
                e.printStackTrace();
            }
            return bitmap;
        }

        protected void onPostExecute(Bitmap result) {
            bmImage.setImageBitmap(result);
        }
    }
Harshil
  • 914
  • 1
  • 12
  • 26
  • 1
    it would really improve your answer if you could include information like: "Why this code might be helpful?" and "what is so different from that of OP?" this way you would convey knowledge about the solution itself. Basically teaching fishing, instead of feeding fish ;) – Mong Zhu Sep 26 '17 at 13:44
  • ImmutableMap class is not found – Shomu Dec 18 '18 at 09:15
0

Using this library its easier

add the dependency :

implementation 'com.journeyapps:zxing-android-embedded:4.3.0'

and easily get the bitmap:

try {
       val qrCodeBitmap = BarcodeEncoder().encodeBitmap("your qr code data here", BarcodeFormat.QR_CODE, 400, 400)
} catch (e: Exception) {

}
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38