Android 扫描相册中的二维码

关于生成扫描二维码的操作可使用GitHub的开源库ZXing:https://github.com/zxing/zxing

我在项目中使用了Zxing的精简库https://github.com/azhong1011/libzxing

将libzxing作为module导入项目

一、生成二维码(可添加logo)

 Bitmap logo = BitmapFactory.decodeResource(getResources(), R.drawable.azhong);
                /**
                 * 第一个参数:需要转换成二维码的内容
                 * 第二个参数:二维码的宽度
                 * 第三个参数:二维码的高度
                 * 第四个参数:Logo图片
                 */
 Bitmap bitmap = EncodingUtils.createQRCode("test", 500, 500, logo);

二、生成的二维码长按保存相册

ig_qrcode.setImageBitmap(bitmap);
ig_qrcode.setOnLongClickListener(new View.OnLongClickListener() {
                                             @Override
                                             public boolean onLongClick(View v) {
                                                 String[] items = new String[]{"保存图片"};
                                                 AlertDialog.Builder builder = new AlertDialog.Builder(ActivityQRCode.this);
                                                 builder.setItems(items, new DialogInterface.OnClickListener() {
                                                     @Override
                                                     public void onClick(DialogInterface dialog, int which) {
                                                         saveImageToGallery(context,bitmap);

                                                     }
                                                 });
                                                 builder.show();
                                                 return true;
                                                 }
                                         });
 /**
     * 将二维码图片保存到文件夹
     *
     *
     * @param context
     * @param bmp
     */
    public static void saveImageToGallery(Context context, Bitmap bmp) {
        // 首先保存图片
        String externalStorageState = Environment.getExternalStorageState();
        //判断sd卡是否挂载
        if (externalStorageState.equals(Environment.MEDIA_MOUNTED)) {
        /*外部存储可用,则保存到外部存储*/
            //创建一个文件夹
            File appDir = new File(Environment.getExternalStorageDirectory(), "二维码");
            //如果文件夹不存在
            if (!appDir.exists()) {
                //则创建这个文件夹
                appDir.mkdir();
            }
            //将bitmap保存
            save(context, bmp, appDir,parklot);
        } else {
            //外部不可用,将图片保存到内部存储中,获取内部存储文件目录
            File filesDir = context.getFilesDir();
            //保存
            save(context, bmp, filesDir,imageName);
        }
    }
    private static void save(Context context, Bitmap bmp, File appDir ,String name) {
        //命名文件名称
        String fileName = name + "_" + new Date().getTime() + ".jpg";
        //创建图片文件,传入文件夹和文件名
        File imagePath = new File(appDir, fileName);
        try {
            //创建文件输出流,传入图片文件,用于输入bitmap
            FileOutputStream fos = new FileOutputStream(imagePath);
            //将bitmap压缩成png,并保存到相应的文件夹中
            bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
            //冲刷流
            fos.flush();
            //关闭流
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 其次把文件插入到系统图库
        try {
            MediaStore.Images.Media.insertImage(context.getContentResolver(),
                    imagePath.getAbsolutePath(), fileName, null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 最后通知图库更新
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + imagePath.getAbsolutePath())));
    }

三、扫描二维码

//需要以带返回结果的方式启动扫描界面
  Intent intent = new Intent(oneActivity.this, CaptureActivity.class);
  startActivityForResult(intent, 0);

//重写onActivityResult方法
 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 0){
            if (resultCode == RESULT_OK) {
                Bundle bundle = data.getExtras();
                //获取扫描结果
                String result = bundle.getString("result");
                tv_result.setText(result);
            }
        }
    }

四、扫描在相册中的二维码

1、在libzxing中layout activity_capture.xml中添加TextView“相册” tv_openpic

2、在CaptureActivity中为tv_openpic增加监听事件:

        tv_openpic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent innerIntent = new Intent(); // "android.intent.action.GET_CONTENT"
                if (Build.VERSION.SDK_INT < 19) {
                    innerIntent.setAction(Intent.ACTION_GET_CONTENT);
                } else {
                  // innerIntent.setAction(Intent.ACTION_OPEN_DOCUMENT);
                    innerIntent.setAction(Intent.ACTION_PICK);
                }

                innerIntent.setType("image/*");

                Intent wrapperIntent = Intent.createChooser(innerIntent, "选择二维码图片");

                CaptureActivity.this
                        .startActivityForResult(wrapperIntent, 0);
            }
        });

重写onActivityResult方法:

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {

            switch (requestCode) {

                case 0:
                    String[] proj = { MediaStore.Images.Media.DATA };

                    // 获取选中图片的路径
                    Cursor cursor = getContentResolver().query(data.getData(),
                            proj, null, null, null);

                    if (cursor != null) {
                        cursor.moveToFirst();
                        int column_index = cursor
                                .getColumnIndexOrThrow(proj[0]);
                        photo_path = cursor.getString(column_index);

                    }

                    cursor.close();

                    new Thread(new Runnable() {

                        @Override
                        public void run() {

                            Result result = scanningImage(photo_path);
                            // String result = decode(photo_path);
                            if (result == null) {
                                Looper.prepare();
                                Toast.makeText(getApplicationContext(), "图片格式有误",Toast.LENGTH_SHORT).show();
                                Looper.loop();
                            } else {
                                // 数据返回
                                inactivityTimer.onActivity();
                                beepManager.playBeepSoundAndVibrate();
                                String recode = recode(result.toString());
                                Intent resultIntent = new Intent();
                                resultIntent.putExtra("result", recode);
                                setResult(RESULT_OK, resultIntent);
                                finish();
                            }
                        }
                    }).start();
                    break;

            }

        }
    }
    protected Result scanningImage(String path) {
        if (TextUtils.isEmpty(path)) {

            return null;

        }
        // DecodeHintType 和EncodeHintType
        Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
        hints.put(DecodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码内容的编码
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; // 先获取原大小
        scanBitmap = BitmapFactory.decodeFile(path, options);
        options.inJustDecodeBounds = false; // 获取新的大小

        int sampleSize = (int) (options.outHeight / (float) 200);

        if (sampleSize <= 0)
            sampleSize = 1;
        options.inSampleSize = sampleSize;
        scanBitmap = BitmapFactory.decodeFile(path, options);
        int[] data = new int[scanBitmap.getWidth() * scanBitmap.getHeight()];
        scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());
        RGBLuminanceSource source = new RGBLuminanceSource(scanBitmap.getWidth(),scanBitmap.getHeight(),data);
        BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
        QRCodeReader reader = new QRCodeReader();
        try {

            return reader.decode(bitmap1, hints);

        } catch (NotFoundException e) {

            e.printStackTrace();

        } catch (ChecksumException e) {

            e.printStackTrace();

        } catch (FormatException e) {

            e.printStackTrace();

        }

        return null;

    }

    private String recode(String str) {
        String formart = "";

        try {
            boolean ISO = Charset.forName("ISO-8859-1").newEncoder()
                    .canEncode(str);
            if (ISO) {
                formart = new String(str.getBytes("ISO-8859-1"), "GB2312");
                Log.i("1234      ISO8859-1", formart);
            } else {
                formart = str;
                Log.i("1234      stringExtra", str);
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return formart;
    }

五、二维码效果

在libzing中EncodingUtils类中可以看出生成二维码方法是

BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix,
                    heightPix, hints);

encode方法:

public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map<EncodeHintType, ?> hints)

EncodeHintType为二维码的一些设置:

public enum EncodeHintType {
    ERROR_CORRECTION,
    CHARACTER_SET,
    DATA_MATRIX_SHAPE,
    MIN_SIZE,
    MAX_SIZE,
    MARGIN,
    PDF417_COMPACT,
    PDF417_COMPACTION,
    PDF417_DIMENSIONS,
    AZTEC_LAYERS;

    private EncodeHintType() {
    }
}

其中ERROR_CORRECTION为容错级别

CHARACTER_SET为字符转码格式

MARGIN为二维码空白边框大小

可以如下配置参数

// 配置参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 容错级别
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.MARGIN,1);

参考:https://blog.csdn.net/a_zhon/article/details/52551554

           https://blog.csdn.net/qiuqi12/article/details/72270969

           https://blog.csdn.net/cdhahaha/article/details/64439558

           https://blog.csdn.net/chen52671/article/details/46981137

           https://www.jianshu.com/p/b275e818de6a

猜你喜欢

转载自blog.csdn.net/sinat_33969299/article/details/81114254
今日推荐