Android 养成记-1.4 二维码生成+添加logo+识别+扫码

先看图说话:

1.二维码生成:

 public void generateQRcode() throws FileNotFoundException {

        String mLink = text.getText().toString();
        if (mLink.length()==0)
        {
            mLink=text.getHint().toString();
        }
        Log.v("MainActivity","mLink:" + mLink);
        //generateCode(mLink);
//生成图片二维码
        boolean success = false;
        success = createQRImage(mLink, qrImgImageView);
        if (success) {
            isQrImgShow = true;
            Toast.makeText(getBaseContext(), "二维码成功生成,请长按识别", Toast.LENGTH_SHORT).show();
        }
        //设置图片长按识别
        readImagePicture(qrImgImageView);
    }


    /*
     * 生成二维码
     */
    //要转换的地址或字符串,可以是中文
    public boolean createQRImage(String url, final ImageView qrImgImageView) throws FileNotFoundException {
        int QR_WIDTH = 300;
        int QR_HEIGHT = 300;
        try {
            //判断URL合法性
            if (url == null || "".equals(url) || url.length() < 1) {
                return false;
            }
            Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            //图像数据转换,使用了矩阵转换
            BitMatrix bitMatrix = new QRCodeWriter().encode(url, BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
            int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
            //下面这里按照二维码的算法,逐个生成二维码的图片,
            //两个for循环是图片横列扫描的结果
            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;
                    }
                }
            }
            //生成二维码图片的格式,使用ARGB_8888
            Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);
            if (checkBox.isChecked()) {
                //获取要设置的logo的bitmap
                ImageView imageView_logo = new ImageView(this);
                imageView_logo.setImageResource(R.drawable.ic_launcher);

                Bitmap obmp = ((BitmapDrawable) (imageView_logo).getDrawable()).getBitmap();
                int width = obmp.getWidth();
                int height = obmp.getHeight();
                int[] data = new int[width * height];
                obmp.getPixels(data, 0, width, 0, 0, width, height);
                if (obmp != null) {
                    bitmap = addLogo(bitmap, obmp);
                }
            }
            boolean b_need_save_first = false;
            if (!b_need_save_first) {
                qrImgImageView.setImageBitmap(bitmap);

            } else {
                if (bitmap != null) {
                    //必须使用compress方法将bitmap保存到文件中再进行读取。直接返回的bitmap是没有任何压缩的,内存消耗巨大!
                    final String filePath = getFileRoot(getBaseContext()) + File.separator
                            + "qr_" + System.currentTimeMillis() + ".jpg";
                    final boolean success = bitmap.compress(Bitmap.CompressFormat.JPEG, 30, new FileOutputStream(filePath));
                    //二维码图片较大时,生成图片、保存文件的时间可能较长,因此放在新线程中
                    new Thread(new Runnable() {
                        @Override
                        public void run() {

                            if (success) {
                                //显示到一个ImageView上面
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        qrImgImageView.setImageBitmap(BitmapFactory.decodeFile(filePath));
                                    }
                                });
                            }
                        }
                    }).start();
                }
            }
            return true;

        } catch (WriterException e) {
            e.printStackTrace();
        }
        return false;
    }
    //文件存储根目录
    private String getFileRoot(Context context) {
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            File external = context.getExternalFilesDir(null);
            if (external != null) {
                return external.getAbsolutePath();
            }
        }

        return context.getFilesDir().getAbsolutePath();
    }

2.生成的二维码中间添加logo

(这个添加了logo的二维码只有超链接可以识别)

 /**
     * 在二维码中间添加Logo图案
     */
    @SuppressWarnings("deprecation")
    private static Bitmap addLogo(Bitmap src, Bitmap logo) {
        if (src == null) {
            return null;
        }

        if (logo == null) {
            return src;
        }

        //获取图片的宽高
        int srcWidth = src.getWidth();
        int srcHeight = src.getHeight();
        int logoWidth = logo.getWidth();
        int logoHeight = logo.getHeight();

        if (srcWidth == 0 || srcHeight == 0) {
            return null;
        }

        if (logoWidth == 0 || logoHeight == 0) {
            return src;
        }

        //logo大小为二维码整体大小的1/5
        float scaleFactor = srcWidth * 1.0f / 5 / logoWidth;
        Bitmap bitmap = Bitmap.createBitmap(srcWidth, srcHeight, Bitmap.Config.ARGB_8888);
        try {
            Canvas canvas = new Canvas(bitmap);
            canvas.drawBitmap(src, 0, 0, null);
            canvas.scale(scaleFactor, scaleFactor, srcWidth / 2, srcHeight / 2);
            canvas.drawBitmap(logo, (srcWidth - logoWidth) / 2, (srcHeight - logoHeight) / 2, null);

            canvas.save(Canvas.ALL_SAVE_FLAG);
            canvas.restore();
        } catch (Exception e) {
            bitmap = null;
            e.getStackTrace();
        }

        return bitmap;
    }

3.是否添加logo通过一个checkbox 来获取状态,并在生成的过程中判断这个checkbox状态

 @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (buttonView == checkBox) {   //自动登陆选框发生改变时
            if (isChecked) {
                checkBox.setChecked(true);
            }
        }
    }
 if (checkBox.isChecked()) {
                //获取要设置的logo的bitmap
                ImageView imageView_logo = new ImageView(this);
                imageView_logo.setImageResource(R.drawable.ic_launcher);

                Bitmap obmp = ((BitmapDrawable) (imageView_logo).getDrawable()).getBitmap();
                int width = obmp.getWidth();
                int height = obmp.getHeight();
                int[] data = new int[width * height];
                obmp.getPixels(data, 0, width, 0, 0, width, height);
                if (obmp != null) {
                    bitmap = addLogo(bitmap, obmp);
                }
            }
扫描二维码关注公众号,回复: 4023231 查看本文章

4.长按二维码图片选择识别或者保存到手机相册:

 /*
     * 长按图片解析二维码
     */
    private void readImagePicture(final ImageView imageView) {
        // TODO Auto-generated method stub
        //长按,通过zxing读取图片,判断是否有二维码
        imageView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View viewm) {
                Bitmap obmp = ((BitmapDrawable) (imageView).getDrawable()).getBitmap();
                recogQRcode(obmp);
                return false;
            }
        });
    }

    //识别二维码的函数
    public void recogQRcode(Bitmap obmp){

        int width = obmp.getWidth();
        int height = obmp.getHeight();
        int[] data = new int[width * height];
        obmp.getPixels(data, 0, width, 0, 0, width, height);
        RGBLuminanceSource source = new RGBLuminanceSource(width, height, data);
        BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
        QRCodeReader reader = new QRCodeReader();
        Result re = null;
        try {
            re = reader.decode(bitmap1);
        } catch (NotFoundException e) {
            e.printStackTrace();
        } catch (ChecksumException e) {
            e.printStackTrace();
        } catch (FormatException e) {
            e.printStackTrace();
        }

        if (re == null) {
            showAlert(obmp);
        } else {
            showSelectAlert(obmp, re);
        }

    }
    private void showAlert(final Bitmap bitmap) {
        Toast.makeText(MainActivity.this,"添加了logo,无法识别",Toast.LENGTH_SHORT).show();
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("保存图片")
                .setCancelable(false);

        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterfacem, int i) {
                saveImageToGallery(bitmap);
            }
        })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterfacem, int i) {
                    }
                });
        builder.show();
    }

    protected void saveImageToGallery(Bitmap bitmap) {
        // 首先保存图片
        String path = Environment.getExternalStorageDirectory()+"/QRcodeImage/";
        File fileDir;
        /**
         * 文件目录如果不存在,则创建
         */
        fileDir = new File(path);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
       String bitName = System.currentTimeMillis()+".JPG";
        String filePath =Environment.getExternalStorageDirectory().getPath()+"/DCIM/Camera/"+ bitName;
        Log.e(Debug.filename(new Exception()), Debug.funAndLine(new Exception())+filePath);
        File file=new File(filePath);
        if(file.exists()){
            file.delete();
        }
        FileOutputStream out;
        try{
            out = new FileOutputStream(file);
            // 格式为 JPEG,照相机拍出的图片为JPEG格式的,PNG格式的不能显示在相册中
            if(bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out))
            {
                out.flush();
                out.close();
// 插入图库
                MediaStore.Images.Media.insertImage(this.getContentResolver(), file.getAbsolutePath(), bitName, null);

            }
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();

        }
        // 发送广播,通知刷新图库的显示
        this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + filePath)));

        Toast.makeText(getBaseContext(), "图片保存成功", Toast.LENGTH_SHORT).show();
        System.out.println("图片保存成功");

    }

    private void showSelectAlert(final Bitmap bitmap,final Result re) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("请选择");
        String str[] = {"保存图片", "识别二维码"};
        builder.setItems(str, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterfacem, int i) {
                switch (i) {
                    case 0: {
                        saveImageToGallery(bitmap);
                    }
                    break;
                    case 1: {
                        //Toast出内容
                        Toast.makeText(MainActivity.this,re.getText(),Toast.LENGTH_SHORT).show();
                        scanResult.setText("识别结果:"+re);
                        //利用正则表达式判断内容是否是URL,是的话则打开网页
                        String regex = "(((https|http)?://)?([a-z0-9]+[.])|(www.))"
                                + "\\w+[.|\\/]([a-z0-9]{0,})?[[.]([a-z0-9]{0,})]+((/[\\S&&[^,;\u4E00-\u9FA5]]+)+)?([.][a-z0-9]{0,}+|/?)";//设置正则表达式

                        Pattern pat = Pattern.compile(regex.trim());//比对
                        Matcher mat = pat.matcher(re.getText().trim());
                        if (mat.matches()){
                            Uri uri = Uri.parse(re.getText());
                            Intent intent = new Intent(Intent.ACTION_VIEW, uri);//打开浏览器
                            startActivity(intent);
                        }
                    }
                    break;
                }
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterfacem, int i) {

            }
        });
        builder.show();
    }

生成的效果图:

5.扫描二维码:

这部分采用了第三方的识别库:https://blog.csdn.net/ky1996/article/details/79502358

我是添加到了自己的工程中。上面说的方法很好,这里就不贴了,只说下要注意的地方:

1) 在manifest 添加权限:

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <!--获取sd卡写的权限,用于文件上传和下载-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--允许读取手机状态 用于创建BmobInstallation-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera"/>
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.FLASHLIGHT" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

2) 在main Activity中获取权限:

 /**
         * 动态获取权限,Android 6.0 新特性,一些保护权限,除了要在AndroidManifest中声明权限,还要使用如下代码动态获取
         */
        if (Build.VERSION.SDK_INT >= 23) {
            int REQUEST_CODE_CONTACT = 101;
            String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.CAMERA,
                    Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS,
                    Manifest.permission.VIBRATE
                    };
            //验证是否许可权限
            for (String str : permissions) {
                if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
                    //申请权限
                    this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
                    return;
                }
            }
        }

下面是效果图:

从相册获取的gif图

下面是整个demo的下载链接https://download.csdn.net/download/linzihahaha/10777476

猜你喜欢

转载自blog.csdn.net/linzihahaha/article/details/83956685