扫描二维码_扫描器二维码 - CSDN
  • 修复了在某些win7 64位电脑无法扫描二维码的BUG 在C#下通过DirectShow控制摄像头,实现快照后解码二维码。 在winXP及win7下测试通过。 希望此代码对使用C#开发摄像头和二维码应用的人有用。
  • 我开发了几个项目都用到了扫描二维码的功能,第一个项目,写了个完整的功能,之后的项目都是从第一个项目里面复制代码的,几次之后,觉得有点繁琐,所以就单独封装成一个项目,传到jcenter上,...

    前言

    二维码扫描的功能在很多APP上都会出现,较为常用的第三方库是zxing,zxing很强大,但是有时候我们并不需要那么复杂的功能,只需要简单的扫描、生成以及处理扫描结果,一般都是通过重写几个类来实现项目需求。我开发了几个项目都用到了扫描二维码的功能,第一个项目,写了个完整的功能,之后的项目都是从第一个项目里面复制代码的,几次之后,觉得有点繁琐,所以就单独封装成一个项目,传到jcenter上,以后再遇到扫描二维码的功能,只需要在gradle导入,即可实现快速开发了。

    下载APP体验
    img

    导入

    compile 'com.hebin:hxbrzxing:1.0.1'

    使用

    导入库之后,就可以使用扫描二维码的功能了,只需要新建一个activity,然后继承CaptureActivity即可。

    class MainActivity : CaptureActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
        }
    }
    

    自定义使用

    如果只是简单的继承,那么得到的效果图如下:
    这里写图片描述

    这里提供了几个可以自定义的属性;

    1. 标题栏自定义

    class MainActivity : CaptureActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val view = LayoutInflater.from(this@MainActivity).inflate(R.layout.simple_title,null)
            setTitleView(view)
        }
    }
    

    2. 背景图片自定义

    class MainActivity : CaptureActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setBackground(R.mipmap.ic_launcher)
        }
    }
    

    3. 提示文字自定义

    class MainActivity : CaptureActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setTipText("请扫描二维码")
        }
    }

    4. 附加功能

    class MainActivity : CaptureActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val view= LayoutInflater.from(this@MainActivity).inflate(R.layout.simple_title,null)
            // 打开相册,识别图片二维码
            view.tvTitle.setOnClickListener { openPhoto() }
            // 打开闪光灯
            view.tvTitle.setOnClickListener { openLight() }
            setTitleView(view)
        }
    
    }

    扫描结果处理

    继承CaptureActivity.ResultListener,并且在oncreat里面,写上setListener(this)即可实现监听,然后在onResult里面做逻辑处理。

    class MainActivity : CaptureActivity(), CaptureActivity.ResultListener {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setListener(this)
        }
    
        override fun onResult(result: String) {
            if (result.contains("http")) {
                Toast.makeText(this@MainActivity, "跳转到网页", Toast.LENGTH_SHORT).show()
            } else {
                Toast.makeText(this@MainActivity, "这个二维码不是网页", Toast.LENGTH_SHORT).show()
            }
        }
    }

    后话

    至此,只要通过简单的几行代码就实现扫描二维码的功能,而且这个扫描二维码的功能,是支持连续扫描的,不需要退出重新进入即可再次扫描。项目源码已经传到github上了。

     https://github.com/Hebin320/Zxing
    展开全文
  • 二维码扫描

    2019-01-09 11:52:26
    导入Zxing_lib 设置权限 <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.CAMERA"...android....

    导入Zxing_lib

    设置权限

    <uses-permission android:name="android.permission.CALL_PHONE"/>
    
    <uses-permission android:name="android.permission.CAMERA"/>
    
    <uses-permission android:name="android.permission.FLASHLIGHT"/>
    
    <uses-feature android:name="android.hardware.camera"/>
    
    <uses-feature android:name="android.hardware.camera.autofocus"/>
    
    <uses-permission android:name="android.permission.VIBRATE"/>
    
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    
    <uses-permission android:name="android.permission.INTERNET"/>

    添加依赖 Acp依赖和logger依赖

    implementation 'com.orhanobut:logger:2.2.0'
    implementation 'com.mylhyl:acp:1.1.7'

    初始化Zxing

    
            ZXingLibrary.initDisplayOpinion(this);
            Acp.getInstance(this).request(new AcpOptions.Builder()
                            .setPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE
                                    , Manifest.permission.READ_PHONE_STATE
                                    , Manifest.permission.SEND_SMS
                                    ,Manifest.permission.ACCESS_COARSE_LOCATION,
                                    Manifest.permission.ACCESS_WIFI_STATE,Manifest.permission.CALL_PHONE,
                                    Manifest.permission.CAMERA
                                    )
    
                            .build(),
                    new AcpListener() {
                        @Override
                        public void onGranted() {
                           // call();
                        }
    
                        @Override
                        public void onDenied(List<String> permissions) {
                            Toast.makeText(MainActivity.this, "你拒绝了这个权限", Toast.LENGTH_SHORT).show();
                        }
                    });

    设置点击的intent的跳转

     @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, CaptureActivity.class);
            startActivityForResult(intent,112);
            Log.d(TAG, "onActivityResult: "+ "我很快乐");
            Logger.i("hello444555555");
            Logger.v("hello444");
            Logger.wtf("hello666");
            String  JSON_CONTENT=
                    "{\"Category\":[{\"categoryId\":1,\"categoryName\":\"饮品\",\"categoryImage\":\"/upload/yinpin.jpg\"},{\"categoryId\":2,\"categoryName\":\"食品\",\"categoryImage\":\"/upload/shiping.jpg\"},{\"categoryId\":3,\"categoryName\":\"酒类\",\"categoryImage\":\"/upload/jiullei.jpg\"}],\"recommend\":{\"id\":11,\"productName\":\"统一老坛泡椒牛肉袋面香辣味110g*24袋\",\"filenameSmall\":\"/upload/ty_ltpj_small.jpg\",\"productPrice\":48.0,\"productCost\":47.5}}";
            Logger.json(JSON_CONTENT);
        }

    设置请求返回的数据

     @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            /**
             * 处理二维码扫描结果
             */
            if (requestCode == 112) {
                //处理扫描结果(在界面上显示)
                if (null != data) {
                    Bundle bundle = data.getExtras();
                    if (bundle == null) {
                        return;
                    }
                    if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_SUCCESS) {
                        String result = bundle.getString(CodeUtils.RESULT_STRING);
                        Toast.makeText(this, "解析结果:" + result, Toast.LENGTH_LONG).show();
                        Log.d(TAG, "onActivityResult: "+ result);
    
                    } else if (bundle.getInt(CodeUtils.RESULT_TYPE) == CodeUtils.RESULT_FAILED) {
                        Toast.makeText(MainActivity.this, "解析二维码失败", Toast.LENGTH_LONG).show();
                    }
                }
            }
        }
    

     

    展开全文
  • 现在的应用都有自己的二维码扫描工具,最近接手的项目也不例外,集成了ZXing二维码扫描,但是用起来却实在差强人意,后来看到QrCodeReaderView效果不错,识别速度上有明显提高,而且使用也非常简单,于是便迅速集成...

    现在的应用都有自己的二维码扫描工具,最近接手的项目也不例外,集成了ZXing二维码扫描,但是用起来却实在差强人意,后来看到QrCodeReaderView效果不错,识别速度上有明显提高,而且使用也非常简单,于是便迅速集成,唯独对扫码界面定制不够,于是再对ZXing中的自定义View修改,便得到较为完整的二维码扫描解决方案:

    • 二维码扫描框
    • 自定义属性
    • 颜色资源
    • 图片资源
    • 生成二维码
    • 二维码生成工具类

    二维码扫描框

    /*
     * Copyright (C) 2008 ZXing authors
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.apple.widget;
    
    import android.content.Context;
    import android.content.res.Resources;
    import android.content.res.TypedArray;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    import android.view.View;
    
    import com.apple.lottle.R;
    
    import java.util.Collection;
    import java.util.HashSet;
    
    /**
     * 自定义组件实现,扫描功能
     */
    public final class ViewfinderView extends View {
    
        private static final long ANIMATION_DELAY = 100L;
        private static final int OPAQUE = 0xFF;
    
        public static int FRAME_WIDTH = -1;
        public static int FRAME_HEIGHT = -1;
        public static int FRAME_MARGINTOP = -1;
        private final Paint paint;
        private final int maskColor;
        private final int resultColor;
        private final int resultPointColor;
        private int screenWidthPx;
        private int screenHeightPx;
        private Bitmap resultBitmap;
        private Collection<ResultPoint> possibleResultPoints;
        private Collection<ResultPoint> lastPossibleResultPoints;
        private Rect framingRect;
        //扫描区域提示文本
        private String labelText;
        //扫描区域提示文本颜色
        private int labelTextColor;
        private float labelTextSize;
        // 扫描线移动的y
        private int scanLineTop;
        // 扫描线移动速度
        private int SCAN_VELOCITY;
        // 扫描线
        private Bitmap scanLight;
        // 是否展示小圆点
        private boolean isCircle;
        // 扫描框边角颜色
        private int innercornercolor;
        // 扫描框边角长度
        private int innercornerlength;
        // 扫描框边角宽度
        private int innercornerwidth;
    
        public ViewfinderView(Context context) {
            this(context, null);
        }
    
        public ViewfinderView(Context context, AttributeSet attrs) {
            this(context, attrs, -1);
        }
    
        public ViewfinderView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            paint = new Paint();
            Resources resources = getResources();
            maskColor = resources.getColor(R.color.viewfinder_mask);
            resultColor = resources.getColor(R.color.result_view);
            resultPointColor = resources.getColor(R.color.possible_result_points);
            possibleResultPoints = new HashSet<>(5);
            screenWidthPx = context.getResources().getDisplayMetrics().widthPixels;
            screenHeightPx = context.getResources().getDisplayMetrics().heightPixels;
            scanLight = BitmapFactory.decodeResource(resources, R.drawable.scan_light);
    
            initInnerRect(context, attrs);
        }
    
        /**
         * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
         */
        public static int dip2px(Context context, float dpValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    
        /**
         * 初始化内部框的大小
         *
         * @param context
         * @param attrs
         */
        private void initInnerRect(Context context, AttributeSet attrs) {
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewfinderView);
            // 扫描框距离顶部
            float innerMarginTop = ta.getDimension(R.styleable.ViewfinderView_inner_margintop, -1);
            if (innerMarginTop != -1) {
                FRAME_MARGINTOP = (int) innerMarginTop;
            }
            // 扫描框的宽度
            FRAME_WIDTH = (int) ta.getDimension(R.styleable.ViewfinderView_inner_width, screenWidthPx * 2 / 3);
            // 扫描框的高度
            FRAME_HEIGHT = (int) ta.getDimension(R.styleable.ViewfinderView_inner_height, screenWidthPx * 2 / 3);
            // 扫描框边角颜色
            innercornercolor = ta.getColor(R.styleable.ViewfinderView_inner_corner_color, Color.parseColor("#45DDDD"));
            // 扫描框边角长度
            innercornerlength = (int) ta.getDimension(R.styleable.ViewfinderView_inner_corner_length, 65);
            // 扫描框边角宽度
            innercornerwidth = (int) ta.getDimension(R.styleable.ViewfinderView_inner_corner_width, 15);
            labelTextColor = ta.getColor(R.styleable.ViewfinderView_label_text_color, 0x90FFFFFF);
            labelText = ta.getString(R.styleable.ViewfinderView_label_text);
            labelTextSize = ta.getFloat(R.styleable.ViewfinderView_label_text_size, 36);
            // 扫描bitmap
            Drawable drawable = ta.getDrawable(R.styleable.ViewfinderView_inner_scan_bitmap);
            if (drawable != null) {
            }
            // 扫描控件
            scanLight = BitmapFactory.decodeResource(getResources(), ta.getResourceId(R.styleable.ViewfinderView_inner_scan_bitmap, R.drawable.scan_light));
            // 扫描速度
            SCAN_VELOCITY = ta.getInt(R.styleable.ViewfinderView_inner_scan_speed, 5);
            isCircle = ta.getBoolean(R.styleable.ViewfinderView_inner_scan_iscircle, true);
            ta.recycle();
        }
    
        /**
         * Calculates the framing rect which the UI should draw to show the user where to place the
         * barcode. This target helps with alignment as well as forces the user to hold the device
         * far enough away to ensure the image will be in focus.
         *
         * @return The rectangle to draw on screen in window coordinates.
         */
        public Rect getFramingRect() {
            try {
                int leftOffset = (screenWidthPx - FRAME_WIDTH) / 2;
    
                int topOffset;
                if (FRAME_MARGINTOP != -1) {
                    topOffset = FRAME_MARGINTOP;
                } else {
                    topOffset = (screenHeightPx - FRAME_HEIGHT) / 3;
                }
                framingRect = new Rect(leftOffset, topOffset, leftOffset + FRAME_WIDTH, topOffset + FRAME_HEIGHT);
                // }
                return framingRect;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        @Override
        public void onDraw(Canvas canvas) {
            Rect frame = getFramingRect();
            if (frame == null) {
                return;
            }
            int width = canvas.getWidth();
            int height = canvas.getHeight();
    
            // Draw the exterior (i.e. outside the framing rect) darkened
            paint.setColor(resultBitmap != null ? resultColor : maskColor);
            canvas.drawRect(0, 0, width, frame.top, paint);
            canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
            canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
            canvas.drawRect(0, frame.bottom + 1, width, height, paint);
    
            if (resultBitmap != null) {
                // Draw the opaque result bitmap over the scanning rectangle
                paint.setAlpha(OPAQUE);
                canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);
            } else {
                drawFrameBounds(canvas, frame);
                drawScanLight(canvas, frame);
                //绘制提示信息
                drawTextInfo(canvas, frame);
                Collection<ResultPoint> currentPossible = possibleResultPoints;
                Collection<ResultPoint> currentLast = lastPossibleResultPoints;
                if (currentPossible.isEmpty()) {
                    lastPossibleResultPoints = null;
                } else {
                    possibleResultPoints = new HashSet<ResultPoint>(5);
                    lastPossibleResultPoints = currentPossible;
                    paint.setAlpha(OPAQUE);
                    paint.setColor(resultPointColor);
    
                    if (isCircle) {
                        for (ResultPoint point : currentPossible) {
                            canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
                        }
                    }
                }
                if (currentLast != null) {
                    paint.setAlpha(OPAQUE / 2);
                    paint.setColor(resultPointColor);
    
                    if (isCircle) {
                        for (ResultPoint point : currentLast) {
                            canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 3.0f, paint);
                        }
                    }
                }
                postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top, frame.right, frame.bottom);
            }
        }
    
        /**
         * 绘制移动扫描线
         *
         * @param canvas
         * @param frame
         */
        private void drawScanLight(Canvas canvas, Rect frame) {
            if (scanLineTop == 0) {
                scanLineTop = frame.top;
            }
            if (scanLineTop >= frame.bottom - 30) {
                scanLineTop = frame.top;
            } else {
                scanLineTop += SCAN_VELOCITY;
            }
            Rect scanRect = new Rect(frame.left, scanLineTop, frame.right,
                    scanLineTop + 30);
            canvas.drawBitmap(scanLight, null, scanRect, paint);
        }
    
        /**
         * 绘制取景框边框
         *
         * @param canvas
         * @param frame
         */
        private void drawFrameBounds(Canvas canvas, Rect frame) {
            paint.setColor(innercornercolor);
            paint.setStyle(Paint.Style.FILL);
            int corWidth = innercornerwidth;
            int corLength = innercornerlength;
            // 左上角
            canvas.drawRect(frame.left, frame.top, frame.left + corWidth, frame.top + corLength, paint);
            canvas.drawRect(frame.left, frame.top, frame.left + corLength, frame.top + corWidth, paint);
            // 右上角
            canvas.drawRect(frame.right - corWidth, frame.top, frame.right, frame.top + corLength, paint);
            canvas.drawRect(frame.right - corLength, frame.top, frame.right, frame.top + corWidth, paint);
            // 左下角
            canvas.drawRect(frame.left, frame.bottom - corLength, frame.left + corWidth, frame.bottom, paint);
            canvas.drawRect(frame.left, frame.bottom - corWidth, frame.left + corLength, frame.bottom, paint);
            // 右下角
            canvas.drawRect(frame.right - corWidth, frame.bottom - corLength, frame.right, frame.bottom, paint);
            canvas.drawRect(frame.right - corLength, frame.bottom - corWidth, frame.right, frame.bottom, paint);
        }
    
        //绘制文本
        private void drawTextInfo(Canvas canvas, Rect frame) {
            paint.setColor(labelTextColor);
            paint.setTextSize(labelTextSize);
            paint.setTextAlign(Paint.Align.CENTER);
            canvas.drawText(labelText, frame.left + frame.width() / 2, frame.bottom + innercornerlength * 1.5f, paint);
        }
    
        public void drawViewfinder() {
            resultBitmap = null;
            invalidate();
        }
    
        public void addPossibleResultPoint(ResultPoint point) {
            possibleResultPoints.add(point);
        }
    }

    自定义属性

    <declare-styleable name="ViewfinderView">
        <attr name="inner_width" format="dimension"/>
        <attr name="inner_height" format="dimension"/>
        <attr name="inner_margintop" format="dimension" />
        <attr name="inner_corner_color" format="color" />
        <attr name="inner_corner_length" format="dimension" />
        <attr name="inner_corner_width" format="dimension" />
        <attr name="inner_scan_bitmap" format="reference" />
        <attr name="inner_scan_speed" format="integer" />
        <attr name="inner_scan_iscircle" format="boolean" />
        <attr name="label_text_color" format="color"/>
        <attr name="label_text" format="string"/>
        <attr name="label_text_size" format="integer"/>
    </declare-styleable>

    颜色资源

    <!-- 二维码扫描 -->
    <color name="viewfinder_mask">#60000000</color>
    <color name="result_view">#b0000000</color>
    <color name="possible_result_points">#c0ffff00</color>

    图片资源

    扫描线

    生成二维码

    Bitmap bitmap = QrCodeUtils.createImage(jsonObject.toString(), 400, 400, null);
    imageView.setImageBitmap(bitmap);

    二维码生成工具类

    package com.apple.utils;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.res.AssetFileDescriptor;
    import android.graphics.Bitmap;
    import android.graphics.Matrix;
    import android.media.AudioManager;
    import android.media.MediaPlayer;
    import android.os.Vibrator;
    import android.text.TextUtils;
    
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.EncodeHintType;
    import com.google.zxing.WriterException;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.qrcode.QRCodeWriter;
    import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
    import com.zhcx.doctorgh.R;
    
    import java.io.IOException;
    import java.util.Hashtable;
    
    /**
     * 二维码扫描工具类
     */
    public class QrCodeUtils {
    
        /**
         * 生成二维码图片
         *
         * @param text
         * @param w
         * @param h
         * @param logo
         * @return
         */
        public static Bitmap createImage(String text, int w, int h, Bitmap logo) {
            if (TextUtils.isEmpty(text)) {
                return null;
            }
            try {
                Bitmap scaleLogo = getScaleLogo(logo, w, h);
    
                int offsetX = w / 2;
                int offsetY = h / 2;
    
                int scaleWidth = 0;
                int scaleHeight = 0;
                if (scaleLogo != null) {
                    scaleWidth = scaleLogo.getWidth();
                    scaleHeight = scaleLogo.getHeight();
                    offsetX = (w - scaleWidth) / 2;
                    offsetY = (h - scaleHeight) / 2;
                }
                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, 0);
                BitMatrix bitMatrix = new QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, w, h, hints);
                int[] pixels = new int[w * h];
                for (int y = 0; y < h; y++) {
                    for (int x = 0; x < w; x++) {
                        if (x >= offsetX && x < offsetX + scaleWidth && y >= offsetY && y < offsetY + scaleHeight) {
                            int pixel = scaleLogo.getPixel(x - offsetX, y - offsetY);
                            if (pixel == 0) {
                                if (bitMatrix.get(x, y)) {
                                    pixel = 0xff000000;
                                } else {
                                    pixel = 0xffffffff;
                                }
                            }
                            pixels[y * w + x] = pixel;
                        } else {
                            if (bitMatrix.get(x, y)) {
                                pixels[y * w + x] = 0xff000000;
                            } else {
                                pixels[y * w + x] = 0xffffffff;
                            }
                        }
                    }
                }
                Bitmap bitmap = Bitmap.createBitmap(w, h,
                        Bitmap.Config.ARGB_8888);
                bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
                return bitmap;
            } catch (WriterException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private static Bitmap getScaleLogo(Bitmap logo, int w, int h) {
            if (logo == null) return null;
            Matrix matrix = new Matrix();
            float scaleFactor = Math.min(w * 1.0f / 5 / logo.getWidth(), h * 1.0f / 5 / logo.getHeight());
            matrix.postScale(scaleFactor, scaleFactor);
            Bitmap result = Bitmap.createBitmap(logo, 0, 0, logo.getWidth(), logo.getHeight(), matrix, true);
            return result;
        }
    }

    展开全文
  • 利用html5(navigator.getUserMedia)调用摄像头抓拍图片媒体流,通过php调用java接口解析图片二维码,实现二维码解析,可结合自己的业务!不过目前支持的浏览器不多是个问题。

    闲话不说,直接上代码,本人测试通过!

    html/js

    <!DOCTYPE html>
    <html><head>
    	<title>HTML5 code Reader</title>
    	<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    </head>
    <style type="text/css">
     html, body { height: 100%; width: 100%; text-align:center; }  
    </style>
    <script src="jquery-1.9.1.js"></script>
    <script>
    //这段代 主要是获取摄像头的视频流并显示在Video 签中  
    var canvas=null,context=null,video=null;   
    window.addEventListener("DOMContentLoaded", function ()
    {
    	try{
    		canvas = document.getElementById("canvas");
    		context = canvas.getContext("2d");
    		video = document.getElementById("video");
    		
    		var videoObj = { "video": true,audio:false},
    		flag=true,
    		MediaErr = function (error)
    		{           
    			flag=false;  
    			if (error.PERMISSION_DENIED)
    			{
    				 alert('用户拒绝了浏览器请求媒体的权限', '提示');
    			} else if (error.NOT_SUPPORTED_ERROR) {
    				 alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器', '提示');
    			} else if (error.MANDATORY_UNSATISFIED_ERROR) {
    				 alert('指定的媒体类型未接收到媒体流', '提示');
    			} else {
    				 alert('系统未能获取到摄像头,请确保摄像头已正确安装。或尝试刷新页面,重试', '提示');
    			}
    		};
    		//获取媒体的兼容代码,目前只支持(Firefox,Chrome,Opera)
            if (navigator.getUserMedia)
    		{
    			//qq浏览器不支持
    			if (navigator.userAgent.indexOf('MQQBrowser') > -1) {
    				 alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器', '提示');
    				 return false;
                }
                navigator.getUserMedia(videoObj, function (stream) {
    				video.src = stream;                
    				video.play();      
                }, MediaErr);           
    		}
    		else if(navigator.webkitGetUserMedia)
    		{
               navigator.webkitGetUserMedia(videoObj, function (stream)
    		   {          
                 video.src = window.webkitURL.createObjectURL(stream);           
                 video.play();           
            	}, MediaErr);           
    		}
    		else if (navigator.mozGetUserMedia)
    		{
    			navigator.mozGetUserMedia(videoObj, function (stream) {
    				 video.src = window.URL.createObjectURL(stream);
    				 video.play();
    			}, MediaErr);
    		}
    		else if (navigator.msGetUserMedia)
    		{ 
    			 navigator.msGetUserMedia(videoObj, function (stream) {
                 	$(document).scrollTop($(window).height());
                    video.src = window.URL.createObjectURL(stream);
                    video.play();
                 }, MediaErr);
    		}else{
    			alert('对不起,您的浏览器不支持拍照功能,请使用其他浏览器');
    			return false;
    		}
    		if(flag){
    			alert('为了获得更准确的测试结果,请尽量将二维码置于框中,然后进行拍摄、扫描。 请确保浏览器有权限使用摄像功能');
    		}
         	 //这个是拍照按钮的事件,          
         	$("#snap").click(function () {startPat();}).show();
    	}catch(e){      
            printHtml("浏览器不支持HTML5 CANVAS");       
        } 
    }, false);
        
    //打印内容到页面      
    function printHtml(content){
    	$(window.document.body).append(content+"<br/>");
    }
    //开始拍照
    function startPat(){
    	setTimeout(function(){//防止调用过快
    		if(context)
    		{
    			context.drawImage(video, 0, 0, 320, 320);     
    			CatchCode(); 
    		}
    	},200);
    } 
    //抓屏获取图像流,并上传到服务器      
    function CatchCode() {        
    	if(canvas!=null)
    	{  
       		//以下开始编 数据   
    		var imgData = canvas.toDataURL(); 
    		//将图像转换为base64数据
            var base64Data = imgData;//.substr(22); //在前端截取22位之后的字符串作为图像数据
            //开始异步上
    	   $.post("saveimg.php", { "img": base64Data },function (result)
    	   {   
    			printHtml("解析结果:"+result.data);
    			if (result.status == "success" && result.data!="")
    			{                 
    				printHtml("解析结果成功!");
    			}else{  
    				startPat();//如果没有解析出来则重新抓拍解析       
    			}
    	   },"json");
    	}
    }      
    </script>
      <body>
    
    <div id="support"></div>
    <div id="contentHolder">       
    <video id="video" width="320" height="320" autoplay>
    </video>       
    <canvas style="display:none; background-color:#F00;" id="canvas" width="320" height="320">
    </canvas> <br/>
    <button id="snap" style="display:none; height:50px; width:120px;">开始扫描</button>  
       </div>
    
    
    
    </body></html>

    php(saveimg)

    <?php
    include_once("utils.php");
    $base64_image_content=$_POST['img'];
    if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result))
    {
      $type = $result[2];
      $new_file = "./2.{$type}";
      if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))){
    	$code=utils::deCodeBitMap("2.png","192.168.46.123",20147);
    	echo '{"status":"success","data":"'.trim($code).'"}';
      }else{
      	echo '{"status":"write error","data":"NO"}';
      }
    }else{
    	echo '{"status":"preg error","data":"NO"}';
    }
    ?>

    php(utils)

     class  utils{
     	
    	/**
         	* @access static
         	* @param  $imagepath String 图片的完整路径
    	* @param  $host      String 主机如:127.0.0.1
    	* @param  $port      String 端口号如:20147
         	* @return string 解析出的URL
        	*/
    	static function deCodeBitMap($imagepath,$host,$port){
    		$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die($imagepath." Could not connet server create\n"); // 创建一个Socket
    		if(!$socket){
    			return "";
    		}
    		$connection = socket_connect($socket, $host, $port) or die($imagepath." Could not connet server connection\n");    //  连接
    		if(!$connection){
    			return "";
    		}
    		socket_write($socket, $imagepath) or die("Write failed\n"); // 数据传送 向服务器发送消息
    
    		$buff = socket_read($socket, 1024, PHP_NORMAL_READ);
    		return $buff;
    	}
    	
     }
    java扩展使用说明

    该解析过程需要java环境支持,jar包启动后在本机的20147端口接受socket监听,因此网络编程语言都可以调用。
    1 命令行启动jar包
    java -jar xxxxx.jar
    启动成功应该能看到20147端口的应用
    2服务socket调用
    暂提供php调用代码

    最终效果:


    程序已打包:在我的资源里面,可自行下载!

    源码打包下载


    浏览器支持情况


    展开全文
  • 首先,任何一个二维码表示的都是一串字符串。 我们打开淘宝登录页面:https://login.taobao.com/member/login.jhtml,展示了二维码:    通过草料二维码解析出这张二维码表示的是如下字符串: ...
  • 之前我写过一篇博客是关于如何将zxing集成到Android...扫描速度也比较慢,功能不是很全,没有闪光灯,生成二维码,解析二维码图片,解析条码图片等。 这几天抽了点时间,将之前的代码完善了一下,主要是修复了一些b...
  • 一、什么是二维码 二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。二维条码...
  • 现在的很多项目都拥有web网页端和APP端,一般都是同时使用,当使用APP时则需要下载,常用的方式则是扫描二维码下载。现在来分享一下自己在工作中具体是如何实现扫描二维码进行下载的。 生成二维码 草料二维码...
  • 转载:http://blog.csdn.net/yuzhiqiang_1993/article/details/782920041.基本的扫一扫扫描二维码从图片可以看到,我扫的二维码还是挺复杂的一个二维码,识别速度还可以。具体使用跟设备的摄像头配置有很大关系。...
  • 微信扫描二维码跳转页面 近在完成一个大作业,反正一个小部分就是扫描二维码,跳转到一个界面去,搜网上也没有什么太有用的信息,觉得难死了。。 后来想想,以前写过一个程序,就是把字符串生成相应的二维码,...
  • 引子:最近公司项目有个需求,微博客户端中, h5 的页面上的某个按钮能够与native 交互呼起摄像头,扫描二维码并且解析。在非微博客户端中(微信或者是原生浏览器,如:safari)呼起系统的拍照或者上传图片按钮,...
  • 所以就干脆照抄别人的,简单实现了一个生成二维码,调用摄像头实时扫描二维码。 扫描的基本思路是每个10秒截一次屏,并保存为一个bmp格式的图片,然后调用zxing的类库解码,如果解码成功就终止截屏任务。
  • 而我们扫描二维码有时候显示的是普通的几个汉字,有时候是一个网页页面,那么这些效果都是如何实现的呢,下面我们就来详细看一下: 在中琅标签打印软件中,制作条形码二维码都是其基础功能,扫描二维码显示汉字也是...
  • 文章目录文章参考问题描述开发工具模拟扫描二维码进入小程序的解决办法 文章参考 微信小程序未发布 二维码图片如何扫描测试 问题描述 有个要识别二维码页面跳转的功能,想着怎么样模拟识别二维码呢,用开发工具...
  • 网站实现扫描二维码关注微信公众号,自动登陆网站并获取其信息 生成带参数的二维码-微信开发文档   需求  网站实现扫描二维码关注微信公众号,如果已经关注公众号就自动登陆网站并获取其微信昵称,头像等信息...
  • 现在二维码随处可见,二维码支付,二维码点餐,二维码坐公交,二维码做地铁,广告宣传页上, 电视台节目上等等。...IOS怎么实现扫描二维码功能呢? 直接复制代码粘贴一下即可使用,贴上@2x @3x图片...
  • android 扫描二维码程序代码 可将扫描结果存到手机中的 名为Barcode文件夹下面的BS.txt文件中
  • 关于扫描二维码下载app功能实现方法   功能实现思路:  Androidapk的下载本质上就是文件的下载,所以我们只需要在后台提供一个下载的方法,就能是实现apk的下载。  在实现后台代码以后,我们生成一个url下载...
  • js扫描二维码并跳转

    2019-07-31 05:45:50
    项目中,需要用到扫描二维码,并识别二维码。在此记录,便于以后深入了解,这里是一个简单的例子: 这里需要引入jquery.js和jquery-qrcode-min.js <!doctype html><html lang="en"><head><...
1 2 3 4 5 ... 20
收藏数 96,735
精华内容 38,694
关键字:

扫描二维码