• Android二维码开源项目zxing用例简化和生成二维码、条形码


    上一篇讲到:Android二维码开源项目zxing编译,编译出来后有一个自带的測试程序:CaptureActivity比較复杂,我仅仅要是把一些不用的东西去掉,用看起来更方便,二维码和条形码的流行性自不必说了。

    自带的样例,文件夹结构例如以下:


    改动后的程序文件夹结构,去掉了非常多功能,假设分享、设置等。


    先上效果图

            

    扫描ZXing生成的条形码和二维码结果



    扫描界面


    扫描商品的条码


    整个程序仅仅改动了下面两个类,其他都是直接从原来的Demo中复制出来的


    生成二维码的代码

    /**
    	 * 生成二维码 要转换的地址或字符串,能够是中文
    	 * 
    	 * @param url
    	 * @param width
    	 * @param height
    	 * @return
    	 */
    	public Bitmap createQRImage(String url, final int width, final int height) {
    		try {
    			// 推断URL合法性
    			if (url == null || "".equals(url) || url.length() < 1) {
    				return null;
    			}
    			Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
    			hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
    			// 图像数据转换,使用了矩阵转换
    			BitMatrix bitMatrix = new QRCodeWriter().encode(url,
    					BarcodeFormat.QR_CODE, width, height, hints);
    			int[] pixels = new int[width * height];
    			// 以下这里依照二维码的算法,逐个生成二维码的图片,
    			// 两个for循环是图片横列扫描的结果
    			for (int y = 0; y < height; y++) {
    				for (int x = 0; x < width; x++) {
    					if (bitMatrix.get(x, y)) {
    						pixels[y * width + x] = 0xff000000;
    					} else {
    						pixels[y * width + x] = 0xffffffff;
    					}
    				}
    			}
    			// 生成二维码图片的格式,使用ARGB_8888
    			Bitmap bitmap = Bitmap.createBitmap(width, height,
    					Bitmap.Config.ARGB_8888);
    			bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    			return bitmap;
    		} catch (WriterException e) {
    			e.printStackTrace();
    		}
    		return null;
    	}
    
    能够生成中文


    生成条形码关键代码,下面代码是把条形码和条形码下的文字合并成一张图片显示。

    /**
    	 * 生成条形码
    	 * 
    	 * @param context
    	 * @param contents
    	 *            须要生成的内容
    	 * @param desiredWidth
    	 *            生成条形码的宽带
    	 * @param desiredHeight
    	 *            生成条形码的高度
    	 * @param displayCode
    	 *            是否在条形码下方显示内容
    	 * @return
    	 */
    	public static Bitmap creatBarcode(Context context, String contents,
    			int desiredWidth, int desiredHeight, boolean displayCode) {
    		Bitmap ruseltBitmap = null;
    		/**
    		 * 图片两端所保留的空白的宽度
    		 */
    		int marginW = 20;
    		/**
    		 * 条形码的编码类型
    		 */
    		BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;
    
    		if (displayCode) {
    			Bitmap barcodeBitmap = encodeAsBitmap(contents, barcodeFormat,
    					desiredWidth, desiredHeight);
    			Bitmap codeBitmap = creatCodeBitmap(contents, desiredWidth + 2
    					* marginW, desiredHeight, context);
    			ruseltBitmap = mixtureBitmap(barcodeBitmap, codeBitmap, new PointF(
    					0, desiredHeight));
    		} else {
    			ruseltBitmap = encodeAsBitmap(contents, barcodeFormat,
    					desiredWidth, desiredHeight);
    		}
    
    		return ruseltBitmap;
    	}
    
    	/**
    	 * 生成条形码的Bitmap
    	 * 
    	 * @param contents
    	 *            须要生成的内容
    	 * @param format
    	 *            编码格式
    	 * @param desiredWidth
    	 * @param desiredHeight
    	 * @return
    	 * @throws WriterException
    	 */
    	protected static Bitmap encodeAsBitmap(String contents,
    			BarcodeFormat format, int desiredWidth, int desiredHeight) {
    		final int WHITE = 0xFFFFFFFF;
    		final int BLACK = 0xFF000000;
    
    		MultiFormatWriter writer = new MultiFormatWriter();
    		BitMatrix result = null;
    		try {
    			result = writer.encode(contents, format, desiredWidth,
    					desiredHeight, null);
    		} catch (WriterException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    		int width = result.getWidth();
    		int height = result.getHeight();
    		int[] pixels = new int[width * height];
    		// All are 0, or black, by default
    		for (int y = 0; y < height; y++) {
    			int offset = y * width;
    			for (int x = 0; x < width; x++) {
    				pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
    			}
    		}
    
    		Bitmap bitmap = Bitmap.createBitmap(width, height,
    				Bitmap.Config.ARGB_8888);
    		bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    		return bitmap;
    	}
    
    	/**
    	 * 生成显示编码的Bitmap
    	 * 
    	 * @param contents
    	 * @param width
    	 * @param height
    	 * @param context
    	 * @return
    	 */
    	protected static Bitmap creatCodeBitmap(String contents, int width,
    			int height, Context context) {
    		TextView tv = new TextView(context);
    		LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
    				LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    		tv.setLayoutParams(layoutParams);
    		tv.setText(contents);
    		tv.setHeight(height);
    		tv.setGravity(Gravity.CENTER_HORIZONTAL);
    		tv.setWidth(width);
    		tv.setDrawingCacheEnabled(true);
    		tv.setTextColor(Color.BLACK);
    		tv.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
    				MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
    		tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
    
    		tv.buildDrawingCache();
    		Bitmap bitmapCode = tv.getDrawingCache();
    		return bitmapCode;
    	}
    
    	/**
    	 * 将两个Bitmap合并成一个
    	 * 
    	 * @param first
    	 * @param second
    	 * @param fromPoint
    	 *            第二个Bitmap開始绘制的起始位置(相对于第一个Bitmap)
    	 * @return
    	 */
    	protected static Bitmap mixtureBitmap(Bitmap first, Bitmap second,
    			PointF fromPoint) {
    		if (first == null || second == null || fromPoint == null) {
    			return null;
    		}
    		int marginW = 20;
    		Bitmap newBitmap = Bitmap.createBitmap(
    				first.getWidth() + second.getWidth() + marginW,
    				first.getHeight() + second.getHeight(), Config.ARGB_4444);
    		Canvas cv = new Canvas(newBitmap);
    		cv.drawBitmap(first, marginW, 0, null);
    		cv.drawBitmap(second, fromPoint.x, fromPoint.y, null);
    		cv.save(Canvas.ALL_SAVE_FLAG);
    		cv.restore();
    
    		return newBitmap;
    	}
    CaptureActivity.java是扫描二维码和条形码的界面,对Camera进行初始化和开启扫描线程

    private void initCamera(SurfaceHolder surfaceHolder) {
    		if (surfaceHolder == null) {
    			throw new IllegalStateException("No SurfaceHolder provided");
    		}
    		if (cameraManager.isOpen()) {
    			ZXingApplication
    					.print_i("CaptureActivity",
    							"initCamera() while already open -- late SurfaceView callback?");
    			return;
    		}
    
    		try {
    			cameraManager.openDriver(surfaceHolder);
    		} catch (IOException ioe) {
    			return;
    		} catch (RuntimeException e) {
    			return;
    		}
    		if (handler == null) {
    			handler = new CaptureActivityHandler(this, decodeFormats,
    					decodeHints, characterSet, cameraManager);
    		}
    		ZXingApplication.print_i("CaptureActivity",
    				"initCamera-----------finish");
    	}
    在CaptureActivityHandler.java类中会处理扫描的结果

    @Override
    	public void handleMessage(Message message) {
    		switch (message.what) {
    		case R.id.restart_preview:
    			restartPreviewAndDecode();
    			break;
    		case R.id.decode_succeeded:
    			state = State.SUCCESS;
    			Bundle bundle = message.getData();
    			Bitmap barcode = null;
    			float scaleFactor = 1.0f;
    			if (bundle != null) {
    				byte[] compressedBitmap = bundle
    						.getByteArray(DecodeThread.BARCODE_BITMAP);
    				if (compressedBitmap != null) {
    					barcode = BitmapFactory.decodeByteArray(compressedBitmap,
    							0, compressedBitmap.length, null);
    					// Mutable copy:
    					barcode = barcode.copy(Bitmap.Config.ARGB_8888, true);
    				}
    				scaleFactor = bundle
    						.getFloat(DecodeThread.BARCODE_SCALED_FACTOR);
    			}
    			activity.handleDecode((Result) message.obj, barcode, scaleFactor);
    			break;
    		case R.id.decode_failed:
    			// We're decoding as fast as possible, so when one decode fails,
    			// start another.
    			state = State.PREVIEW;
    			cameraManager.requestPreviewFrame(decodeThread.getHandler(),
    					R.id.decode);
    			break;
    		case R.id.return_scan_result:
    			activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
    			activity.finish();
    			break;
    		case R.id.launch_product_query:
    			String url = (String) message.obj;
    
    			Intent intent = new Intent(Intent.ACTION_VIEW);
    			intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
    			intent.setData(Uri.parse(url));
    
    			ResolveInfo resolveInfo = activity.getPackageManager()
    					.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
    			String browserPackageName = null;
    			if (resolveInfo != null && resolveInfo.activityInfo != null) {
    				browserPackageName = resolveInfo.activityInfo.packageName;
    				Log.d(TAG, "Using browser in package " + browserPackageName);
    			}
    
    			// Needed for default Android browser / Chrome only apparently
    			if ("com.android.browser".equals(browserPackageName)
    					|| "com.android.chrome".equals(browserPackageName)) {
    				intent.setPackage(browserPackageName);
    				intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    				intent.putExtra(Browser.EXTRA_APPLICATION_ID,
    						browserPackageName);
    			}
    
    			try {
    				activity.startActivity(intent);
    			} catch (ActivityNotFoundException ignored) {
    				Log.w(TAG, "Can't find anything to handle VIEW of URI " + url);
    			}
    			break;
    		}
    	}
    在case R.id.decode_succeeded 分支会通过activity.handleDecode((Result) message.obj, barcode, scaleFactor);回传结果给Activity

    /**
    	 * A valid barcode has been found, so give an indication of success and show
    	 * the results.
    	 * 
    	 * @param rawResult
    	 *            The contents of the barcode.
    	 * @param scaleFactor
    	 *            amount by which thumbnail was scaled
    	 * @param barcode
    	 *            A greyscale bitmap of the camera data which was decoded.
    	 */
    	public void handleDecode(final Result rawResult, Bitmap barcode,
    			float scaleFactor) {
    		inactivityTimer.onActivity();
    		// ResultHandler resultHandler = ResultHandlerFactory.makeResultHandler(
    		// this, rawResult);
    
    		boolean fromLiveScan = barcode != null;
    		AlertDialog.Builder dialog = new AlertDialog.Builder(this);
    		if (barcode == null) {
    			dialog.setIcon(null);
    		} else {
    
    			Drawable drawable = new BitmapDrawable(barcode);
    			dialog.setIcon(drawable);
    		}
    		dialog.setTitle("扫描结果");
    		dialog.setMessage(rawResult.getText());
    		dialog.setNegativeButton("确定", new DialogInterface.OnClickListener() {
    			@Override
    			public void onClick(DialogInterface dialog, int which) {
    				// 用默认浏览器打开扫描得到的地址
    				Intent intent = new Intent();
    				intent.setAction("android.intent.action.VIEW");
    				Uri content_url = Uri.parse(rawResult.getText());
    				intent.setData(content_url);
    				startActivity(intent);
    				finish();
    			}
    		});
    		dialog.setPositiveButton("取消", new DialogInterface.OnClickListener() {
    			@Override
    			public void onClick(DialogInterface dialog, int which) {
    				finish();
    			}
    		});
    		dialog.create().show();
    	}
    这里仅仅是把扫描的结果显示出来,实际上能够依据不同的须要来处理,假设扫描出二维码能够用HTTP来打开,有一点要注意的,我的ADT版本号是V23.0.2.1259578,须要执行的4.0的系统上

    演示样例代码:http://download.csdn.net/detail/deng0zhaotai/7696615


  • 相关阅读:
    flink checkpoint机制的实现
    openjdk源码分析之AtomicLong
    cpp之宏和函数调用约定
    JNA 相关问题
    spark RDD
    最长连续序列
    买卖股票的最佳时机
    二叉树展开为链表
    不同的二叉搜索树
    柱状图中最大的矩形
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4067077.html
Copyright © 2020-2023  润新知