Java Wi-Fi QR Code

I read a few blogs about technology and new things on the internet and the other day this post (Have guests often – Generate a QR Code with your Wi-Fi details that you can frame on your wall) came up about printing off a QR Code for your guests to log into your Wi-Fi. I followed the link to the site to see what the QR Code generator looked like and thought about filling it in. Then I stopped… Even though the person that made the site is exceedingly unlikely to ever visit my area, why would I fill out my SSID and password onto a random site?!

I was asked this summer by someone visiting for my wifi password, which I printed off and passed to him. He looked back at me and said that’ll take so long to type in, it’s not worth it. I always choose a minimum of 20 characters password which is completely random. Why? Well, technology improves so fast that cracking a password is easier each year. I read an article a couple of years ago which explained how WPA2 passwords could be computed in under 20 minutes on the Amazon cloud. Therefore, since the password doesn’t have to be typed too often, why not go for a really long password… If I can create a QR Code, that minimum 20 characters could be increased to 40+ as most visitors wouldn’t have to type the code!

So I thought I’d see if I could generate a QR Code in Java on my own PC. A quick google and stackoverflow later and the popular barcode generator at the moment for Java seemed to be zxing. I’ve got a few projects in my Eclipse workspace for testing out different snippets of code, so I added the jars to the pom as follows:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>uk.co.vsf</groupId>
	<artifactId>Test</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
		</dependency>
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>core</artifactId>
			<version>2.1</version>
		</dependency>
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>javase</artifactId>
			<version>2.1</version>
		</dependency>
	</dependencies>
</project>

Next, since all I want to do is test out the creation of a QR Code to img file, a simple test class will suffice:

package uk.co.vsf.test;

import static java.lang.String.format;

import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

import org.junit.Test;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * Test class for testing out zxing and QR Codes.
 */
public class QRTest {

    @Test
    public void generateQRCodeForWiFi() throws IOException, WriterException {

        // Remember to encode the string if it contains unusual characters - see internet page
        String ssid = "abc";
        String password = "def";

        String wifiString = "WIFI:S:%s;T:WPA;P:%s;;";
        wifiString = format(wifiString, ssid, password);

        MultiFormatWriter writer = new MultiFormatWriter();
        Hashtable<EncodeHintType, ErrorCorrectionLevel> hints = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);

        // image has to be big enough to print onto A4 in reasonable quality
        // so 1600 should do.
        BitMatrix bitMatrix = writer.encode(wifiString, BarcodeFormat.QR_CODE, 1600, 1600, hints);
        MatrixToImageWriter.writeToFile(bitMatrix, "png", new File("qrcode.png"));
    }
}

And when that test method is run, you get the following output:

qrcode

Cool eh?