您的位置:首页 > 移动开发 > Android开发

SB程序媛学习笔记--Android zxing实现二维码开发

2015-09-01 13:20 621 查看
博主有话说:写这个博客只是为了记录学习android过程中的问题,这篇文章只是参考了很多其他博主写的文章和资料总结出的笔记,并非完全原创。如果你运气不咋地看到这篇文章而且又觉得似曾相识,请勿喷我,我会在文章最后贴出参考博客地址。

关于zxing库,有以下几个方面:

(1)下载zxing库(下载精简过的android库)

(2)配置zxing库到项目中

(3)生成二维码

(4)扫描二维码

(5)扫描框UI

(1)下载zxing库

尊重原作者:https://github.com/zxing/zxing

但是因为原作者实在是太厉害,库实在太大,所以请下载精简过的zxing库,以下是精简库的结构:



(2)配置zxing库到项目中

①将下载的zxing库import进eclipse中

②选中该项目右键——properties——Android——选中isLibrary(因为这个项目作为库被其他项目使用)——OK



③新建一个项目(这个项目是你需要导入这个功能的项目)



④选中该项目右键——properties——Android——Add加入zxing库——OK



(3)生成二维码

①创建EditText et1接受输入内容

<span style="font-size:14px;">String str =et1.getText().toString();</span>


②创建Bitmap存储二维码图片,而生成二维码是用到库里面的EncodingHandler类中的createQRCode方法

Bitmap qrcode = EncodingHandler.createQRCode(et1.getText().toString(), 400);


参数:

1.生成二维码的内容

2.生成二维码横向纵向长度(由于是一个正方形,所以只有一个值)

完整代码:

String str =et1.getText().toString();
		if(str.equals("")){
			Toast.makeText(MainActivity.this, "请输入文本", Toast.LENGTH_SHORT).show();
		}
		else{
			try {
					//第一个参数是要生成二维码的内容,第二个参数是生成二维码横向纵向长度
					Bitmap qrcode = EncodingHandler.createQRCode(et1.getText().toString(), 400);
					iv.setImageBitmap(qrcode);
				} catch (WriterException e) {
						
					e.printStackTrace();
				}
			}


(4)扫描二维码

①二维码扫描的页面实际是库里面的一个Activity,项目里面通过跳转到库里面CaptureActivity来使用二维码扫描功能,所以要定义一个intent来跳转。

Intent  startScan = new Intent(MainActivity.this, CaptureActivity.class);


②实现跳转功能需要在你的项目AndroidManifest.xml中定义Activity,可以直接把zxing库中AndroidManifest.xml的以下内容复制到你的项目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>


③调用startActivity(startScan);跳转到二维码扫描页面,扫描页面如下(这是改变过的UI)

完整代码:

Intent  startScan = new Intent(MainActivity.this, CaptureActivity.class);
startActivity(startScan);






但是调用startActivity(startScan);只能打开扫描Activity,但是不能解码,由于库的CaptureActivity中的handleDecode方法会将解码内容回调,如下:

public void handleDecode(Result result, Bitmap barcode) {
		inactivityTimer.onActivity();
		playBeepSoundAndVibrate();
		String resultString = result.getText();
		
		if (resultString.equals("")) {
			Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
		}else {
			Intent resultIntent = new Intent();
			Bundle bundle = new Bundle();
			bundle.putString("result", resultString);
			resultIntent.putExtras(bundle);
			this.setResult(RESULT_OK, resultIntent);
		}
		CaptureActivity.this.finish();
	}


所以在你的项目的MainActivity需要调用startActivityForResult(startScan, 0);来跳转页面且使用onActivityResult方法接收回调的内容,用TextView tv1显示出来,如下:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode ==RESULT_OK){
            String str =data.getExtras().getString("result");
            tv1.setText(str);
        }

}


完整代码:

public class MainActivity extends Activity {

	private Button bt1,bt2;
	private TextView tv1;
	private EditText et1;
	private ImageView iv;
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		bt1 =(Button)findViewById(R.id.bt1);
		bt2 =(Button)findViewById(R.id.bt2);
		tv1 =(TextView)findViewById(R.id.tv1);
		et1 =(EditText)findViewById(R.id.et1);
		iv =(ImageView)findViewById(R.id.iv1);
		
		bt1.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				Toast.makeText(MainActivity.this, "你写可以扫描条形码或者二维码", Toast.LENGTH_SHORT).show();
				Intent  startScan = new Intent(MainActivity.this, CaptureActivity.class);
				//startActivity(startScan);
				startActivityForResult(startScan, 0);
				
			}
		});
		
		bt2.setOnClickListener(new OnClickListener() {
			
			
			@Override
			public void onClick(View v) {
				
				String str =et1.getText().toString();
				if(str.equals("")){
					Toast.makeText(MainActivity.this, "请输入文本", Toast.LENGTH_SHORT).show();
				}
				else{
					try {
						//第一个参数是要生成二维码的内容,第二个参数是生成二维码横向纵向长度
						Bitmap qrcode = EncodingHandler.createQRCode(et1.getText().toString(), 400);
						iv.setImageBitmap(qrcode);
					} catch (WriterException e) {
						
						e.printStackTrace();
					}
				}
			
			}
		});

	}
	
	   
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode ==RESULT_OK){
            String str =data.getExtras().getString("result");
            tv1.setText(str);
        }

    }
	

}


由于扫描功能用到照相机,和震动,需要加入permission:

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


演示:

①在EditText输入需要转换内容,点击生成二维码生成。



②点击打开扫描二维码按钮,扫描,显示输入的内容



(5)扫描框UI

由于库中自带的扫描框是横屏的,解决横屏和其他详见问题参考: http://www.cnblogs.com/dolphin0520/p/3355728.html
扫描框其实是通过View画出来的,在zxing库中的包com.zxing.view的ViewfinderView类就是扫描框的UI,由于对View不怎么熟悉,只能凭我自己理解。

1.包 com.zxing.camera的CameraManager类中以下两个参数是可以控制框的大小
//控制框的最大宽度
  private static final int MAX_FRAME_WIDTH = 480;
  //控制框的最大高度
  private static final int MAX_FRAME_HEIGHT = 480;


2.包com.zxing.view的ViewfinderView类中以下代码获取到这个框

Rect frame = CameraManager.get().getFramingRect();
    if (frame == null) {
      return;
}


3在ondraw方法中对获得的框进行装饰

①绘制扫描框以外的阴影部分

// Draw the exterior (i.e. outside the framing rect) darkened 
    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);


② 画出扫描框的四个角

paint.setColor(getResources().getColor(R.color.blues));
        
    //左上角
    canvas.drawRect(frame.left,frame.top, frame.left + ScreenRate,frame.top+ 10,paint);
    canvas.drawRect(frame.left,frame.top, frame.left + 10,frame.top+ ScreenRate,paint);

    //右上角
    canvas.drawRect(frame.right- ScreenRate,frame.top, frame.right,frame.top + 10,paint);
    canvas.drawRect(frame.right- 10,frame.top, frame.right,frame.top + ScreenRate,paint);

    //左下角
    canvas.drawRect(frame.left,frame.bottom - 10,frame.left + ScreenRate,frame.bottom,paint);
    canvas.drawRect(frame.left,frame.bottom - ScreenRate,frame.left + 10,frame.bottom,paint);

    //右下角
    canvas.drawRect(frame.right- ScreenRate,frame.bottom - 10,frame.right,frame.bottom, paint);
canvas.drawRect(frame.right- 10,frame.bottom - ScreenRate,frame.right,frame.bottom, paint);


③绘制框中移动的线(可以用图片实现)

//初始化中间线滑动的最上边和最下边  
    if(!isFirst){  
        isFirst = true;  
        slideTop = frame.top;  
        slideBottom = frame.bottom;  
}  

//绘制中间的线,每次刷新界面,中间的线往下移动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);


④画扫描框的边框

// Draw a two pixel solid black border inside the framing rect 
      paint.setColor(frameColor);
      canvas.drawRect(frame.left, frame.top, frame.right + 1, frame.top + 2, paint);
      canvas.drawRect(frame.left, frame.top + 2, frame.left + 2, frame.bottom - 1, paint);
      canvas.drawRect(frame.right - 1, frame.top, frame.right + 1, frame.bottom - 1, paint);
      canvas.drawRect(frame.left, frame.bottom - 1, frame.right + 1, frame.bottom + 1, paint);


⑤画扫描框下面的字

paint.setColor(Color.BLACK);  
        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);


⑥在扫描的时候,框里面会出现一些***点,将以下代码注释掉就不会有了

for (ResultPoint point : currentPossible) {
          canvas.drawCircle(frame.left + point.getX(), frame.top + point.getY(), 6.0f, paint);
        }


问题(这是为了提醒博主以后深入研究的问题)

①手机离二维码很近的时候反而不能扫描出二维码,在一定距离后才能正常扫描出二维码(可能与内部算法有关)。

②扫描框下字体颜色很暗,即使用了WITHE,(可能是因为在绘制阴影部分的时候,掩盖了字体的颜色,需要去看看View详解),所以在这里直接用TextView 在camera.xml写出来。缺点是当扫描框大小改变的时候,TextView位置不改变。

<TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_margin="2dp"
                android:gravity="center"
                android:text="@string/scan_text"
                android:textColor="@android:color/white"
                android:textSize="20sp"
                android:textStyle="bold" />


③中间移动的线在扫描时候不平滑

④...

参考网址与博客:

http://www.cnblogs.com/dolphin0520/p/3355728.html

http://blog.csdn.net/xiaanming/article/details/10163203?D2kdVYKfPI_-8QXCzICABQ&ved=0CBkQFjABOIwB&usg=AFQjCNF2ULtaIMPd5bndaol7tFI3AO61Xw

http://blog.csdn.net/xinchen200/article/details/18036695

http://www.jikexueyuan.com/course/134_3.html?ss=1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: