2017-04-12 14:33:58 weixin_37730482 阅读数 633
  • 微信公众平台深度开发v2.0第3季——二维码、模板消息

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    10262 人正在学习 去看看 翟东平

前篇介绍了ZXing开源框架的使用,此篇接着讲解一些ZXing的知识并使用ZXing生成二维码

 

Android 二维码框架之Zxing实现二维码扫描功能

 

 

1、ZXing库介绍

  这里简单介绍一下ZXing库。ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。该项目可实现的条形码编码和解码。目前支持以下格式:UPC-A,UPC-E、EAN-8,EAN-13、39码、93码。ZXing是个很经典的条码/二维码识别的开源类库,以前在功能机上,就有开发者使用J2ME运用ZXing了,不过要支持JSR-234规范(自动对焦)的手机才能发挥其威力。

 

 

 

2、ZXing库主要类

CaptureActivity。这个是启动Activity 也就是扫描器。


CaptureActivityHandler 解码处理类,负责调用另外的线程进行解码。


DecodeThread 解码的线程。


com.google.zxing.client.android.camera 包,摄像头控制包。


ViewfinderView 自定义的View,就是我们看见的拍摄时中间的框框了。

 

 

 

3.生成二维码

 

代码

public class ShowQrCodeActivity extends BaseActivity implements View.OnClickListener{

    private RelativeLayout backlayout;
    private TextView titletextview;
    private ImageView imageview;
    private Bitmap bitmap;
    private Bitmap logobitmap;
    private PopupWindow saveimg_ppw;//自定义保存图片PPW
    private Button savebtn;//保存图片
    private Button cancalbtn;//取消
    private ToastUtils toast;
    private AlertDialog alertDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_showqrcode);
        initView();
    }

    /**
     * 初始化各种view方法
     * */

    private void initView(){
        toast=new ToastUtils(this);
        backlayout= (RelativeLayout) findViewById(R.id.apptoplayout_onlyback_backlayout);
        titletextview= (TextView) findViewById(R.id.apptoplayout_onlyback_titletextview);
        backlayout.setOnClickListener(this);
        imageview= (ImageView) findViewById(R.id.activity_showqrcode_imageview);
        titletextview.setText(R.string.activity_showqrcodetextview1);
        imageview.setOnClickListener(this);
        //二维码Logo
        logobitmap=BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        if(null!=logobitmap){
            if(FileHelper.isSdCardExist()){
                createQRImage(StringConstant.CliniciansQrCodeUrl,logobitmap);
            }else{
                toast.showToast(StringConstant.Filestatus2);
            }
        }
    }

    /**
     * 生成二维码
     * */

    private void createQRImage(final String url,final Bitmap logobitmap){
        
    }

    /**
     * 保存二维码文件存储根目录
     * */

    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();
    }

    /**
     * 各种点击事件的方法
     * */

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.apptoplayout_onlyback_backlayout://返回操作
                backPPW();
                break;
            case R.id.activity_showqrcode_imageview://显示PPW
                requestAndroidPermission();
                break;
            case R.id.saveimagepopuview_savebtn://保存图片
                if (null != imageview) {
                    imageview.setDrawingCacheEnabled(true);
                    bitmap = Bitmap.createBitmap(imageview.getDrawingCache());
                    imageview.setDrawingCacheEnabled(false);
                    String strPath =UUID.randomUUID().toString()+".png";
                    FileOutputStream fos = null;
                    try {
                        File file = new File(FileHelper.getTheRootDirectory() + StringConstant.PICTURESAVE_Path);
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        fos = new FileOutputStream(FileHelper.getTheRootDirectory()+ StringConstant.PICTURESAVE_Path+strPath);
                        //当指定压缩格式为PNG时保存下来的图片显示正常
                        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
                        //当指定压缩格式为JPEG时保存下来的图片背景为黑色
                        //bitmap.compress(CompressFormat.JPEG, 100, fos);
                        fos.flush();
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            fos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    toast.showToast(StringConstant.followformstatus24);
                } else {
                    toast.showToast(StringConstant.followformstatus241);
                }
                dismissPpw();
                break;
            case R.id.saveimagepopuview_cancalbtn://取消
                dismissPpw();
                break;
        }
    }

    /**
     * Android 6.0系统及以上申请敏感权限方法
     * */

    private void requestAndroidPermission(){
        if(FileHelper.isSdCardExist()){
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){//6.0
                boolean has= AndroidPermissionUtils.hasAndroidPermission(ShowQrCodeActivity.this, DataConstant.permission);
                if(!has){//6.0及以上 没有权限
                    AndroidPermissionUtils.requestAndroidPermission(ShowQrCodeActivity.this,0,DataConstant.permission);
                }else{//6.0及以上 有权限 操作文件
                    getSavePopupWindowInstance();
                    saveimg_ppw.showAtLocation(this.findViewById(R.id.activity_showqrcode_fatherlayout), Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,0);
                }
            }else{//6.0以下 操作文件
                getSavePopupWindowInstance();
                saveimg_ppw.showAtLocation(this.findViewById(R.id.activity_showqrcode_fatherlayout), Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,0);
            }
        }else{
            toast.showToast(StringConstant.Filestatus2);
        }
    }

    /**
     * onRequestPermissionsResult 动态申请回调方法
     * */

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(grantResults.length > 0 && !(grantResults[0] == PackageManager.PERMISSION_GRANTED)){
            showDialogs("温馨提示",StringConstant.errorstate6);
        }
    }

    /**
     * 显示提示对话框
     */

    public void showDialogs(final String title,final String msg) {
        if(!ActivityUtils.isActivityIsAlive(this)){
            return;
        }
        alertDialog=new AlertDialog.Builder(this).create();
        alertDialog.show();
        alertDialog.setCancelable(false);//点击外部 对话框不消失
        Window window=alertDialog.getWindow();
        window.setContentView(R.layout.dialog_informations);
        TextView titletv= (TextView) window.findViewById(R.id.dialog_informations_titletv);
        titletv.setText(title);
        //显示内容
        TextView contexttv = (TextView) window.findViewById(R.id.dialog_informations_contexttv);
        contexttv.setText(msg);
        //确定
        TextView suretv=(TextView) window.findViewById(R.id.dialog_informations_surelv);
        suretv.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                alertDialog.dismiss();
            }
        });
    }

    /**
     * 获取自定义保存图片PPW对象的方法
     * */

    public void getSavePopupWindowInstance(){
        if(saveimg_ppw!=null){
            saveimg_ppw.dismiss();//隐藏保存图片PPW
        }else{
            initSavePopuptWindow();//创建保存图片PPW
        }
    }

    /**
     * 创建自定义选择头像保存图片PPW对象的方法
     * */

    public void initSavePopuptWindow(){
        View userView=View.inflate(this,R.layout.saveimagepopupview,null);
        savebtn=(Button) userView.findViewById(R.id.saveimagepopuview_savebtn);
        cancalbtn=(Button) userView.findViewById(R.id.saveimagepopuview_cancalbtn);
        savebtn.setOnClickListener(this);
        cancalbtn.setOnClickListener(this);

        /**
         * 创建一个PopupWindow
         * 参数1:contentView 指定PopupWindow的内容
         * 参数2:width 指定PopupWindow的width
         * 参数3:height 指定PopupWindow的height
         * */

        saveimg_ppw=new PopupWindow(userView, ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
        //这2行是为了当点击外部时候popupWindow自己dismiss掉
        saveimg_ppw.setBackgroundDrawable(new BitmapDrawable());
        saveimg_ppw.setOutsideTouchable(true);
        //设置SelectPicPopupWindow弹出窗体动画效果
        saveimg_ppw.setAnimationStyle(R.style.AnimBottomss);
        //实例化一个ColorDrawable颜色为半透明
        ColorDrawable dw = new ColorDrawable(0xb0000000);
        //设置SelectPicPopupWindow弹出窗体的背景
        saveimg_ppw.setBackgroundDrawable(dw);
    }

    /**
     * 隐藏PPW对象的方法
     * */

    public void dismissPpw(){
        if(saveimg_ppw!=null){
            saveimg_ppw.dismiss();
        }
    }

    /**
     * 返回时操作ppw
     * */

    public void backPPW(){
        if(saveimg_ppw!=null){
            if(saveimg_ppw.isShowing()){
                saveimg_ppw.dismiss();
            }else{
                finish();
                overridePendingTransition(0,R.anim.activity_right_open);
            }
        }else{
            finish();
            overridePendingTransition(0,R.anim.activity_right_open);
        }
    }

    /**
     * onDestroy方法
     * */

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ImageViewCachUtils.releaseBitmap(bitmap);
        ImageViewCachUtils.releaseBitmap(logobitmap);
        if(null!=alertDialog){//隐藏对话框
            alertDialog.dismiss();
        }
    }

    /**
     * onKeyDown方法
     * */

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            backPPW();
            return false;
        }
        return super.onKeyDown(keyCode, event);
    }

}

 

完整项目代码:https://github.com/wujianning/QrCode

2018-05-14 08:09:06 luoyayun361 阅读数 1575
  • 微信公众平台深度开发v2.0第3季——二维码、模板消息

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    10262 人正在学习 去看看 翟东平

前言

由于项目要求,需要用 Qt 做一个Android 程序用于扫描二维码并获取扫码内容,之前参考了很多资料,很多都是基于桌面端的二维码识别,如一去丶二三里大神的Qt之二维码扫描,原理是直接导入一张二维码图片然后进行识别,而移动端会稍微麻烦一点点,并且关于 Qt 来做一个 Android 程序扫描二维码的资料太少,最终通过各种尝试,采用 QML+QZXing 的结合来实现该功能,这里做一个简单的总结。

原理

程序实现原理大概分为几个步骤:

1.Camera启动手机摄像头
2.VideoOutput获取一个摄像头的预览视频帧
3.QZXing对视频帧进行解析并返回内容

效果图

界面做得很简陋,但是功能实现,后期只要提供界面图标来重新实现界面就完美了。

左边是程序界面,中间的扫描线是动态的,右边是扫描后的效果,content 是扫描到的二维码内容,Detected count是检测次数。

源码

来看看 QML 端关键的代码

import QtQuick 2.6
import QtQuick.Window 2.0
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.1
import QtMultimedia 5.5
import QZXing 2.3

ApplicationWindow
{
    id: window
    visible: true
    width: 1080
    height: 1920
    title: "Qt QZXing Filter Test"

    property int detectedTags: 0
    property string lastTag: ""
    property  int  nWidth: Math.min(width,height)

    Rectangle
    {
        id: bgRect
        color: "white"
        anchors.fill: videoOutput
    }

    Label
    {
        id: text1
        wrapMode: Text.Wrap
        color:"white"
        z: 50
        text: "Detected count: " + detectedTags
    }

    Camera
    {
        id:camera
        focus {
            focusMode: CameraFocus.FocusContinuous
            focusPointMode: CameraFocus.FocusPointAuto
        }
    }

    VideoOutput
    {
        id: videoOutput
        source: camera
        anchors.fill: parent
        autoOrientation: true
        fillMode: VideoOutput.Stretch
        filters: [ zxingFilter ]
        MouseArea {
            anchors.fill: parent
            onClicked: {
                camera.focus.customFocusPoint = Qt.point(mouse.x / width,  mouse.y / height);
                camera.focus.focusMode = CameraFocus.FocusMacro;
                camera.focus.focusPointMode = CameraFocus.FocusPointCustom;
            }
        }
        Rectangle {
            id: captureZone
            width: nWidth*0.6
            height: width
            anchors.centerIn: parent
            color:"transparent"
            border.color: "lightgreen"
            border.width: 3

            Rectangle{
                id:line
                width: parent.width*0.9
                height: 12
                color: "lightgreen"
                anchors.horizontalCenter: parent.horizontalCenter
                radius: 8

                PropertyAnimation{
                    id:ani
                    target:line
                    properties: "y"
                    duration: 1500
                    from:0
                    running: true
                    to:captureZone.height
                    onStopped: {
                        y=0
                        ani.start()
                    }
                }
            }

        }
    }

    QZXingFilter
    {
        id: zxingFilter
        captureRect: {
            // setup bindings
            videoOutput.contentRect;
            videoOutput.sourceRect;
            //识别的区域,这里稍微比扫描框大一些
            return videoOutput.mapRectToSource(videoOutput.mapNormalizedRectToItem(Qt.rect(
                0.2, 0.2, 0.6, 0.6
            )));
        }

        decoder {
            enabledDecoders: QZXing.DecoderFormat_EAN_13 | QZXing.DecoderFormat_CODE_39 | QZXing.DecoderFormat_QR_CODE

            onTagFound: {
                console.log(tag + " | " + decoder.foundedFormat() + " | " + decoder.charSet());

                window.detectedTags++;
                window.lastTag = tag;
            }

            tryHarder: false
        }

        onDecodingStarted:
        {
            console.log("started");
        }

        property int framesDecoded: 0
        property real timePerFrameDecode: 0

        onDecodingFinished:
        {
           timePerFrameDecode = (decodeTime + framesDecoded * timePerFrameDecode) / (framesDecoded + 1);
           framesDecoded++;
           console.log("frame finished: " + succeeded, decodeTime, timePerFrameDecode, framesDecoded);
        }
    }

    Label
    {
        wrapMode: Text.Wrap
        color:"white"
        anchors.bottom: parent.bottom
        z: 50
        text: "content: " + lastTag
    }
}

权限

在 Android 上运行,开启摄像头需要先添加权限,在 AndroidManifest.xml文件中添加:

<uses-permission android:name="android.permission.CAMERA"/>

关于 QZXing

QML 中用到的二维码解码库,需要去官网下载源码并导入到工程中, 官网:QZXing ,详情请参考官网介绍,这里不再赘述。

源码

鉴于有好几位童鞋遇到问题,在开始玩 GitHub 后,就整理了一份完整的代码,有疑问的可以直接直接下载源码进行编译。
代码地址:https://github.com/luoyayun361/QML-Android-ScanCode
欢迎大家提出自己更好的想法,共同进步和交流。

2017-04-12 14:28:26 weixin_37730482 阅读数 603
  • 微信公众平台深度开发v2.0第3季——二维码、模板消息

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    10262 人正在学习 去看看 翟东平

Android 项目中生成二维码的开源项目主要有,SwetakeQRCode、BarCode4j、Zxing等等。

 

 

 

 

本章节讲述Zxing框架的使用

 

 

代码说明

 

核心代码1:处理扫描结果

	/**
	 * 处理扫描结果
	 * @param result
	 * @param barcode
	 */
	 
	public void handleDecode(Result result, Bitmap barcode) {
		inactivityTimer.onActivity();
		playBeepSoundAndVibrate();
		String resultString = result.getText();
		if (resultString.equals("")) {
			Toast.makeText(MipcaActivityCapture.this, "Scan failed!", Toast.LENGTH_SHORT).show();
		}else {
			Intent resultIntent = new Intent();
			Bundle bundle = new Bundle();
			bundle.putString("result", resultString);
			bundle.putParcelable("bitmap", barcode);
			resultIntent.putExtras(bundle);
			this.setResult(RESULT_OK, resultIntent);
		}
		MipcaActivityCapture.this.finish();
	}

 

 

核心代码2:扫描框

public final class ViewfinderView extends View {
	private static final String TAG = "log";
	/**
	 * 刷新界面的时间
	 */
	private static final long ANIMATION_DELAY = 10L;
	private static final int OPAQUE = 0xFF;

	/**
	 * 四个绿色边角对应的长度
	 */
	private int ScreenRate;
	
	/**
	 * 四个绿色边角对应的宽度
	 */
	private static final int CORNER_WIDTH = 10;
	/**
	 * 扫描框中的中间线的宽度
	 */
	private static final int MIDDLE_LINE_WIDTH = 6;
	
	/**
	 * 扫描框中的中间线的与扫描框左右的间隙
	 */
	private static final int MIDDLE_LINE_PADDING = 5;
	
	/**
	 * 中间那条线每次刷新移动的距离
	 */
	private static final int SPEEN_DISTANCE = 5;
	
	/**
	 * 手机的屏幕密度
	 */
	private static float density;
	/**
	 * 字体大小
	 */
	private static final int TEXT_SIZE = 16;
	/**
	 * 字体距离扫描框下面的距离
	 */
	private static final int TEXT_PADDING_TOP = 30;
	
	/**
	 * 画笔对象的引用
	 */
	private Paint paint;
	
	/**
	 * 中间滑动线的最顶端位置
	 */
	private int slideTop;
	
	/**
	 * 中间滑动线的最底端位置
	 */
	private int slideBottom;
	
	/**
	 * 将扫描的二维码拍下来,这里没有这个功能,暂时不考虑
	 */
	private Bitmap resultBitmap;
	private final int maskColor;
	private final int resultColor;
	
	private final int resultPointColor;
	private Collection<ResultPoint> possibleResultPoints;
	private Collection<ResultPoint> lastPossibleResultPoints;

	boolean isFirst;
	
	public ViewfinderView(Context context, AttributeSet attrs) {
		super(context, attrs);
		
		density = context.getResources().getDisplayMetrics().density;
		//将像素转换成dp
		ScreenRate = (int)(20 * density);

		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<ResultPoint>(5);
	}

	@Override
	public void onDraw(Canvas canvas) {
		//中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改
		Rect frame = CameraManager.get().getFramingRect();
		if (frame == null) {
			return;
		}
		
		//初始化中间线滑动的最上边和最下边
		if(!isFirst){
			isFirst = true;
			slideTop = frame.top;
			slideBottom = frame.bottom;
		}
		
		//获取屏幕的宽和高
		int width = canvas.getWidth();
		int height = canvas.getHeight();

		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 {

			//画扫描框边上的角,总共8个部分
			paint.setColor(Color.GREEN);
			canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate,
					frame.top + CORNER_WIDTH, paint);
			canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top
					+ ScreenRate, paint);
			canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right,
					frame.top + CORNER_WIDTH, paint);
			canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top
					+ ScreenRate, paint);
			canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left
					+ ScreenRate, frame.bottom, paint);
			canvas.drawRect(frame.left, frame.bottom - ScreenRate,
					frame.left + CORNER_WIDTH, frame.bottom, paint);
			canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH,
					frame.right, frame.bottom, paint);
			canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate,
					frame.right, frame.bottom, paint);

			
			//绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCE
			slideTop += SPEEN_DISTANCE;
			if(slideTop >= frame.bottom){
				slideTop = frame.top;
			}
			canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH/2, frame.right - MIDDLE_LINE_PADDING,slideTop + MIDDLE_LINE_WIDTH/2, paint);
			
			
			//画扫描框下面的字
			paint.setColor(Color.WHITE);
			paint.setTextSize(TEXT_SIZE * density);
			paint.setAlpha(0x40);
			paint.setTypeface(Typeface.create("System", Typeface.BOLD));
			canvas.drawText(getResources().getString(R.string.scan_text), frame.left, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint);
			
			

			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);
				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);
				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);
			
		}
	}

	public void drawViewfinder() {
		resultBitmap = null;
		invalidate();
	}

	/**
	 * Draw a bitmap with the result points highlighted instead of the live
	 * scanning display.
	 * 
	 * @param barcode
	 *            An image of the decoded barcode.
	 */
	public void drawResultBitmap(Bitmap barcode) {
		resultBitmap = barcode;
		invalidate();
	}

	public void addPossibleResultPoint(ResultPoint point) {
		possibleResultPoints.add(point);
	}

}

 

 

完整项目代码:https://github.com/wujianning/QrCode

 

2017-08-31 22:04:23 zheglei 阅读数 1229
  • 微信公众平台深度开发v2.0第3季——二维码、模板消息

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    10262 人正在学习 去看看 翟东平

最近项目中需求是类似微信扫描功能,而我的项目是通过扫描所乘班车跟车二维码来进行快捷扫描购票和验票功能;

     1.准备工作

         去github上下载最新的ZXing压缩包,路径https://github.com/zxing/zxing,下载整个项目完成之后目录如下图;

   

   而我们需要的使用到的是红色框中的内容。

  2.  将文件夹android作为工程项目导入studio当中,注意导入的时候需要以   Eclips-ADT的方式导入如下图


导入之后你会发现你的工程会报错,其原因时因为还未添加所需zxing的code的jar包,其实就是之前我们下载的文件夹code当中的内容,但由于studio打jar包比较麻烦,所以我们可以去github下载所需jar包,而下载的时候一定要注意下载3.3.1-SNAPSHOT的code.jar,并且里面有两个3.3.1版本的jar包,我们需要下在3.3.1 20170225.023406.jar这个包。(如果不是下载这个版本,你的项目中的)emailResult.getTos(),emailResult.getCCs(),emailResult.getBCCs(),calendarResult.getStartTimestamp(),

calendarResult.getEndTimestamp()这些方法都会报错,因为低版本时没有这些方法的;
 3.jar包依赖添加成功之后,运行项目会发现提示没有CameraConfigurationUtils这个类,其实这个类直接从我们下载的文件
中的android.code文件夹中将这个类复制到camera包下即可;
到这里你的项目就可以运行起来了,但是运行起来你会发现扫描是横线的,而我们需要的效果往往时竖屏扫描,为了解决这个问题请看我下一篇关于扫描优化的问题。

2016-06-28 11:27:07 zhupengqq 阅读数 714
  • 微信公众平台深度开发v2.0第3季——二维码、模板消息

    “微信公众平台深度开发Java版 v2.0”系列课程共有6季,使用JAVA语言,系统讲解微信公众平台订阅号、服务号官方列出的全部功能接口,包括:自定义菜单、个性化菜单(按需定制菜单)、群发消息、客服消息(有限次消息推送)、模板消息接(无限次消息推送)、微信网页开发(微信WEB开发、微信游戏)、微信JSSDK开发、用户管理、获取用户基本信息、网页授权获取用户基本信息(通过WEB得到用户信息)、二维码(临时二维码、永久二维码)、事件推送、接收普通消息、被动回复用户消息,等知识点。 以及,针对微信公众号开发的服务端架构设计方案。课程以微信公众号开发视角,讲解JAVA开发微信公众号所需的框架、第三方工具。 购买套餐还赠送经典微信开发课程——[微信公众号_独立知识点]环境搭建。该课程针对各种复杂的网络环境,讲解如何构建开发环境,已解决“没有服务器”、“没有固定IP”等开发者遇到的窘境。 课程采用独立知识点讲解,一个知识点,一组课程,真正做到“简单、高效、”以短的时间、实现的学习。更多课程信息请访问CSDN。网址:http://edu.csdn.net/lecturer/631 “微信公众平台企业号开发Java版”陆续上线。 详情 qq2326321088

    10262 人正在学习 去看看 翟东平

Android二维码扫描开发和二维码的生成


下面看完成过程:
1.先导入外界的类库 BarCodeTest

2新建一个项目:
在布局中定义
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/btnscon"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="开始扫描" />

    <TextView
        android:id="@+id/tv1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="show" />
</LinearLayout>
在MainActivity.java中
package com.example.testqrcode;

import java.security.spec.EncodedKeySpec;

import com.google.zxing.WriterException;
import com.zxing.activity.CaptureActivity;
import com.zxing.encoding.EncodingHandler;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;

public class MainActivity extends Activity {
	private Button  scanButton,btngen;
	private TextView   tvshow;
	private EditText    edt1;
	private ImageView  iv1;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		scanButton=(Button) findViewById(R.id.btnscon);
		tvshow=(TextView) findViewById(R.id.tv1);
		scanButton.setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Log.d("MainActivity", "可以扫描二维码了");
				Intent  startSan=new Intent(MainActivity.this,CaptureActivity.class);
				//startActivity(startSan);
				startActivityForResult(startSan, 0);
			}
		});
	}
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		if(resultCode==RESULT_OK){
			String result=data.getExtras().getString("result");
			tvshow.setText(result);
		}
	}
}
另外这个CaptureActivity.class是外部的类,所以要在 AndroidManifest.xml中定义
找到BarCodeTest的AndroidManifest.xml,会发现有这样一段话
 <activity
            android:configChanges="orientation|keyboardHidden"
            android:name="com.zxing.activity.CaptureActivity"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
            android:windowSoftInputMode="stateAlwaysHidden" >
        </activity>
把这个类的声明复制到你的项目中去

运行之后,会出现这样,反馈的信息


那么怎么根据输入的值生成一个二维码呢?
在布局中定义:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <EditText
        android:id="@+id/edt1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="请输入要编码的内容" >
    </EditText>

    <Button
        android:id="@+id/btngen"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="生成二维码" />

    <ImageView
        android:id="@+id/iv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_gravity="center_horizontal"
        />

</LinearLayout>
在MainActivity.java中

package com.example.testqrcode;

import java.security.spec.EncodedKeySpec;

import com.google.zxing.WriterException;
import com.zxing.activity.CaptureActivity;
import com.zxing.encoding.EncodingHandler;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;

public class MainActivity extends Activity {
	private Button  scanButton,btngen;
	private TextView   tvshow;
	private EditText    edt1;
	private ImageView  iv1;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		tvshow=(TextView) findViewById(R.id.tv1);
		btngen=(Button) findViewById(R.id.btngen);
		edt1=(EditText) findViewById(R.id.edt1);
		iv1=(ImageView) findViewById(R.id.iv1);
		btngen.setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				String in=edt1.getText().toString();
				if(in.equals("")){
					Log.d("MainActivity", "请输入文本");
				}
				try {					
					Bitmap  qrcode=EncodingHandler.createQRCode(in, 400);
					iv1.setImageBitmap(qrcode);
				} catch (WriterException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});
	}
}
生成的二维码会放在定义的ImgeView里(这里是放在ImgeView,当然你可以根据你项目的需求,放在自己 想放的地方,方便我们灵活运用


Android二维码扫描

阅读数 5566

没有更多推荐了,返回首页