android 利用ZXING扫描二维码代码分析

之前给公司做了一个摄影相关的应用,现在要添加二维码扫描的功能,网上找资料后,虽然已经成功集成到app里面,但是总感觉心里没底儿。所以趁这段时间不是很忙,总结一下。

首先是启动扫描的UI类:

1,Activity启动,当然是onCreate方法





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

private CaptureActivityHandler handler;

private ViewfinderView viewfinderView;

private boolean hasSurface;

private Vector<BarcodeFormat> decodeFormats;

private String characterSet;

private InactivityTimer inactivityTimer;

private MediaPlayer mediaPlayer;

private boolean playBeep;

private static final float BEEP_VOLUME = 0.10f;

private
boolean vibrate;

/** Called when the activity is first created. */

@Override

public
void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_capture);

    // ViewUtil.addTopView(getApplicationContext(), this,

    // R.string.scan_card);

    CameraManager.init(getApplication());

    viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view);

    Button mButtonBack = (Button) findViewById(R.id.button_back);

    mButtonBack.setOnClickListener(new
OnClickListener() {

        @Override

        public
void onClick(View v) {

            Scaner.this.finish();

        }

    });

    hasSurface = false;

    inactivityTimer = new
InactivityTimer(this);

}

@Override

protected
void 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

protected
void onPause() {

    super.onPause();

    if
(handler != null) {

        handler.quitSynchronously();

        handler = null;

    }

    CameraManager.get().closeDriver();

}

@Override

protected
void onDestroy() {

    inactivityTimer.shutdown();

    super.onDestroy();

}

/**

 *

*

*

* @param @param result

* @param @param barcode

* @author  Administrator

* @return void

 */

public
void handleDecode(Result result, Bitmap barcode) {

    inactivityTimer.onActivity();

    playBeepSoundAndVibrate();

    String
resultString = result.getText();

    if
(resultString.equals("")) {

        Toast.makeText(Scaner.this, "Scan failed!",3000).show();

    } else
{

        //查询keycode 本地数据库 1,优先查询本地库,2,没有本地库,直接跳到知道链接

        //分析出keyCode

        Log.i("testMain","scan_result=====>"+resultString);

        String
keyCode="";

        String[] split1;

        if(resultString.lastIndexOf("?")<0){

            Intent intent = new
Intent(this, InnerBrowser.class);

            Bundle bundle = new
Bundle();

            bundle.putString("result", resultString);

            //bundle.putParcelable("bitmap", barcode);

            intent.putExtras(bundle);

            startActivity(intent);Scaner.this.finish();return;

        }

        String[] attr = resultString.substring(resultString.lastIndexOf("?")-1, resultString.length()).split("&");

        for
(String string : attr) {

             split1 = string.split("=");

            if(split1[0].equalsIgnoreCase("keycode")){

                //找到

                if(split1.length==2){

                    keyCode=split1[1];

                }

            }

        }

        Log.i("testMain","keyCode=====>"+keyCode);

        if(!StringUtils.isBlank(keyCode)){

            AttractionDAO dao=new
AttractionDAO(Scaner.this);

            Attraction a=dao.findAttrByKeyCode(keyCode);

            Log.i("testMain","a=====>"+a);

            if(a!=null){

                Intent it=new
Intent();

                it.setClass(Scaner.this, UIAttractionDetail.class);

                it.putExtra("a", a);

                startActivity(it);

            }else{

                Intent intent = new
Intent(this, InnerBrowser.class);

                Bundle bundle = new
Bundle();

                bundle.putString("result", resultString);

                //bundle.putParcelable("bitmap", barcode);

                intent.putExtras(bundle);

                startActivity(intent);

                //this.setResult(RESULT_OK, resultIntent);

                //使用内置浏览器打开网站内容

            }

        }else{

            Intent intent = new
Intent(this, InnerBrowser.class);

            Bundle bundle = new
Bundle();

            bundle.putString("result", resultString);

            //bundle.putParcelable("bitmap", barcode);

            intent.putExtras(bundle);

            startActivity(intent);

            //this.setResult(RESULT_OK, resultIntent);

            //使用内置浏览器打开网站内容

        }

    }

    Scaner.this.finish();

}

private
void 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

public
void surfaceChanged(SurfaceHolder holder, int
format, int
width,

        int
height) {

}

@Override

public
void surfaceCreated(SurfaceHolder holder) {

    if
(!hasSurface) {

        hasSurface = true;

        initCamera(holder);

    }

}

@Override

public
void surfaceDestroyed(SurfaceHolder holder) {

    hasSurface = false;

}

public
ViewfinderView getViewfinderView() {

    return
viewfinderView;

}

public
Handler getHandler() {

    return
handler;

}

public
void drawViewfinder() {

    viewfinderView.drawViewfinder();

}

private
void 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;

        }

    }

}

private
static final long VIBRATE_DURATION = 200L;

private
void 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.

 */

private
final OnCompletionListener beepListener = new
OnCompletionListener() {

    public
void onCompletion(MediaPlayer mediaPlayer) {

        mediaPlayer.seekTo(0);

    }

};

从上面代码可以看出,做了三件事儿:加载布局文件;初始化了一个相机管理器;设置按钮监听,初始化了一个InactivityTimer实例;

然后,最重要的是他实现了一个CallBack函数:具体参见:

SurfaceHolder.Callback 译文

此时,





1

surfaceCreated

这个方法会调用然后就初始化相机的一些参数:

前两个我们好理解,第三个是干嘛的?

我们先看布局文件:





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<?xml version="1.0"
encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

        android:layout_height="fill_parent"
>

    <RelativeLayout

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"
>

        <SurfaceView

            android:id="@+id/preview_view"

            android:layout_width="fill_parent"

            android:layout_height="fill_parent"

            android:layout_gravity="center"
/>

        <com.euc.app.scan.view.ViewfinderView

            android:id="@+id/viewfinder_view"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"
/>

        <include

            android:id="@+id/include1"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:layout_alignParentTop="true"

            layout="@layout/activity_title"
/>

    </RelativeLayout>

</FrameLayout>

可以看到里面有一个自定义的View及surfaceView,

对于我这样的初学者来说,surfaceView 是什么东西?

csdn上看到这个文章

Android中SurfaceView的使用详解

虽然不是很明白,但是大致明白这是个什么东西了。

了解了生命周期之后,我们来看他执行的方法:





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

private void 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

    public
void surfaceChanged(SurfaceHolder holder, int
format, int
width,

            int
height) {

    }

    @Override

    public
void surfaceCreated(SurfaceHolder holder) {

        if
(!hasSurface) {

            hasSurface = true;

            initCamera(holder);

        }

    }

    @Override

    public
void surfaceDestroyed(SurfaceHolder holder) {

        hasSurface = false;

    }

这个surfaceView 创建出来之后,其实也把摄像头的配置信息以及硬件信息初始化好了。

OK,经过上面一个oncreate以及布局文件的加载,我们已经知道,摄像头预览成功,

这个自定义的View又是干嘛的?我们继续看源码:





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

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

}

哦,这个就是定义了一个有动态效果的扫描界面


上面的虽然代码不多,当时我们现在回忆一下步骤:

1,启动activity,加载布局文件,初始化surfaceView,初始化自定义的View(动态界面),

2,在初始化surfaceView的时候,同时初始化了摄像头的参数,初始化的handler处理器,启动了摄像头预览。


问题:那什么时候开始监听扫描二维码的呢?

初始化handler 的时候就开始监听了,看一下其构造函数:





1

2

3

4

5

6

7

8

9

10

11

public CaptureActivityHandler(Scaner activity, Vector<BarcodeFormat> decodeFormats,

      String
characterSet) {

    this.activity = activity;

    decodeThread = new
DecodeThread(activity, decodeFormats, characterSet,

        new
ViewfinderResultPointCallback(activity.getViewfinderView()));

    decodeThread.start();

    state = State.SUCCESS;

    // Start ourselves capturing previews and decoding.

    CameraManager.get().startPreview();

    restartPreviewAndDecode();

  }

再来一个:上面构造函数new了一个对象,这个对象就是用来监听获取扫描的图像的。

直到获取了二维码图像,调用回调函数就结束。





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

final class DecodeThread extends
Thread {

  public
static final String BARCODE_BITMAP = "barcode_bitmap";

  private
final Scaner activity;

  private
final Hashtable<DecodeHintType, Object> hints;

  private
Handler handler;

  private
final CountDownLatch handlerInitLatch;

  DecodeThread(Scaner activity,

               Vector<BarcodeFormat> decodeFormats,

               String
characterSet,

               ResultPointCallback resultPointCallback) {

    this.activity = activity;

    handlerInitLatch = new
CountDownLatch(1);

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

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

  }

  Handler getHandler() {

    try
{

      handlerInitLatch.await();

    } catch
(InterruptedException ie) {

      // continue?

    }

    return
handler;

  }

  @Override

  public
void run() {

    Looper.prepare();

    handler = new
DecodeHandler(activity, hints);

    handlerInitLatch.countDown();

    Looper.loop();

  }

}

回调函数:





1

2

3

4

5

6

7

8

9

10

11

public void handleDecode(Result result, Bitmap barcode) {

    inactivityTimer.onActivity();

    playBeepSoundAndVibrate();

    String
resultString = result.getText();

    if
(resultString.equals("")) {

        Toast.makeText(Scaner.this, "Scan failed!",3000).show();

    } else

        //扫描结果的处理。

    }

    Scaner.this.finish();

}


life日志

时间: 2024-11-05 02:41:28

android 利用ZXING扫描二维码代码分析的相关文章

完美解决Android使用Zxing扫描二维码改成竖屏后,后面的预览画面出现了拉伸,扭曲的情况

完美解决解决Android使用Zxing扫描二维码改成竖屏后,后面的预览画面出现了拉伸,扭曲的情况 第一步:找到com.zxing.camera包下的CameraConfigurationManager.java文件中的void initFromCameraParameters(Camera camera)方法 第二步:在 Log.d(TAG, "Screen resolution: " + screenResolution);后加上如下的代码 Point screenResoluti

【转】Android平台下利用zxing实现二维码开发

http://www.cnblogs.com/dolphin0520/p/3355728.html 现在走在大街小巷都能看到二维码,而且最近由于项目需要,所以研究了下二维码开发的东西,开源的二维码扫描库主要有zxing和zbar,zbar在iPos平台上应用比较成熟,而在Android平台上主流还是用zxing库,因此这里主要讲述如何利用zxing进行二维码开发. 1.如何将zxing的Android源码导入工程. 在导入zxing的android源码之前,先去官方下载zxing的源码:http

Android平台下利用zxing实现二维码开发

http://www.cnblogs.com/dolphin0520/p/3355728.html 现在走在大街小巷都能看到二维码,而且最近由于项目需要,所以研究了下二维码开发的东西,开源的二维码扫描库主要有zxing和zbar,zbar在iPos平台上应用比较成熟,而在Android平台上主流还是用zxing库,因此这里主要讲述如何利用zxing进行二维码开发. 1.如何将zxing的Android源码导入工程. 在导入zxing的android源码之前,先去官方下载zxing的源码:http

[Unity+Android]横版扫描二维码

终于解决了一个忧伤好久的问题,严重拖了项目进度,深感惭愧!一直被一系列的问题所困扰,然后又只能自己一个人摸索,也是一段辛酸忧伤史,现在小结一下上个月在做二维码的过程中所碰到的问题以及解决办法,现在庆幸终于解决好了,终于能将这个功能告一段落,一下小结也是分享一下Unity的某些"坑",让同行少走弯路,起码在二维码这方面应该会有所启迪,欣慰的是接下来几天终于可以做自己应该做的事情了! 效果图: 先小结一下碰到的问题: 1.Unity工程屏幕方向与Android工程屏幕方向要一致的问题 本来

Android开发——通过扫描二维码,打开或者下载Android应用

Android开发——通过扫描二维码,打开或者下载Android应用 在实现这个功能的时候,被不同的浏览器折磨的胃疼,最后实现了勉强能用,也查考了一下其他人的博客 android实现通过浏览器点击链接打开本地应用(APP)并拿到浏览器传递的数据 android/iPhone:如何从browser直接打开应用程序或者打开应用商店(如果没有应用程序) 1.Html页面(JS不在行,这个是其他人写的) 需要留意的是Android_URL,格式需要符合[scheme]://[host]/[path]?[

Android实例-实现扫描二维码并生成二维码(XE8+小米5)

相关资料: 第三方资料太大没法写在博文上,请下载CSDN的程序包. 程序包下载: 过几天,刚上传的包,都没有办法显示. 注意事项: 如果只加了Lib,然没有改AndroidManifest.xml,App在呼叫BarCode时会ANR没反应.开始可能没有官方的classes.dex,但如果发现编译出错后,请再检查一下.TMessageManager须加System.Messaging单元. 使用DelphiXE7加入JavaLibrary后,呼叫Zxing相机1.新建一个DelphiXE工程,双

使用ZXing扫描二维码和生成二维码

二维码在APP中的使用越来越多,于是就是找了相关的资料写了一个二维码扫描和生成二维码的Demo. 本Demo使用了第三方的ZXing库.github的地址: Zxing AndroidStudio中的引用: File---New---import  module导入ZXing的第三方库然后选中项目按F4, 点击加号选择File dependency将ZXing库导入. 接下来就开始写布局文件 activity_main.xml <?xml version="1.0" encodi

Android开发之扫描二维码开发

原贴地址:http://www.cnblogs.com/Fndroid/p/5540688.html 二维码其实有很多种,但是我们常见的微信使用的是一种叫做QRCode的二维码,像下面这样的,可以放心的扫,这只是我的博客主页链接啦: 关于QR码编码的二维码,我们要知道几个特点: 1. 扫描时可以从各个角度去扫,也就是旋转多少度都没关系,不信吗?下次去肯德基买单试试咯. 2. 二维码有容错率,容错率越大,生成的二维码也就越复杂,但是越不容易出错,并且,当二维码被遮挡的时候也越容易扫描出来.这里我上

Java利用Zxing生成二维码

Zxing是Google提供的关于条码(一维码.二维码)的解析工具,提供了二维码的生成与解析的方法,现在我简单介绍一下使用Java利用Zxing生成与解析二维码 1.二维码的生成 1.1 将Zxing-core.jar 包加入到classpath下. 1.2 二维码的生成需要借助MatrixToImageWriter类,该类是由Google提供的,可以将该类拷贝到源码中,这里我将该类的源码贴上,可以直接使用. import com.google.zxing.common.BitMatrix; i