美文网首页
Android二维码扫描.(生成,扫描,相册,闪光灯)

Android二维码扫描.(生成,扫描,相册,闪光灯)

作者: 鹅鹅鹅曲项向天歌呀 | 来源:发表于2018-08-28 15:05 被阅读0次

    项目用到了二维码的相关功能,作为菜鸟我,自己写,不可能存在的,无奈,只好去百度,找找有没有好用的第三方的,拿来用一用,实现实现功能呗。
    地址一:https://github.com/bingoogolapple/BGAQRCode-Android
       这个大家一百度就能百度的到,我也用项目了,但是测试的过程中,发现bug了,长时间扫描不出来,会出来一串随机数字,github上众多用户都在说这个问题,作者好像并没有解决这个问题。除了扫描结果有点不尽人意之外,其他都挺好用的。如果真的想用,那就判断下结果吧,如果是纯数字,那就重新扫描,但是如果你的二维码是纯数字生成的,那就完蛋咯,只能换个库了。
    地址二:https://github.com/mylhyl/Android-Zxing 
       这个我写了demo,试了试,扫描和相册是可以的.
    地址三:https://github.com/journeyapps/zxing-android-embedded
       我用的这个,下载下来,界面不是很美观,还有点晕乎乎的,但是仔细看,仔细找,你会发现,扫描速度堪比微信啊,贼快贼快的,不过只有扫描和闪光灯功能,相册识别和生成的功能,自己加上吧。
    地址四:https://www.imooc.com/article/20971
       嘿嘿,根据这链接来做的。这个链接是根据"地址三"来自定义布局的做出来的.(我也是在这个链接里看到“地址二”的,[皱眉][皱眉])

    大家先看看地址三和四,然后直接复制下面的代码,可以实现功能[吼吼][吼吼]
    -------------------------------------上图上代码-------------------------------------
    图:
    扫描.gif
    相册.gif
    代码:

    build.gradle:

     implementation('com.journeyapps:zxing-android-embedded:3.6.0') { transitive = false }
     implementation 'com.google.zxing:core:3.3.0'
    

    上面是github提供的,但是我没把 zxing:core 下载下来,我老大下载的jar包,放进项目里的,只要能编译过去,咋的都行,管他哪儿来的嘛.还有,关于相册识别二维码,这个是个耗时操作,需要在子线程,我们的项目使用rxjava来转换线程的,需要依赖的哦implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'io.reactivex.rxjava2:rxjava:2.1.5',用异步任务也可以,但是注意下,内存泄露.

    HomeFragment
    ps:这里是入口,对相机是否可以使用进行了判断,百度来的,[羞羞].因为我们的targetSdkVersion=22.直接在清单文件设置权限就好了,但是要是手动关闭了相机权限,还是能进去二维码界面的,只是相机不能使用,一片黢黑黢黑的.

     @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.home_scan:
                    if (!cameraIsCanUse()) {
                        toastShort("请开启相机权限");
                    } else {
                        startActivity(new Intent(getActivity(), QRCodeActivity.class));
                    }
                    break;
      }
          public boolean cameraIsCanUse() {//百度判断相机的
            boolean isCanUse = true;
            Camera mCamera = null;
            try {
                mCamera = Camera.open();
                Camera.Parameters mParameters = mCamera.getParameters(); //针对魅族手机
                mCamera.setParameters(mParameters);
            } catch (Exception e) {
                isCanUse = false;
            }
    
            if (mCamera != null) {
                try {
                    mCamera.release();
                } catch (Exception e) {
                    e.printStackTrace();
                    return isCanUse;
                }
            }
            return isCanUse;
        }
    
    

    QRCodeActivity.Java
    ps:二维码界面,这里是二维码的主界面.照葫芦,画瓢,写写呗.

    二维码界面图.jpg
    public class QRCodeActivity extends BaseToolbarActivity {
        private DecoratedBarcodeView barcodeView;
        private boolean isLight = false;
    
        @NonNull
        @Override
        protected int getLayoutId() {
            return R.layout.activity_qrcode;
        }
    
        @Override
        protected void initIntentData(Intent intent) {
    
        }
    
        @Override
        protected void initViews() {
            setTitleWithBack("扫一扫");
            barcodeView = findViewById(R.id.barcode_scanner);
            Collection<BarcodeFormat> formats = Arrays.asList(BarcodeFormat.QR_CODE, BarcodeFormat.CODE_39);
            barcodeView.getBarcodeView().setDecoderFactory(new DefaultDecoderFactory(formats));
            barcodeView.decodeContinuous(callback);
            addOnClickListeners(R.id.tv_zxing_gallery, R.id.tv_zxing_flashlight);
        }
    
        @Override
        public void onClick(View v) {
            super.onClick(v);
            switch (v.getId()) {
                case R.id.tv_zxing_gallery:
                    EasyPhotos.createAlbum(this, true, GlideEngine.getInstance())
                            .setFileProviderAuthority(Constants.fileProvider)
                            .setCount(1)
                            .start(Constants.PIC);
                    break;
                case R.id.tv_zxing_flashlight:
                    if (!isLight) {
                        barcodeView.setTorchOn();
                        isLight = true;
                    } else {
                        isLight = false;
                        barcodeView.setTorchOff();
                        break;
                    }
            }
        }
    
        private BarcodeCallback callback = new BarcodeCallback() {
            @Override
            public void barcodeResult(BarcodeResult result) {
                if (result.getText() == null) {
                    // Prevent duplicate scans
                    return;
                }
                barcodeView.setStatusText(result.getText());
                parseQRCode(result.getText(), new Bundle());
            }
    
            @Override
            public void possibleResultPoints(List<ResultPoint> resultPoints) {
            }
        };
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                    case Constants.PIC:
                        if (data != null) {
                            showProgressDialog();
                            List<String> pathList = data.getStringArrayListExtra(EasyPhotos.RESULT_PATHS);
                            final String picturePath = pathList.get(0).toString();
                            barcodeView.pause();
                            Observable.create(new ObservableOnSubscribe<Result>() {
                                @Override
                                public void subscribe(ObservableEmitter<Result> e) throws Exception {
                                    Result result = PicUtils.scanningImage(picturePath);
                                    e.onNext(result);
                                }
                            }).subscribeOn(Schedulers.io())
                                    .observeOn(AndroidSchedulers.mainThread())
                                    .compose(this.<Result>bindToLifecycle())
                                    .subscribe(new Observer<Result>() {
                                        @Override
                                        public void onSubscribe(Disposable d) {
    
                                        }
    
                                        @Override
                                        public void onNext(Result result) {
                                            onComplete();
                                            parseQRCode(result.getText(), new Bundle());
                                        }
    
                                        @Override
                                        public void onError(Throwable e) {
                                            barcodeView.resume();
                                            onComplete();
                                            ToastUtils.showToast("照片中未识别到二维码");
                                        }
    
                                        @Override
                                        public void onComplete() {
                                            hideProgressDialog();
                                        }
                                    });
                        } else {
                            ToastUtils.showToast("获取图片失败");
                        }
                        break;
                }
            }
    
        }
    
        //解析二维码中的字符串
        private void parseQRCode(String result, Bundle bundle) {
            LogUtils.e("result is =========" + result);
            hideProgressDialog();
            if (TextUtils.isEmpty(result)) {
                ToastUtils.showToast("照片中未识别到二维码");
                return;
            }
            if (NetWorkUtil.isNetWorkUrl(result)) {
                startActivity(new Intent(this, WebViewActivity.class).putExtra("url", result));
                finish();
                return;
            } else {
                bundle.putString("result", result);
                startActivity(new Intent(this, ResultActivity.class).putExtras(bundle));
            }
    
        }
    
    
    
        @Override
        protected void getNetWorkData() {
    
        }
    
        @Override
        public Object newPresenter() {
            return null;
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            barcodeView.resume();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            barcodeView.pause();
        }
    
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            return barcodeView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
        }
    

    activity_qrcode.xml
    ps:主界面的布局,直接复制就好

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
       >
    
        <com.journeyapps.barcodescanner.DecoratedBarcodeView
            android:id="@+id/barcode_scanner"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:zxing_scanner_layout="@layout/scaner">
    
        </com.journeyapps.barcodescanner.DecoratedBarcodeView>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal"
            android:paddingBottom="@dimen/dpValue35">
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />
    
            <TextView
                android:id="@+id/tv_zxing_gallery"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawablePadding="@dimen/dpValue12"
                android:drawableTop="@drawable/zxing_gallery"
                android:gravity="center"
                android:paddingLeft="@dimen/dpValue10"
                android:paddingRight="@dimen/dpValue10"
                android:text="相册"
                android:textColor="@color/white"
                android:textSize="@dimen/textSizeValue12" />
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="2" />
    
            <TextView
                android:id="@+id/tv_zxing_flashlight"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawablePadding="@dimen/dpValue12"
                android:drawableTop="@drawable/zxing_flashlight"
                android:gravity="center"
                android:paddingLeft="@dimen/dpValue10"
                android:paddingRight="@dimen/dpValue10"
                android:text="手电筒"
                android:textColor="@color/white"
                android:textSize="@dimen/textSizeValue12" />
    
    
            <View
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="1" />
        </LinearLayout>
    
    </RelativeLayout>
    

    scaner.xml
    ps:不要改这里控件的id,重写的第三方控件,改了就找不到了,直接复制就好.

    <?xml version="1.0" encoding="utf-8"?>
    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    
        <com.journeyapps.barcodescanner.BarcodeView
            android:id="@+id/zxing_barcode_surface"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:zxing_framing_rect_height="258dp"
            app:zxing_framing_rect_width="258dp" />
    
        <com.yangsu.chaodao.view.ZxingViewFinderView
            android:id="@+id/zxing_viewfinder_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:scannerBoundColor="@color/white"
            app:scannerBoundCornerHeight="24dp"
            app:scannerBoundCornerWith="1.5dp"
            app:scannerBoundWidth="0.5dp"
            app:scannerLaserResId="@drawable/scan_icon_scanline"
            app:scannerTipText="将二维码图片放到取景框内即可自动扫描"
            app:scannerTipTextColor="@color/white"
            app:scannerTipTextGravity="false"
            app:scannerTipTextMargin="43dp"
            app:scannerTipTextSize="14sp"
            app:zxing_possible_result_points="@color/zxing_custom_possible_result_points"
            app:zxing_result_view="@color/zxing_custom_result_view"
            app:zxing_viewfinder_laser="@color/zxing_custom_viewfinder_laser"
            app:zxing_viewfinder_mask="@color/zxing_custom_viewfinder_mask" />
    </merge>
    
    

    ZxingViewFinderView.Java
    ps:这个是自定义的自定义的扫描框,复制粘贴即可,copy地址四的.

    public class ZxingViewFinderView extends ViewfinderView {
        private int scannerBoundColor;
        private float scannerBoundWidth; // viewfinder width
        private int scannerBoundCornerColor; // viewfinder corner color
        private float scannerBoundCornerWidth; // viewfinder corner width
        private float scannerBoundCornerHeight; // viewfinder corner height
        private int scannerLaserResId; // laser resource
        private String scannerTipText; // tip text
        private float scannerTipTextSize; // tip text size
        private int scannerTipTextColor; // tip text color
        private float scannerTipTextMargin; // tip text margin between viewfinder
        private boolean tipTextGravityBottom; // tip text gravity
        private Bitmap scannerLaserBitmap; // laser bitmap
        private int scannerLaserTop; // laser top position
        private final static int LASER_MOVE_DISTANCE_PER_UNIT_TIME = 10;
        private int LASER_MOVE_DIRECTION = 1;
    
        public ZxingViewFinderView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            Resources resources = getResources(); // Get attributes on view
            TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.ZxingViewFinderView);
            scannerBoundColor = attributes.getColor(R.styleable.ZxingViewFinderView_scannerBoundColor, resources.getColor(R.color.white));
            scannerBoundWidth = attributes.getDimension(R.styleable.ZxingViewFinderView_scannerBoundWidth, 0.5f);
            scannerBoundCornerColor = attributes.getColor(R.styleable.ZxingViewFinderView_scannerBoundCornerColor, resources.getColor(R.color.color_blue));
            scannerBoundCornerWidth = attributes.getDimension(R.styleable.ZxingViewFinderView_scannerBoundCornerWith, 1.5f);
            scannerBoundCornerHeight = attributes.getDimension(R.styleable.ZxingViewFinderView_scannerBoundCornerHeight, 24f);
            scannerLaserResId = attributes.getResourceId(R.styleable.ZxingViewFinderView_scannerLaserResId, 0);
            scannerTipText = attributes.getString(R.styleable.ZxingViewFinderView_scannerTipText);
            scannerTipTextSize = attributes.getDimension(R.styleable.ZxingViewFinderView_scannerTipTextSize, 14f);
            scannerTipTextColor = attributes.getColor(R.styleable.ZxingViewFinderView_scannerTipTextColor, resources.getColor(R.color.white));
            scannerTipTextMargin = attributes.getDimension(R.styleable.ZxingViewFinderView_scannerTipTextMargin, 40f);
            tipTextGravityBottom = attributes.getBoolean(R.styleable.ZxingViewFinderView_scannerTipTextGravity, true);
            attributes.recycle();
        }
    
        @Override
        public void onDraw(Canvas canvas) {
            refreshSizes();
            if (framingRect == null || previewFramingRect == null) {
                return;
            }
            Rect frame = framingRect;
            Rect previewFrame = previewFramingRect;
            int width = canvas.getWidth();
            int height = canvas.getHeight(); // Draw the exterior
            drawExteriorDarkened(canvas, frame, width, height);
            if (resultBitmap != null) { // Draw the opaque result bitmap over the scanning rectangle
                paint.setAlpha(CURRENT_POINT_OPACITY);
                canvas.drawBitmap(resultBitmap, null, frame, paint);
            } else {
                drawFrameBound(canvas, frame);
                drawFrameCorner(canvas, frame);
                drawLaserLine(canvas, frame);
                drawTipText(canvas, frame, width);
                drawResultPoint(canvas, frame, previewFrame); // Request another update at the animation interval,
                // but only repaint the laser line, // not the entire viewfinder mask.
                postInvalidateDelayed(ANIMATION_DELAY, frame.left - POINT_SIZE, frame.top - POINT_SIZE, frame.right + POINT_SIZE, frame.bottom + POINT_SIZE);
            }
        }
    
        /**
         * Draw a "laser scanner" line to show decoding is active
         */
        private void drawLaserLine(Canvas canvas, Rect frame) {
            if (scannerLaserResId == 0) {
                paint.setColor(laserColor);
                paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
                scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
                int middle = frame.height() / 2 + frame.top;
                canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint);
            } else {
                if (scannerLaserBitmap == null) {
                    scannerLaserBitmap = BitmapFactory.decodeResource(getResources(), scannerLaserResId);
                }
                if (scannerLaserBitmap != null) {
                    int LaserHeight = scannerLaserBitmap.getHeight();
                    if (scannerLaserTop < frame.top) {
                        scannerLaserTop = frame.top;
                        LASER_MOVE_DIRECTION = 1;
                    }
                    if (scannerLaserTop > frame.bottom - LaserHeight) {
                        scannerLaserTop = frame.bottom - LaserHeight;
                        LASER_MOVE_DIRECTION = -1;
                    }
                    Rect laserBitmapRect = new Rect(frame.left, scannerLaserTop, frame.right, scannerLaserTop + LaserHeight);
                    canvas.drawBitmap(scannerLaserBitmap, null, laserBitmapRect, paint);
                    scannerLaserTop = scannerLaserTop + LASER_MOVE_DISTANCE_PER_UNIT_TIME * LASER_MOVE_DIRECTION;
                }
            }
        }
    
        /**
         * Draw result points
         */
        private void drawResultPoint(Canvas canvas, Rect frame, Rect previewFrame) {
            float scaleX = frame.width() / (float) previewFrame.width();
            float scaleY = frame.height() / (float) previewFrame.height();
            List<ResultPoint> currentPossible = possibleResultPoints;
            List<ResultPoint> currentLast = lastPossibleResultPoints;
            int frameLeft = frame.left;
            int frameTop = frame.top;
            if (currentPossible.isEmpty()) {
                lastPossibleResultPoints = null;
            } else {
                possibleResultPoints = new ArrayList<>(5);
                lastPossibleResultPoints = currentPossible;
                paint.setAlpha(CURRENT_POINT_OPACITY);
                paint.setColor(resultPointColor);
                for (ResultPoint point : currentPossible) {
                    canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX), frameTop + (int) (point.getY() * scaleY), POINT_SIZE, paint);
                }
            }
            if (currentLast != null) {
                paint.setAlpha(CURRENT_POINT_OPACITY / 2);
                paint.setColor(resultPointColor);
                float radius = POINT_SIZE / 2.0f;
                for (ResultPoint point : currentLast) {
                    canvas.drawCircle(frameLeft + (int) (point.getX() * scaleX), frameTop + (int) (point.getY() * scaleY), radius, paint);
                }
            }
        }
    
        /**
         * Draw tip text
         */
        private void drawTipText(Canvas canvas, Rect frame, int width) {
            if (TextUtils.isEmpty(scannerTipText)) {
                scannerTipText = "提示";
            }
            paint.setColor(scannerTipTextColor);
            paint.setTextSize(scannerTipTextSize);
            float textWidth = paint.measureText(scannerTipText);
            float x = (width - textWidth) / 2; //根据 drawTextGravityBottom 文字在扫描框上方还是下文,默认下方
            float y = tipTextGravityBottom ? frame.bottom + scannerTipTextMargin : frame.top - scannerTipTextMargin;
            canvas.drawText(scannerTipText, x, y, paint);
        }
    
        /**
         * Draw scanner frame bound * Note: draw inside frame
         */
        private void drawFrameBound(Canvas canvas, Rect frame) {
            if (scannerBoundWidth <= 0) {
                return;
            }
            paint.setColor(scannerBoundColor); // top
            canvas.drawRect(frame.left, frame.top, frame.right, frame.top + scannerBoundWidth, paint); // left
            canvas.drawRect(frame.left, frame.top, frame.left + scannerBoundWidth, frame.bottom, paint); // right
            canvas.drawRect(frame.right - scannerBoundWidth, frame.top, frame.right, frame.bottom, paint); // bottom
            canvas.drawRect(frame.left, frame.bottom - scannerBoundWidth, frame.right, frame.bottom, paint);
        }
    
        /**
         * Draw scanner frame corner
         */
        private void drawFrameCorner(Canvas canvas, Rect frame) {
            if (scannerBoundCornerWidth <= 0 || scannerBoundCornerHeight <= 0) {
                return;
            }
            paint.setColor(scannerBoundCornerColor); // left top
            canvas.drawRect(frame.left - scannerBoundCornerWidth, frame.top - scannerBoundCornerWidth, frame.left + scannerBoundCornerHeight, frame.top, paint);
            canvas.drawRect(frame.left - scannerBoundCornerWidth, frame.top - scannerBoundCornerWidth, frame.left, frame.top + scannerBoundCornerHeight, paint); // left bottom
            canvas.drawRect(frame.left - scannerBoundCornerWidth, frame.bottom + scannerBoundCornerWidth - scannerBoundCornerHeight, frame.left, frame.bottom + scannerBoundCornerWidth, paint);
            canvas.drawRect(frame.left - scannerBoundCornerWidth, frame.bottom, frame.left - scannerBoundCornerWidth + scannerBoundCornerHeight, frame.bottom + scannerBoundCornerWidth, paint); // right top
            canvas.drawRect(frame.right + scannerBoundCornerWidth - scannerBoundCornerHeight, frame.top - scannerBoundCornerWidth, frame.right + scannerBoundCornerWidth, frame.top, paint);
            canvas.drawRect(frame.right, frame.top - scannerBoundCornerWidth, frame.right + scannerBoundCornerWidth, frame.top - scannerBoundCornerWidth + scannerBoundCornerHeight, paint); // right bottom
            canvas.drawRect(frame.right + scannerBoundCornerWidth - scannerBoundCornerHeight, frame.bottom, frame.right + scannerBoundCornerWidth, frame.bottom + scannerBoundCornerWidth, paint);
            canvas.drawRect(frame.right, frame.bottom + scannerBoundCornerWidth - scannerBoundCornerHeight, frame.right + scannerBoundCornerWidth, frame.bottom + scannerBoundCornerWidth, paint);
        }
    
        /**
         * Draw the exterior (i.e. outside the framing rect) darkened
         */
        private void drawExteriorDarkened(Canvas canvas, Rect frame, int width, int height) {
            paint.setColor(resultBitmap != null ? resultColor : maskColor); //top
            canvas.drawRect(0, 0, width, frame.top, paint); //left
            canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint); //right
            canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint); //bottom
            canvas.drawRect(0, frame.bottom + 1, width, height, paint);
        }
    }
    
    

    attrs.xml
    ps:这个不用多说了

            <attr name="scannerBoundColor" format="color" />
            <attr name="scannerBoundCornerColor" format="color" />
            <attr name="scannerTipTextColor" format="color" />
            <attr name="scannerBoundWidth" format="dimension" />
            <attr name="scannerBoundCornerWith" format="dimension" />
            <attr name="scannerBoundCornerHeight" format="dimension" />
            <attr name="scannerTipTextSize" format="dimension" />
            <attr name="scannerTipTextMargin" format="dimension" />
    
            <attr name="pstsTabBackground" format="reference" />
            <attr name="scannerLaserResId" format="integer" />
            <attr name="scannerTipText" format="string" />
            <attr name="scannerTipTextGravity" format="boolean" />
        </declare-styleable>
    

    PicUtils.Java
    处理图片,解析二维码图片使用

    public class PicUtils {
        static Uri uritempFile;
    
        public static Uri getUritempFile() {
            return uritempFile;
        }
    
        public static Uri pathToUri(Context context, String path) {
            if (path != null) {
                path = Uri.decode(path);
                ContentResolver cr = context.getContentResolver();
                StringBuffer buff = new StringBuffer();
                buff.append("(")
                        .append(MediaStore.Images.ImageColumns.DATA)
                        .append("=")
                        .append("'" + path + "'")
                        .append(")");
                Cursor cur = cr.query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        new String[]{MediaStore.Images.ImageColumns._ID},
                        buff.toString(), null, null);
                int index = 0;
                for (cur.moveToFirst(); !cur.isAfterLast(); cur
                        .moveToNext()) {
                    index = cur.getColumnIndex(MediaStore.Images.ImageColumns._ID);
                    // set _id value
                    index = cur.getInt(index);
                }
                if (index == 0) {
                    //do nothing
                } else {
                    Uri uri_temp = Uri
                            .parse("content://media/external/images/media/"
                                    + index);
                    return uri_temp;
                }
            }
            return null;
        }
    
    
        /**
         * 裁剪图片
         */
    
        public static void startPhotoZoom2(Activity context, Uri uri, int width, int height) {
            Intent intent = new Intent("com.android.camera.action.CROP");
            intent.setDataAndType(uri, "image/*");
            // crop为true是设置在开启的intent中设置显示的view可以剪裁
            intent.putExtra("crop", "true");
            // aspectX aspectY 是宽高的比例
            intent.putExtra("aspectX", 1);
            intent.putExtra("aspectY", 1);
    
            // outputX,outputY 是剪裁图片的宽高
            if (width != 0 && height != 0) {
                intent.putExtra("outputX", 500);
                intent.putExtra("outputY", 500 * height / width);
            } else {
                intent.putExtra("outputX", 300);
                intent.putExtra("outputY", 300);
            }
    
            //裁剪后的图片Uri路径,uritempFile为Uri类变量
            uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + String.valueOf(System.currentTimeMillis()) + ".jpg");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
            context.startActivityForResult(intent, Constants.ZOOM_IMAGE);
        }
    
    
        /**
         * 扫描图片
         *
         * @param path
         * @return
         */
         public static Result scanningImage(String path) {
            if (TextUtils.isEmpty(path)) {
                return null;
            }
    
            BitmapFactory.Options opt = new BitmapFactory.Options();
            opt.inJustDecodeBounds = true;
            Bitmap bitmap = BitmapFactory.decodeFile(path, opt);
            // 获取到这个图片的原始宽度和高度
            int picWidth = opt.outWidth;
            int picHeight = opt.outHeight;
            // 获取画布中间方框的宽度和高度
            int screenWidth = 1200;
            int screenHeight = 675;
            // isSampleSize是表示对图片的缩放程度,比如值为2图片的宽度和高度都变为以前的1/2
            opt.inSampleSize = 1;
            // 根据屏的大小和图片大小计算出缩放比例
            if (picWidth > picHeight) {
                if (picWidth > screenWidth)
                    opt.inSampleSize = picWidth / screenWidth;
            } else {
                if (picHeight > screenHeight)
                    opt.inSampleSize = picHeight / screenHeight;
            }
            // 生成有像素经过缩放了的bitmap
            opt.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeFile(path, opt);
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            if (bitmap == null) {
                return null;
            }
            return QrUtils.decodeImage(QrUtils.getYUV420sp(width, height, bitmap), width, height);
        }
    
    }
    
    

    QrUtils.Java

    public class QrUtils {
         private static byte[] yuvs;
    
        /**
         * YUV420sp
         *
         * @param inputWidth
         * @param inputHeight
         * @param scaled
         * @return
         */
        public static byte[] getYUV420sp(int inputWidth, int inputHeight, Bitmap scaled) {
            int[] argb = new int[inputWidth * inputHeight];
    
            scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);
    
            /**
             * 需要转换成偶数的像素点,否则编码YUV420的时候有可能导致分配的空间大小不够而溢出。
             */
            int requiredWidth = inputWidth % 2 == 0 ? inputWidth : inputWidth + 1;
            int requiredHeight = inputHeight % 2 == 0 ? inputHeight : inputHeight + 1;
    
            int byteLength = requiredWidth * requiredHeight * 3 / 2;
            if (yuvs == null || yuvs.length < byteLength) {
                yuvs = new byte[byteLength];
            } else {
                Arrays.fill(yuvs, (byte) 0);
            }
    
            encodeYUV420SP(yuvs, argb, inputWidth, inputHeight);
    
            scaled.recycle();
    
            return yuvs;
        }
        /*public static Bitmap decodeSampledBitmapFromFile(String imgPath, int reqWidth, int reqHeight) {
    
            // First decode with inJustDecodeBounds=true to check dimensions
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imgPath, options);
    
            // Calculate inSampleSize
            options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
    
            // Decode bitmap with inSampleSize set
            options.inJustDecodeBounds = false;
            return BitmapFactory.decodeFile(imgPath, options);
        }*/
    
        /**
         * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, reuse the same reader
         * objects from one decode to the next.
         */
        public static Result decodeImage(byte[] data, int width, int height) {
            // 处理
            Result result = null;
            try {
                Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
                hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
                hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
                hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
                PlanarYUVLuminanceSource source =
                        new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);
                /**
                 * HybridBinarizer算法使用了更高级的算法,但使用GlobalHistogramBinarizer识别效率确实比HybridBinarizer要高一些。
                 *
                 * GlobalHistogram算法:(http://kuangjianwei.blog.163.com/blog/static/190088953201361015055110/)
                 *
                 * 二值化的关键就是定义出黑白的界限,我们的图像已经转化为了灰度图像,每个点都是由一个灰度值来表示,就需要定义出一个灰度值,大于这个值就为白(0),低于这个值就为黑(1)。
                 * 在GlobalHistogramBinarizer中,是从图像中均匀取5行(覆盖整个图像高度),每行取中间五分之四作为样本;以灰度值为X轴,每个灰度值的像素个数为Y轴建立一个直方图,
                 * 从直方图中取点数最多的一个灰度值,然后再去给其他的灰度值进行分数计算,按照点数乘以与最多点数灰度值的距离的平方来进行打分,选分数最高的一个灰度值。接下来在这两个灰度值中间选取一个区分界限,
                 * 取的原则是尽量靠近中间并且要点数越少越好。界限有了以后就容易了,与整幅图像的每个点进行比较,如果灰度值比界限小的就是黑,在新的矩阵中将该点置1,其余的就是白,为0。
                 */
    //            BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
                BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
                QRCodeReader reader2 = new QRCodeReader();
                result = reader2.decode(bitmap1, hints);
            } catch (ReaderException e) {
            }
            return result;
        }
    
    
        /**
         * 将bitmap里得到的argb数据转成yuv420sp格式
         * 这个yuv420sp数据就可以直接传给MediaCodec, 通过AvcEncoder间接进行编码
         *
         * @param yuv420sp 用来存放yuv429sp数据
         * @param argb     传入argb数据
         * @param width    bmpWidth
         * @param height   bmpHeight
         */
        private static void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width, int height) {
            // 帧图片的像素大小
            final int frameSize = width * height;
            // Y的index从0开始
            int yIndex = 0;
            // UV的index从frameSize开始
            int uvIndex = frameSize;
            // YUV数据, ARGB数据
            int Y, U, V, a, R, G, B;
            ;
            int argbIndex = 0;
            // ---循环所有像素点,RGB转YUV---
            for (int j = 0; j < height; j++) {
                for (int i = 0; i < width; i++) {
    
                    // a is not used obviously
                    a = (argb[argbIndex] & 0xff000000) >> 24;
                    R = (argb[argbIndex] & 0xff0000) >> 16;
                    G = (argb[argbIndex] & 0xff00) >> 8;
                    B = (argb[argbIndex] & 0xff);
                    argbIndex++;
    
                    // well known RGB to YUV algorithm
                    Y = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
                    U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
                    V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
    
                    Y = Math.max(0, Math.min(Y, 255));
                    U = Math.max(0, Math.min(U, 255));
                    V = Math.max(0, Math.min(V, 255));
    
                    // NV21 has a plane of Y and interleaved planes of VU each
                    // sampled by a factor of 2
                    // meaning for every 4 Y pixels there are 1 V and 1 U. Note the
                    // sampling is every other
                    // pixel AND every other scanline.
                    // ---Y---
                    yuv420sp[yIndex++] = (byte) Y;
                    // ---UV---
                    if ((j % 2 == 0) && (i % 2 == 0)) {
                        yuv420sp[uvIndex++] = (byte) V;
                        yuv420sp[uvIndex++] = (byte) U;
                    }
                }
            }
        }
    
    二维码示例.png

    ZXingCodeUtils(生成二维码)
    ps:这是二维码生成的工具类,四种情况,带logo,不带logo,带文字带logo,带文字无logo.(文字就是指二维码的邀请码部分)嗯.....公司需求,这里是将二维码和文字画在一个背景图上面的,要是不需要,改改就是了,上图,说我们公司需要的的样式.

    public class ZXingCodeUtils {
        private volatile static ZXingCodeUtils instance;
    
        public static ZXingCodeUtils getInstance() {
            if (instance == null) {
                synchronized (ZXingCodeUtils.class) {
                    instance = new ZXingCodeUtils();
                }
            }
            return instance;
        }
    
        //不带logo
        public Bitmap createQRCode(String msg, int width, int height) {
            return createQRCode(msg, width, height, null);
        }
    
        //带logo
        public Bitmap createQRCode(String msg, int width, int height, Bitmap logo) {
            if (!TextUtils.isEmpty(msg)) {
                LogUtils.e("url is ------"+msg);
            }
            try {
                int[] tempSize = new int[]{width, height};//要求生成的二维码的宽高
                Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
                hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
                hints.put(EncodeHintType.MARGIN, 1);
                BitMatrix matrix = new QRCodeWriter().encode(msg, BarcodeFormat.QR_CODE, width, height, hints);
                //调用去除白边方法
                matrix = deleteWhite(matrix);
                width = matrix.getWidth();
                height = matrix.getHeight();
    
                int[] pixels = new int[width * height];
                for (int y = 0; y < height; y++) {
                    for (int x = 0; x < width; x++) {
                        if (matrix.get(x, y)) {
                            pixels[y * width + x] = Color.BLACK;
                        } else {
                            pixels[y * width + x] = Color.WHITE;
                        }
                    }
                }
                // 生成二维码图片的格式,使用ARGB_8888
                Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
                bitmap = addLogoToQRCode(bitmap, logo);
                bitmap = zoomImg(bitmap, tempSize[0], tempSize[1]);//处理去掉白边后,二维码的尺寸变化问题。
                return bitmap;
            } catch (WriterException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
        //带文字无logo
        public Bitmap createQRCodeWithText(ShareBitmapBean dataBean) {
            return createQRCodeWithText(dataBean, null);
        }
    
        //带文字有logo
    
    
        public Bitmap createQRCodeWithText(ShareBitmapBean dataBean, Bitmap logo) {
    
            if (dataBean == null) {
                throw new IllegalArgumentException("shareBitmap data can't be null");
            }
    
            Bitmap bg = dataBean.getBg();
            if (bg == null) {
                throw new IllegalArgumentException("background bitmap can't be null");
            }
            bg = bg.copy(Bitmap.Config.ARGB_8888, true);
            Canvas canvas = new Canvas(bg);
            Paint paint = new Paint();
    
            //绘制二维码
            if (dataBean.getQrCodeList() != null) {
                for (ShareBitmapBean.QRCodeBean qrCodeBean : dataBean.getQrCodeList()) {
                    Bitmap qrCode = createQRCode(qrCodeBean.getCodeMsg(), qrCodeBean.getCodeWidth(), qrCodeBean.getCodeHeight(), logo);
                    canvas.drawBitmap(qrCode, qrCodeBean.getCodeX(), qrCodeBean.getCodeY(), paint);
                }
            }
    
            //绘制文字
            if (dataBean.getTextList() != null) {
                for (ShareBitmapBean.TextBean textBean : dataBean.getTextList()) {
                    int textTop = textBean.getSizePX() * 7 / 8 + textBean.getTextY();
                    paint.setColor(textBean.getTextColor());
                    paint.setTextSize(textBean.getSizePX());
                    if (textBean.isCenter()) {
                        paint.setTextAlign(Paint.Align.CENTER);
                        canvas.drawText(textBean.getText(), 360, textTop, paint);
                    } else {
                        paint.setTextAlign(Paint.Align.LEFT);
                        canvas.drawText(textBean.getText(), textBean.getTextX(), textTop, paint);
                    }
    
                }
            }
    
            //绘制bitmap图像
            if (dataBean.getBitmapList() != null) {
                for (ShareBitmapBean.BitmapBean bitmapBean : dataBean.getBitmapList()) {
                    canvas.drawBitmap(bitmapBean.getBitmap(), bitmapBean.getBitmapX(), bitmapBean.getBitmapY(), paint);
                }
            }
            return bg;
        }
    
    
        //添加logo到二维码图片上
        private Bitmap addLogoToQRCode(Bitmap src, Bitmap logo) {
            if (src == null || logo == null) {
                return src;
            }
            int srcWidth = src.getWidth();
            int srcHeight = src.getHeight();
            int logoWidth = logo.getWidth();
            int logoHeight = logo.getHeight();
    
            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.restore();
            } catch (Exception e) {
                bitmap = null;
            }
            return bitmap;
        }
    
        private static BitMatrix deleteWhite(BitMatrix matrix) {
            int[] rec = matrix.getEnclosingRectangle();
            int resWidth = rec[2] + 1;
            int resHeight = rec[3] + 1;
    
            BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
            resMatrix.clear();
            for (int i = 0; i < resWidth; i++) {
                for (int j = 0; j < resHeight; j++) {
                    if (matrix.get(i + rec[0], j + rec[1]))
                        resMatrix.set(i, j);
                }
            }
            return resMatrix;
        }
    
        /**
         * 按照指定的尺寸缩放Bitmap
         *
         * @param bm
         * @param newWidth
         * @param newHeight
         * @return
         */
        public Bitmap zoomImg(Bitmap bm, float newWidth, float newHeight) {
            if (bm == null) {
                return null;
            }
            // 获得图片的宽高
            int width = bm.getWidth();
            int height = bm.getHeight();
            // 计算缩放比例
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // 取得想要缩放的matrix参数
            Matrix matrix = new Matrix();
            matrix.postScale(scaleWidth, scaleHeight);
            // 得到新的图片   www.2cto.com
            Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
            return newbm;
        }
    }
    
    

    ShareBitmapBean.Java
    这个是二维码使用Bean,使用文字,背景图片用的,需要就用,不需要就不用是了,具体都有备注的.

    public class ShareBitmapBean implements Serializable{
    
        private Bitmap bg;
    
        private List<QRCodeBean> qrCodeList;
    
        private List<TextBean> textList;
    
        private List<BitmapBean> bitmapList;
    
        public Bitmap getBg() {
            return bg;
        }
    
        public void setBg(Bitmap bg) {
            this.bg = bg;
        }
    
        public List<QRCodeBean> getQrCodeList() {
            return qrCodeList;
        }
    
        public void setQrCodeList(List<QRCodeBean> qrCodeList) {
            this.qrCodeList = qrCodeList;
        }
    
        public List<TextBean> getTextList() {
            return textList;
        }
    
        public void setTextList(List<TextBean> textList) {
            this.textList = textList;
        }
    
        public List<BitmapBean> getBitmapList() {
            return bitmapList;
        }
    
        public void setBitmapList(List<BitmapBean> bitmapList) {
            this.bitmapList = bitmapList;
        }
    
        public static class QRCodeBean implements Serializable{
    
            //二维码内的信息
            private String codeMsg;
            //二维码的宽度
            private int codeWidth;
            //二维码的高度
            private int codeHeight;
            //二维码的X坐标
            private int codeX;
            //二维码的Y坐标
            private int codeY;
    
            public QRCodeBean(String codeMsg, int codeWidth, int codeHeight, int codeX, int codeY) {
                this.codeMsg = codeMsg;
                this.codeWidth = codeWidth;
                this.codeHeight = codeHeight;
                this.codeX = codeX;
                this.codeY = codeY;
            }
    
            public String getCodeMsg() {
                return codeMsg;
            }
    
            public void setCodeMsg(String codeMsg) {
                this.codeMsg = codeMsg;
            }
    
            public int getCodeWidth() {
                return codeWidth;
            }
    
            public void setCodeWidth(int codeWidth) {
                this.codeWidth = codeWidth;
            }
    
            public int getCodeHeight() {
                return codeHeight;
            }
    
            public void setCodeHeight(int codeHeight) {
                this.codeHeight = codeHeight;
            }
    
            public int getCodeX() {
                return codeX;
            }
    
            public void setCodeX(int codeX) {
                this.codeX = codeX;
            }
    
            public int getCodeY() {
                return codeY;
            }
    
            public void setCodeY(int codeY) {
                this.codeY = codeY;
            }
    
            public List<QRCodeBean> toList() {
                List<QRCodeBean> list = new ArrayList<>();
                list.add(this);
                return list;
            }
        }
    
    
        public static class TextBean implements Serializable{
            //文字信息
            private String text;
            //字号大小,单位像素
            private int sizePX;
            //文字的X坐标
            private int textX;
            //文字的Y坐标
            private int textY;
            //文字颜色
            private int textColor;
            private boolean isCenter=false;
    
            public boolean isCenter() {
                return isCenter;
            }
    
            public void setCenter(boolean center) {
                isCenter = center;
            }
    
            public TextBean(String text, int sizePX, int textX, int textY, int textColor) {
                this.text = text;
                this.sizePX = sizePX;
                this.textX = textX;
                this.textY = textY;
                this.textColor = textColor;
            }
    
            public String getText() {
                return text;
            }
    
            public void setText(String text) {
                this.text = text;
            }
    
            public int getSizePX() {
                return sizePX;
            }
    
            public void setSizePX(int sizePX) {
                this.sizePX = sizePX;
            }
    
            public int getTextX() {
                return textX;
            }
    
            public void setTextX(int textX) {
                this.textX = textX;
            }
    
            public int getTextY() {
                return textY;
            }
    
            public void setTextY(int textY) {
                this.textY = textY;
            }
    
            public int getTextColor() {
                return textColor;
            }
    
            public void setTextColor(int textColor) {
                this.textColor = textColor;
            }
    
            public List<TextBean> toList() {
                List<TextBean> list = new ArrayList<>();
                list.add(this);
                return list;
            }
        }
    
    
        public static class BitmapBean implements Serializable{
            //bitmap
            private Bitmap bitmap;
    
            private int bitmapWidth;
    
            private int bitmapHeight;
    
            private int bitmapX;
    
            private int bitmapY;
    
            public BitmapBean(Bitmap bitmap, int bitmapWidth, int bitmapHeight, int bitmapX, int bitmapY) {
                this.bitmap = bitmap;
                this.bitmapWidth = bitmapWidth;
                this.bitmapHeight = bitmapHeight;
                this.bitmapX = bitmapX;
                this.bitmapY = bitmapY;
            }
    
            public Bitmap getBitmap() {
                return bitmap;
            }
    
            public void setBitmap(Bitmap bitmap) {
                this.bitmap = bitmap;
            }
    
            public int getBitmapWidth() {
                return bitmapWidth;
            }
    
            public void setBitmapWidth(int bitmapWidth) {
                this.bitmapWidth = bitmapWidth;
            }
    
            public int getBitmapHeight() {
                return bitmapHeight;
            }
    
            public void setBitmapHeight(int bitmapHeight) {
                this.bitmapHeight = bitmapHeight;
            }
    
            public int getBitmapX() {
                return bitmapX;
            }
    
            public void setBitmapX(int bitmapX) {
                this.bitmapX = bitmapX;
            }
    
            public int getBitmapY() {
                return bitmapY;
            }
    
            public void setBitmapY(int bitmapY) {
                this.bitmapY = bitmapY;
            }
    
            public List<BitmapBean> toList() {
                List<BitmapBean> list = new ArrayList<>();
                list.add(this);
                return list;
            }
        }
    
    
    }
    

    ----------------------好了,到此为止了,大功告成---------------------

    以上资源均来源于网络,如有侵权,联系我立刻删除!!!!

    提供四张二维码供扫描:


    1.png 2.png 3.png 4.png

    此二维码liabrary:
    链接:https://pan.baidu.com/s/1UbmscfIQyEiEzw2jrjPkwg
    提取码:onqr
    github地址:https://github.com/Mchunyan/QRTest

    一只萌级小菜鸟,哈哈哈哈哈隔 [糗大了][糗大了]

    相关文章

      网友评论

          本文标题:Android二维码扫描.(生成,扫描,相册,闪光灯)

          本文链接:https://www.haomeiwen.com/subject/szrtwftx.html