Android二维码的生成与解析

jopen 10年前

本示例演示使用文本生成对应的二维码图片,和解析二维码图片的内容。代码如下:

MainActivity:

    package com.home.testqrcode;                import java.util.HashMap;        import java.util.Hashtable;        import java.util.Map;                import android.app.Activity;        import android.graphics.Bitmap;        import android.graphics.drawable.BitmapDrawable;        import android.os.Bundle;        import android.view.View;        import android.view.View.OnClickListener;        import android.widget.Button;        import android.widget.EditText;        import android.widget.ImageView;        import android.widget.TextView;        import android.widget.Toast;                import com.google.zxing.BarcodeFormat;        import com.google.zxing.BinaryBitmap;        import com.google.zxing.DecodeHintType;        import com.google.zxing.EncodeHintType;        import com.google.zxing.Result;        import com.google.zxing.WriterException;        import com.google.zxing.client.androidtest.RGBLuminanceSource;        import com.google.zxing.common.BitMatrix;        import com.google.zxing.common.HybridBinarizer;        import com.google.zxing.qrcode.QRCodeReader;        import com.google.zxing.qrcode.QRCodeWriter;                public class MainActivity extends Activity implements OnClickListener {            private Button generateBtn;            private Button decodeQRCodeBtn;            private ImageView imageView;            private TextView textView;            private EditText contentText;            private static int QR_WIDTH = 400;            private static int QR_HEIGHT = 400;                    @Override            protected void onCreate(Bundle savedInstanceState) {                super.onCreate(savedInstanceState);                setContentView(R.layout.main);                initWidget();            }                    private void initWidget() {                generateBtn = (Button) findViewById(R.id.main_btn_generateQRCode);                generateBtn.setOnClickListener(this);                decodeQRCodeBtn = (Button) findViewById(R.id.main_btn_decodeQRCode);                decodeQRCodeBtn.setOnClickListener(this);                imageView = (ImageView) findViewById(R.id.main_iv);                textView = (TextView) findViewById(R.id.main_tv);                contentText = (EditText) findViewById(R.id.main_et);            }                    @Override            public void onClick(View v) {                if (v == generateBtn) {                    String text = contentText.getText().toString();                    if ("".equals(text) || null == text) {                        Toast.makeText(this, "请输入内容", Toast.LENGTH_SHORT).show();                        return;                    }                    Bitmap bitmap = createBitmap(text);                    if (bitmap != null) {                        imageView.setImageBitmap(bitmap);                    }                } else if (v == decodeQRCodeBtn) {                    String content = readImage(imageView);                    textView.setText(content);                }            }                    /**            * 生成二维码图片            *             * @return            */            private Bitmap createBitmap(String text) {                Bitmap bitmap = null;                try {                    Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();                    hints.put(EncodeHintType.CHARACTER_SET, "utf-8");                    BitMatrix bitMatrix = new QRCodeWriter().encode(text,                            BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);                            // QRCodeWriter writer = new QRCodeWriter();                    // // 把输入的文本转为二维码                    // BitMatrix bitMatrix = writer.encode(text, BarcodeFormat.QR_CODE,                    // QR_WIDTH, QR_HEIGHT);                            int[] pixels = new int[QR_WIDTH * QR_HEIGHT];                    for (int y = 0; y < QR_HEIGHT; y++) {                        for (int x = 0; x < QR_WIDTH; x++) {                            if (bitMatrix.get(x, y)) {                                pixels[y * QR_WIDTH + x] = 0xff000000;                            } else {                                pixels[y * QR_WIDTH + x] = 0xffffffff;                            }                                }                    }                    bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT,                            Bitmap.Config.ARGB_8888);                    bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);                        } catch (WriterException e) {                    e.printStackTrace();                }                return bitmap;            }                    /**            * 解析QR图内容            *             * @param imageView            * @return            */            private String readImage(ImageView imageView) {                String content = null;                Map<DecodeHintType, String> hints = new HashMap<DecodeHintType, String>();                hints.put(DecodeHintType.CHARACTER_SET, "utf-8");                        // 获得待解析的图片                Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();                RGBLuminanceSource source = new RGBLuminanceSource(bitmap);                BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));                QRCodeReader reader = new QRCodeReader();                try {                    Result result = reader.decode(bitmap1, hints);                    // 得到解析后的文字                    content = result.getText();                } catch (Exception e) {                    e.printStackTrace();                }                return content;            }                }  
</div> </div>

RGBLuminanceSource:

    package com.google.zxing.client.androidtest;                import com.google.zxing.LuminanceSource;                import android.graphics.Bitmap;        import android.graphics.BitmapFactory;                import java.io.FileNotFoundException;                /**        * This class is used to help decode images from files which arrive as RGB data        * from Android bitmaps. It does not support cropping or rotation.        *         * @author dswitkin@google.com (Daniel Switkin)        */        public final class RGBLuminanceSource extends LuminanceSource {                    private final byte[] luminances;                    public RGBLuminanceSource(String path) throws FileNotFoundException {                this(loadBitmap(path));            }                    public RGBLuminanceSource(Bitmap bitmap) {                super(bitmap.getWidth(), bitmap.getHeight());                        int width = bitmap.getWidth();                int height = bitmap.getHeight();                int[] pixels = new int[width * height];                bitmap.getPixels(pixels, 0, width, 0, 0, width, height);                        // In order to measure pure decoding speed, we convert the entire image                // to a greyscale array                // up front, which is the same as the Y channel of the                // YUVLuminanceSource in the real app.                luminances = new byte[width * height];                for (int y = 0; y < height; y++) {                    int offset = y * width;                    for (int x = 0; x < width; x++) {                        int pixel = pixels[offset + x];                        int r = (pixel >> 16) & 0xff;                        int g = (pixel >> 8) & 0xff;                        int b = pixel & 0xff;                        if (r == g && g == b) {                            // Image is already greyscale, so pick any channel.                            luminances[offset + x] = (byte) r;                        } else {                            // Calculate luminance cheaply, favoring green.                            luminances[offset + x] = (byte) ((r + g + g + b) >> 2);                        }                    }                }            }                    @Override            public byte[] getRow(int y, byte[] row) {                if (y < 0 || y >= getHeight()) {                    throw new IllegalArgumentException(                            "Requested row is outside the image: " + y);                }                int width = getWidth();                if (row == null || row.length < width) {                    row = new byte[width];                }                        System.arraycopy(luminances, y * width, row, 0, width);                return row;            }                    // Since this class does not support cropping, the underlying byte array            // already contains            // exactly what the caller is asking for, so give it to them without a copy.            @Override            public byte[] getMatrix() {                return luminances;            }                    private static Bitmap loadBitmap(String path) throws FileNotFoundException {                Bitmap bitmap = BitmapFactory.decodeFile(path);                if (bitmap == null) {                    throw new FileNotFoundException("Couldn't open " + path);                }                return bitmap;            }                }  
</div> </div>

main.xml:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:gravity="center_horizontal"            android:orientation="vertical" >                    <EditText                android:id="@+id/main_et"                android:layout_width="match_parent"                android:layout_height="wrap_content" />                    <Button                android:id="@+id/main_btn_generateQRCode"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:text="使用文本生成二维码" />                    <Button                android:id="@+id/main_btn_decodeQRCode"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:text="解析二维码内容" />                    <ImageView                android:id="@+id/main_iv"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />                    <TextView                android:id="@+id/main_tv"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_marginTop="20dp"                android:gravity="center_horizontal"                android:textSize="20sp" />                </LinearLayout>  
</div> </div> 另外需要在二维码的jar: zxing-2.0-core.jar.zip