Bootstrap

Android利用zxing用相机扫描识别二维码(添加闪光灯和本地二维码)超详细教程

之前写了怎么用zxing的jar包进行简单的识别和生成二维码,以及生成带图片的二维码。

接下来单独说说怎么用相机扫描二维码,用相机扫描二维码相对于前面的生成二维码,识别二维码来说要麻烦一点,网上的教程太多,要么太简单,要么说得不清楚,来写写我的,一是方便大家学习,而是方便自己复习。

(1)下载

先致敬前辈,原GitHub的地址,https://github.com/zxing/zxing

然后这是我修改过的别人的,接下来教程都是以我修改过的为准:我修改后的GitHub地址

如果访问GitHub较慢也可以直接在CSDN下载:此demo解压后可直接用Android studio打开

(2)粘贴com.google.zxing包

    在下载好的java文件夹里面找到com.google.zxing包,复制,如图


    打开自己的项目,右键点击java,选择粘贴,注意一定要粘贴在自己的main文件夹里面,不要粘贴到了test里面。包的名字也要是com.google.zxing,不然会报错。


然后打开会发现这4个JAVA文件会出错,原因是R包和自己的包不一样(注意看我com.google.zxing后面的括号里跟了个test,原因是我不小心粘贴到test文件夹里面了,后来调试的时候出错了,正常的粘贴到main里面是没有test的,一定要注意)


修改方法就是打开这四个文件,import自己的R包,格式如图:


(3)粘贴源文件

                两个layout:activity_scanner,scanner_toolbar

                一个raw文件声音beep.ogg

                values里面的attrs,colors,ids,strings,如果有自己的内容的话注意不要覆盖了。


(4)配置权限等

在app下的build.gradle里面添加   compile 'com.google.zxing:core:3.3.0'       如图:

然后在manifest里面申请权限:


   
   
  1. <uses-permission android:name= "android.permission.CAMERA"></uses-permission>
  2. <uses-permission android:name= "android.permission.VIBRATE" />
  3. <uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
  4. <uses-feature android:name= "android.hardware.camera" />
  5. <uses-feature android:name= "android.hardware.camera.autofocus" />
  6. <uses-permission android:name= "android.permission.FLASHLIGHT" />

以及声明CaptureActivity

<activity android:name="com.google.zxing.activity.CaptureActivity"/>
   
   

(5)测试运行

在MainActivity里面import进CaptureActivity

import com.google.zxing.activity.CaptureActivity;
   
   
然后button监听里面:

   
   
  1. Button toscan=(Button)findViewById(R.id.to_scan);
  2. toscan.setOnClickListener( new View.OnClickListener() {
  3. @Override
  4. public void onClick (View v) {
  5. Intent intent= new Intent();
  6. intent.setClass(MainActivity. this,CaptureActivity.class);
  7. startActivity(intent);
  8. }
  9. });

然后看效果:

点击button————————————出现扫描页面————————————扫描结果



可以看到在这里我自己又添加了一个闪光灯按钮和右上角的从相册获取图片按钮,看看效果


(6)show me the code:

主要的改动就是在CaptureActivity里面

handleDecode函数用于处理相机扫描得来的二维码,zxing里面已经写得很完全了,我在这里设置了个对话框,使扫描出来的内容直接显示出来


   
   
  1. /**
  2. * 这里是用相机扫描的处理方法
  3. */
  4. public void handleDecode (Result result, Bitmap barcode) {
  5. inactivityTimer.onActivity();
  6. playBeepSoundAndVibrate();
  7. final String resultString = result.getText();
  8. if (TextUtils.isEmpty(resultString)) {
  9. Toast.makeText(CaptureActivity. this, "Scan failed!", Toast.LENGTH_SHORT).show();
  10. } else {
  11. //对话框
  12. AlertDialog dialog = new AlertDialog.Builder( this)
  13. .setTitle( "扫描结果:") //设置对话框的标题
  14. .setMessage(resultString) //设置对话框的内容
  15. //设置对话框的按钮
  16. .setNegativeButton( "取消", new DialogInterface.OnClickListener() {
  17. @Override
  18. public void onClick (DialogInterface dialog, int which) {
  19. dialog.dismiss();
  20. finish();
  21. }
  22. })
  23. .setPositiveButton( "确定", new DialogInterface.OnClickListener() {
  24. @Override
  25. public void onClick (DialogInterface dialog, int which) {
  26. dialog.dismiss();
  27. finish();
  28. }
  29. }).create();
  30. dialog.setCanceledOnTouchOutside( false); //点击其他地方对话框不消失
  31. dialog.show();
  32. }
  33. }

然后是从相册里面导入二维码:

open_picture方法:


   
   
  1. //打开图片
  2. private void open_picture (){
  3. Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT);
  4. innerIntent.setType( "image/*");
  5. Intent wrapperIntent = Intent.createChooser(innerIntent, "请选择二维码图片");
  6. CaptureActivity. this.startActivityForResult(wrapperIntent, REQUEST_CODE_SCAN_GALLERY);
  7. }

这是系统自带的onActivityResult方法,我做了一些改动。

onActivityResult的主要思路就是找到这个文件的路径,然后根据这个路径找到文件进行解析。


   
   
  1. /**
  2. * 这里是扫描相册图片的处理方法
  3. */
  4. @Override
  5. protected void onActivityResult (final int requestCode, int resultCode, Intent data) {
  6. if (resultCode==RESULT_OK) {
  7. switch (requestCode) {
  8. case REQUEST_CODE_SCAN_GALLERY:
  9. //获取选中图片的路径
  10. Cursor cursor = getContentResolver().query(data.getData(), null, null, null, null);
  11. if (cursor.moveToFirst()) {
  12. photo_path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
  13. }
  14. cursor.close();
  15. //扫描结果
  16. Result result = scanningImage(photo_path);
  17. //对话框
  18. AlertDialog dialog = new AlertDialog.Builder( this)
  19. .setTitle( "扫描结果:") //设置对话框的标题
  20. .setMessage(result.getText().toString()) //设置对话框的内容
  21. //设置对话框的按钮
  22. .setNegativeButton( "取消", new DialogInterface.OnClickListener() {
  23. @Override
  24. public void onClick (DialogInterface dialog, int which) {
  25. dialog.dismiss();
  26. finish();
  27. }
  28. })
  29. .setPositiveButton( "确定", new DialogInterface.OnClickListener() {
  30. @Override
  31. public void onClick (DialogInterface dialog, int which) {
  32. dialog.dismiss();
  33. finish();
  34. }
  35. }).create();
  36. dialog.setCanceledOnTouchOutside( false); //点击其他地方对话框不消失
  37. dialog.show();
  38. break;
  39. }
  40. }
  41. super.onActivityResult(requestCode, resultCode, data);
  42. }

然后是闪光灯控制:

这里另外需要在CameraManager里面修改一些参数,我已经修改好了的,下载我的demo可以直接用


   
   
  1. /**
  2. *闪光灯控制,CaptureActivity里面
  3. */
  4. private void lightOn (){
  5. camera = CameraManager.getCamera();
  6. parameter = camera.getParameters();
  7. if (!isOpen) {
  8. parameter.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_TORCH);
  9. camera.setParameters(parameter);
  10. isOpen = true;
  11. } else { // 关灯
  12. parameter.setFlashMode(android.hardware.Camera.Parameters.FLASH_MODE_OFF);
  13. camera.setParameters(parameter);
  14. isOpen = false;
  15. }
  16. }

最后还有动态权限申请等等:


   
   
  1. /**访问照片权限
  2. *
  3. */
  4. final int checked = ContextCompat.checkSelfPermission(CaptureActivity. this
  5. , Manifest.permission.WRITE_EXTERNAL_STORAGE);
  6. if (checked == PackageManager.PERMISSION_GRANTED) {
  7. } else {
  8. ActivityCompat.requestPermissions(CaptureActivity. this
  9. , new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
  10. }
  11. CameraManager.init(getApplication());
  12. viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_content);

   
   
  1. //摄像头权限
  2. if (Build.VERSION.SDK_INT >= 23) {
  3. //Manifest.permission.CAMERA
  4. //如果用户并没有同意该权限
  5. if (checkSelfPermission(Manifest.permission.CAMERA) != PERMISSION_GRANTED) {
  6. //申请权限
  7. requestPermissions( new String[]{Manifest.permission.CAMERA}, 100);
  8. } else {
  9. }
  10. }

最后:

有什么不懂的可以给我留言或者发邮件,邮箱在博客主页顶部。接下来我准备把这个扫描二维码集成到浏览器里面去。到时候再来写一下



;