`
longgangbai
  • 浏览: 7325360 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

         在企业应用中可能某一些情况,需要二维码扫码,大多数采用的开源组件zxing实现。简介
      最近的Widget项目用到需要用摄像头来处理条形码,章师兄推荐了ZXing这个开源的项目,于是做一简单的调研。
ZXing是一个开源Java类库用于解析多种格式的1D/2D条形码。目标是能够对QR编码、Data Matrix、UPC的1D条形码进行解码。 其提供了多种平台下的客户端包括:J2ME、J2SE和Android。
当前,ZXing主要支持以下条形码:
UPC-A and UPC-E
EAN-8 and EAN-13
Code 39
Code 128
QR Code
Data Matrix ('alpha' quality)
ITF
       首先,在http://code.google.com/p/zxing/上下载到ZXing的应用程序包,解压下载到的程序包后,我们可以看到整个应用程序分为一些组件。如下:
1.core: 核心包,是整个应用的主要组件组成部分。
2.javame: 为JavaME来定制的客户端工具。
3.javase: 为PC端定制的客户端工具。
4.android: 为Android端定制的客户端工具。
5.androidtest: Android测试应用程序,里面有在其它程序中使用此应用的示例。
基本测试
     ZXing程序的运行需要我们使用Ant去打包编译之后才可。在这里,我主要调研了在PC端,在WTK上及android上的运行。

 

各种语言zxing的实现路径:

http://zxing.googlecode.com/svn

源代码svn路径:

http://code.google.com/p/zxing/downloads/list

zxing APK路径:

http://zxing.googlecode.com/files/BarcodeScanner4.1.apk

zxing和应用整合官方代码:

http://zxing.googlecode.com/svn/trunk/android-integration

 

 

方法一:整合为一个项目:

前言

  最近公司的Android项目需要用到摄像头做条码或二维码的扫描,Google一下,发现一个以Apache License 2.0 开源的 ZXing项目。Zxing项目里的Android实现太过复杂多余东西太多,得对其进行简化。

前提条件

  下载源代码:点击这里

  编译核心库:Zxing的主页上有介绍具体步骤,大家也可以参照这篇博文:android 条码识别软件开发全解析(续2详解绝杀!)

导入项目

  打开Eclipse 导入 源码中的 Android 项目,然后右击项目 选择“Build path”——》"Add External Archives" 把核心库 core.jar文件加入到项目中。

此时编译一下项目,会发现报错,“ Multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?”之类的。打开raw 下的Values 发现错误是在一个<String>上。这里把 “preferences_custom_product_search_summary” 里的  %s  %f  全部都改成  %1$s  %1$f(因为我们用不到多国语言,建议只保留默认的Value ,其他全部删除)。

  原因:由于新的SDK采用了新版本的aapt(Android项目编译器),这个版本的aapt编译起来会比老版本更加的严格,然后在Android最新的开发文档的描述String的部分,已经说明如何去设置 %s 等符号

  “If you need to format your strings using String.format(String, Object...) , then you can do so by putting your format arguments in the string resource. For example, with the following resource:

  <string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

  In this example, the format string has two arguments: %1$s is a string and %2$d is a decimal number. You can format the string with arguements from your application...“

  经过以上步骤后项目应该就可以运行了。

  但是ZXing的android项目东西太多了,有很多是我们不需要的,得新建另一个项目简化它。

简化

  在开始前大致介绍一下简化ZXing需要用到各个包 、类的职责。

  • CaptureActivity。这个是启动Activity 也就是扫描器(如果是第一安装,它还会跳转到帮助界面)。
  • CaptureActivityHandler 解码处理类,负责调用另外的线程进行解码。
  • DecodeThread 解码的线程。
  • com.google.zxing.client.android.camera 包,摄像头控制包。
  • ViewfinderView 自定义的View,就是我们看见的拍摄时中间的框框了。

新建另一个项目

  新建另一个项目将启动的Activity命名为CaptureActivity,并导入核心库。项目新建完成后我们打开 CaptureActivity 的布局文件,我这里为main。把里面的XML修改为:

复制代码
1 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
2 android:layout_width="fill_parent" android:layout_height="fill_parent">
3 <SurfaceView android:id="@+id/preview_view"
4 android:layout_width="fill_parent" android:layout_height="fill_parent"
5 android:layout_centerInParent="true"/>
6
7 <com.Zxing.Demo.view.ViewfinderView
8 android:id="@+id/viewfinder_view" android:layout_width="fill_parent"
9 android:layout_height="fill_parent" android:background="@android:color/transparent"/>
10 <TextView android:layout_width="wrap_content"
11 android:id="@+id/txtResult"
12 android:layout_height="wrap_content" android:text="@string/hello"/>
13
14  </FrameLayout>
复制代码

  可以看到在XML里面用到了 ViewfinderView 自定义view 。所以新建一个View 的包,然后把:ViewfinderView 和 ViewfinderResultPointCallback 靠到里面(记得对应修改XML里面的包)。

打开 CaptureActivity 覆盖 onCreate 方法:

复制代码
1 @Override
2 publicvoid onCreate(Bundle savedInstanceState) {
3 super.onCreate(savedInstanceState);
4 setContentView(R.layout.main);
5 //初始化 CameraManager
6   CameraManager.init(getApplication());
7
8 viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);
9 txtResult = (TextView) findViewById(R.id.txtResult);
10 hasSurface =false;
11 inactivityTimer =new InactivityTimer(this);
12 }
复制代码

  这里调用到的 CameraManager 类是控制摄像头的包里的类。新建一个camera包把:com.google.zxing.client.android.camera 里面的类全部拷入,另外我把PlanarYUVLuminanceSource也拷入到这个包里面。根据错误的提示来修正代码,主要是修改正包结构。(整个简化的流程都是如此:“根据错误提示,修改代码”)。

  在修改的过程中,有很多是关于R 资源的问题,在此我们需要将Values  里面的两个xml资源文件拷入项目中:colos.xml 和ids.xml 。 ctrl+b 一下看看error 是不是少了很多。在CameraManager中有些地方需要用到项目的配置,这里需要把配置直接写入代码中:

// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
//是否使用前灯
// if (prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false)) {
// FlashlightManager.enableFlashlight();
// }
FlashlightManager.enableFlashlight();

   使用摄像头需要加入相应的权限:

<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<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.FLASHLIGHT"/>

  当View 和 camera 包里的错误修正完成后,我们继续来看CaptureActivity。

覆盖onResume方法初始化摄像头:

复制代码
@Override
protectedvoid onResume() {
super.onResume();
SurfaceView surfaceView
= (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder
= surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
}
else {
surfaceHolder.addCallback(
this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats
=null;
characterSet
=null;

playBeep
=true;
AudioManager audioService
= (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep
=false;
}
initBeepSound();
vibrate
=true;
}
复制代码
initCamera
1 privatevoid initCamera(SurfaceHolder surfaceHolder) {
2 try {
3 CameraManager.get().openDriver(surfaceHolder);
4 } catch (IOException ioe) {
5 return;
6 } catch (RuntimeException e) {
7 return;
8 }
9 if (handler ==null) {
10 handler =new CaptureActivityHandler(this, decodeFormats,
11 characterSet);
12 }
13 }
SurfaceHolder接口实现
@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

}

@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface
=true;
initCamera(holder);
}

}

@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
hasSurface
=false;

}

initCamera () 方法用于初始化摄像头,如果排除了所有的error ,运行项目时就可以看到大致扫描界面了。 surfaceHolder.addCallback(this);表示让CaptureActivity实现其callback接口。

handler = new CaptureActivityHandler(this, decodeFormats,characterSet) 用于进行扫描解码处理。

解码

  上面的步骤主要都是用于对摄像头的控制,而解码的真正工作入口是在CaptureActivityHandler 里面的。新建一个Decoding包把以下文件拷入包中:

  • CaptureActivityHandler
  • DecodeFormatManager
  • DecodeHandler
  • DecodeThread
  • FinishListener
  • InactivityTimer
  • Intents

由于我们的包结构和Zxing 项目的有所不同所以需要注意一下类的可访问性

同样开始ctrl+B 编译一下,然后开始修正错误。

  在CaptureActivityHandler 里 把 handleMessage 里的部分方法先注释掉如:“decode_succeeded ”分支,这是解码成功时调用 CaptureActivity 展示解码的结果。

在DecodeThread 类里,修改部分涉及Preference配置的代码:

复制代码
DecodeThread(CaptureActivity activity,
Vector
<BarcodeFormat> decodeFormats,
String characterSet,
ResultPointCallback resultPointCallback) {

this.activity = activity;
handlerInitLatch
=new CountDownLatch(1);

hints
=new Hashtable<DecodeHintType, Object>(3);

//// The prefs can't change while the thread is running, so pick them up once here.
// if (decodeFormats == null || decodeFormats.isEmpty()) {
// SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
// decodeFormats = new Vector<BarcodeFormat>();
// if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_1D, true)) {
// decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
// }
// if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_QR, true)) {
// decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
// }
// if (prefs.getBoolean(PreferencesActivity.KEY_DECODE_DATA_MATRIX, true)) {
// decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);
// }
// }
if (decodeFormats ==null|| decodeFormats.isEmpty()) {
decodeFormats
=new Vector<BarcodeFormat>();
decodeFormats.addAll(DecodeFormatManager.ONE_D_FORMATS);
decodeFormats.addAll(DecodeFormatManager.QR_CODE_FORMATS);
decodeFormats.addAll(DecodeFormatManager.DATA_MATRIX_FORMATS);

}

hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);

if (characterSet !=null) {
hints.put(DecodeHintType.CHARACTER_SET, characterSet);
}

hints.put(DecodeHintType.NEED_RESULT_POINT_CALLBACK, resultPointCallback);
}
复制代码

这里是设置 解码的类型,我们现在默认将所有类型都加入。

错误类型基本上都是:包结构、PreferencesActivity 的配置 、类可访问性的问题。根据错误提示耐心把错误解决。

返回解码结果

   还记得在 CaptureActivityHandler 的 messagehandler 里注销掉的Case分支吗?现在CaptureActivity 里实现它。

复制代码
publicvoid handleDecode(Result obj, Bitmap barcode) {
inactivityTimer.onActivity();
viewfinderView.drawResultBitmap(barcode);
playBeepSoundAndVibrate();
txtResult.setText(obj.getBarcodeFormat().toString()
+":"
+ obj.getText());
}
复制代码

最后

  ZXing的简化已基本完成,有几位是可以运行成功的?呵呵。

下面是CaptureActivity的源码:

CaputreActivity
publicclass CaptureActivity extends Activity implements Callback {

private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
privateboolean hasSurface;
private Vector<BarcodeFormat> decodeFormats;
private String characterSet;
private TextView txtResult;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
privateboolean playBeep;
privatestaticfinalfloat BEEP_VOLUME =0.10f;
privateboolean vibrate;

/** Called when the activity is first created. */
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//初始化 CameraManager
CameraManager.init(getApplication());

viewfinderView
= (ViewfinderView) findViewById(R.id.viewfinder_view);
txtResult
= (TextView) findViewById(R.id.txtResult);
hasSurface
=false;
inactivityTimer
=new InactivityTimer(this);
}

@Override
protectedvoid onResume() {
super.onResume();
SurfaceView surfaceView
= (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder
= surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
}
else {
surfaceHolder.addCallback(
this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats
=null;
characterSet
=null;

playBeep
=true;
AudioManager audioService
= (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep
=false;
}
initBeepSound();
vibrate
=true;
}

@Override
protectedvoid onPause() {
super.onPause();
if (handler !=null) {
handler.quitSynchronously();
handler
=null;
}
CameraManager.get().closeDriver();
}

@Override
protectedvoid onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}

privatevoid initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
}
catch (IOException ioe) {
return;
}
catch (RuntimeException e) {
return;
}
if (handler ==null) {
handler
=new CaptureActivityHandler(this, decodeFormats,
characterSet);
}
}

@Override
publicvoid surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {

}

@Override
publicvoid surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface
=true;
initCamera(holder);
}

}

@Override
publicvoid surfaceDestroyed(SurfaceHolder holder) {
hasSurface
=false;

}

public ViewfinderView getViewfinderView() {
return viewfinderView;
}

public Handler getHandler() {
return handler;
}

publicvoid drawViewfinder() {
viewfinderView.drawViewfinder();

}

publicvoid handleDecode(Result obj, Bitmap barcode) {
inactivityTimer.onActivity();
viewfinderView.drawResultBitmap(barcode);
playBeepSoundAndVibrate();
txtResult.setText(obj.getBarcodeFormat().toString()
+":"
+ obj.getText());
}

privatevoid initBeepSound() {
if (playBeep && mediaPlayer ==null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer
=new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener);

AssetFileDescriptor file
= getResources().openRawResourceFd(
R.raw.beep);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
}
catch (IOException e) {
mediaPlayer
=null;
}
}
}

privatestaticfinallong VIBRATE_DURATION =200L;

privatevoid playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer !=null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator
= (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
}

/**
* When the beep has finished playing, rewind to queue up another one.
*/
privatefinal OnCompletionListener beepListener =new OnCompletionListener() {
publicvoid onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(
0);
}
};

简化过的包结构图:

 

 简化后的ZXing 更加方便我们了解ZXing项目 是如何解码的。只要仔细查看源码,进行单点跟踪调试,相信大家很容易能理解。

顾客是上帝

   很多人留言要源码, 其实我这不是什么源码,我只是把ZXing的东西简化了一下而已。事实上我也不喜欢直接放源码项目,这样大家就不想读ZXing的源码了。

下面是我简化的版本:Zxing简化

很多人需要Core 核心包(其实ZXing的源码里面就有),这里提供下我写文章时的版本 1.6的:

Zxing

 

方法二:分别为两个项目:

 

 

测试代码如下:

package com.easyway.android;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
/**
 * 二维码扫码应用实例
 * 
 * 1.安装zxing客户端android apk。
 * 2.调用相关的zxing
 * 3.获取相关的执行的结果
 * 
 * 如何扫描条形码
 *		现在做条形码扫描,java一般用zxing。zxing有多种复用方式,最简单的方式是,
 *安装zxing软件,通过google market。在自己的应用中,通过Intent调用zxing的扫描条码的Activity,
 *然后将扫描到的结果返回自己的Activity。
 *比较复杂的办法是,将zxing库包含在自己的程序中,这比较适合正式的应用。
 * @Title: 
 * @Description: 实现TODO
 * @Copyright:Copyright (c) 2011
 * @Company:易程科技股份有限公司
 * @Date:2012-5-9
 * @author  longgangbai
 * @version 1.0
 */
public class AndroidScanBarcodeActivity extends Activity implements OnClickListener {

	private Button button;

	private TextView textView;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		this.button = (Button) this.findViewById(R.id.btnscan);
		this.button.setOnClickListener(this);
		this.textView = (TextView) this.findViewById(R.id.txtScan);
	}

	@Override
	public void onClick(View view) {
		//调用对应的扫描方法
		Intent intent = new Intent("com.google.zxing.client.android.SCAN");
		this.startActivityForResult(intent, 0);
	}

	/**
	 * 获取扫描的结果
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
		if (requestCode != 0) {
			this.textView.setText(R.string.noresult);
			return;
		}
		if(resultCode==RESULT_OK){
			String contents = intent.getStringExtra("SCAN_RESULT");
			String format = intent.getStringExtra("SCAN_RESULT_FORMAT");
			textView.setText(" 条形码为:"+contents+" 条码类型为: "+format);//利用页面的textveiw显示扫描后的结果                            } else if (resultCode == RESULT_CANCELED) {
		}
	}
}

 

 

源代码下载:

 

分享到:
评论
1 楼 同一片天空 2012-06-08  
恩不错

相关推荐

    Android二维码扫码源码

    这个"Android二维码扫码源码"提供了一种实现这一功能的方式,它不仅支持扫描二维码(QR Code),还支持一维条形码的识别。接下来,我们将深入探讨相关知识点。 1. **二维码与一维条形码**: - 二维码:二维码是一...

    Android 二维码扫码

    这个"Android二维码扫码升级版"显然优化了性能,提高了扫描速度,使得用户体验更加便捷,用户可以直接复制并粘贴扫描结果,大大提升了操作效率。 首先,我们要了解二维码的基本原理。二维码(Quick Response Code)...

    ZBar二维码扫码库

    总的来说,ZBar二维码扫码库凭借其高效的C++实现、跨平台特性以及优秀的扫码速度,成为开发者在构建二维码相关应用时的重要选择。通过理解和熟练运用这个库,开发者可以快速构建出功能完善的扫码功能,提升应用的...

    全Delphi代码实现的安卓二维码扫码

    本项目聚焦于使用全Delphi代码实现的安卓二维码扫码功能,旨在提供一个高效、流畅的解决方案,特别强调在扫码过程中不卡顿的用户体验。 首先,我们要理解二维码(Quick Response Code)是一种二维条形码,能够存储...

    二维码扫码Demo二维码扫码Demo.zip

    在Android和iOS平台上,都有相应的SDK或库支持二维码扫码功能。例如,Google的ZXing库(Zebra Crossing)提供了跨平台的二维码处理能力。开发者可以通过集成这些库,实现扫描器界面的创建、扫描回调接口的设置以及...

    QrCodeScan-master.zip_android 二维码扫码_nightbit_二维码_安卓_扫描二维码

    《安卓手机二维码扫码技术详解》 在移动应用开发领域,二维码扫描已经成为不可或缺的功能之一,尤其在安卓平台上。本文将深入探讨如何在Android设备上利用摄像头实现二维码的扫描与识别,结合"QrCodeScan-master....

    二维码扫码,简单易用

    二维码扫码技术在现代移动应用中广泛应用,无论是支付、信息获取还是广告推广,都离不开它的身影。本教程将深入探讨二维码扫码的基本原理、实现方法以及如何在应用中集成扫码功能,让开发者能够快速理解和掌握。 ...

    二维码扫码代码

    二维码扫码技术在现代移动应用中扮演着至关重要的角色,它为数据交换提供了便捷的方式。"二维码扫码代码"这个实例展示了如何实现一个自定义的扫码界面,使得用户可以在应用程序中轻松扫描并解析二维码。ZxingTest2...

    Android 扫描二维码,类似微信的不断放大扫描效果, 识别率高。

    Android中常用的库有Zxing(ZXing,全称为“Zebra Crossing”),这是一个开源的二维码和条形码解码框架。在项目中,我们可以引入google_zxing库,它是Zxing的一个分支,提供了更稳定的版本和更新。使用Zxing,我们...

    Android 二维码扫一扫demo

    在Android平台上,开发一款二维码扫一扫的应用程序是一项常见的需求。这里我们关注的是一个名为"Android 二维码扫一扫demo"的项目,它使用了ZXing(Zebra Crossing)库来实现这一功能。ZXing是一个开源的条码读取库...

    android Zxing扫描二维码条形码功能仿微信自定义扫码框扫描线边框样式Android studio版本

    在这个项目中,我们将讨论如何在Android Studio环境下,利用Zxing库来实现一个仿微信的自定义扫码框,带有动态扫描线和边框样式的扫描界面。 首先,你需要在你的Android项目中添加Zxing依赖。在`build.gradle` ...

    Android利用ZBar实现二维码、条形码扫码实例

    在Android应用开发中,有时我们需要集成二维码和条形码扫描功能,这在移动支付、信息交换等场景中非常常见。ZBar是一个强大的开源库,它提供了读取多种条码格式的能力,包括一维条形码(如EAN-13、UPC-A)和二维条码...

    Android二维码扫描Demo 程序源码

    在Activity或Fragment中初始化扫码器,创建一个CaptureActivity或ScannerFragment类,继承自ZXing的CaptureActivity或BaseCaptureActivity,并重写其相关方法。 4. **权限请求**: 因为需要访问摄像头,所以必须...

    Zbar二维码扫码so

    总的来说,这个Zbar二维码扫码SO文件是一个优化过的、适用于Android的二维码识别库,它具有快速扫描和兼容高版本Android系统的特性,可以方便地集成到各种需要二维码扫描功能的Android应用中,提升用户体验并简化...

    前置摄像头的android二维码扫描demo

    总的来说,这个"前置摄像头的android二维码扫描demo"项目涵盖了Android应用开发中的多个核心概念,包括摄像头操作、权限管理、用户界面设计、事件处理以及性能优化。通过学习和理解这个项目,开发者可以更好地掌握...

    二维码扫码器

    二维码扫码器是一款基于二维码识别技术的应用程序,它能够读取并解析各种类型的二维码,从而实现数据的快速交换和处理。二维码技术在当今信息化社会中广泛应用,如产品追溯、电子支付、网页链接、名片交换等场景。这...

    Delphi与Android二维码识别应用演示

    "Delphi与Android二维码识别应用演示"旨在展示如何利用Delphi的跨平台能力,实现在Android设备上扫描并解析二维码的功能。 【描述】:这个项目的核心在于,它提供了一个实例,说明了Delphi开发者如何利用特定的库和...

    实现二维码扫码源码

    二维码扫码技术在现代移动应用中扮演着至关重要的角色,它为快速传递信息、链接网络资源提供了便捷的方式。本文将深入探讨如何实现一个二维码扫码程序,包括核心原理、库的使用以及编码与解码过程。 首先,我们需要...

    android Zxing扫描二维码条形码功能仿微信自定义扫码框扫描线边框样式Eclipse版本

    在Android开发中,集成二维码和条形码扫描功能是一项常见的需求。Zxing(又称为ZXing,意为“快速...通过以上步骤,你可以在你的Android应用中实现一个功能完备且用户体验良好的二维码和条形码扫描功能,就像微信那样。

Global site tag (gtag.js) - Google Analytics