最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程:
首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。
2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个com文件夹copy到ZXing文件夹内andorid目录中src下(里面也有个com文件夹)选择覆盖。然后就会发现里面的client文件夹内有多个result文件夹。
下面全都是以在2.2版本为例
3、把ZXing内的android/src/com文件夹copy到你自己项目src下。然后又把res那些资源文件也copy到自己项目中对应的目录下。有报错则按提示改,一般是报R文件的引用问题,当然还有一小部分是文件类引用问题,进入报错类的源码看下引用类的方法已改成什么,按照说明改下(清单文件中的启动类要改成自己的,ZXing中启动的是CaptureActivity)。
4、修改CaptureActivity类中handleDecode方法,这个方法的作用是解码已扫到的内容。我是参照网上的写法自己再稍加修改下。
public void handleDecode(Result rawResult, Bitmap barcode, float scaleFactor) {
final String result = rawResult.getText().toString();
if (!TextUtils.isEmpty(result)) {
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("scan_result", rawResult.getText());
bundle.putParcelable("bitmap",barcode);
intent.putExtras(bundle);
setResult(RESULT_OK, intent);
} else {
setResult(RESULT_CANCELED);
}
finish();
}
5、在main.xml文件中创建button跟TextView以及ImageView控件,然后在MainActivity中通过按钮监听事件中启动相机也就是扫描功能并返回结果,SCAN_CODE是常量自己定义。
Button button = (Button) findViewById(R.id.scan_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, CaptureActivity.class);
startActivityForResult(intent, SCAN_CODE);
}
});
6、通过onActivityResult方法把值获取出来并显示在控件上
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case SCAN_CODE:
TextView scanResult = (TextView) findViewById(R.id.scan_result);
if (resultCode == RESULT_OK) {
final String result = data.getStringExtra("scan_result");
iv.setImageBitmap((Bitmap) data.getParcelableExtra("bitmap"));
scanResult.setText(result);
if(isValideUrl(result)){
new AlertDialog.Builder(this)
.setTitle("扫描结果")
.setMessage(result)
.setPositiveButton("打开", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setClass(MainActivity.this,WebViewAct.class);
intent.putExtra("url",result);
startActivity(intent);
MainActivity.this.finish();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).show();
}
} else if (resultCode == RESULT_CANCELED) {
scanResult.setText("没有扫描出结果");
}
break;
}
}
到这里就已经能实现扫描功能了,而我还在这方法里面加个判断获取到的内容值是否为有效的网址,如果是的话则弹出提示是否打开。我这里先给出判断方法
/**
* 判断是否是网址
*/
public boolean isValideUrl(String text){
Pattern p = Pattern.compile("((http|ftp|https)://)(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?", Pattern.CASE_INSENSITIVE);
if(p.matcher(text).matches()){
return true;
}
return false;
}
而跳转的WebViewAct.class是自己写的:
package com.google.zxing.client.android;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
import com.example.qrcodetest.R;
/**
* Created by xiaoli.yang on 2016/7/27.
*/
public class WebViewAct extends Activity {
private WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview);
Bundle extras =this.getIntent().getExtras();
String url= extras.getString("url");
Log.i("**获取到的url值为******",url);
mWebView = (WebView) findViewById(R.id.web_view);
mWebView.loadUrl(url);
}
从代码中可以看到,我把这个类也写到com.google.zxing.client.android这个包下,方便统一更改。
《—————————————–分割线——————————————-》
上面已实现扫描功能,但扫描界面是横向的,我们一般都是竖直方向用的,so改方向。
0、按照网上各大神教的,我这算是整合吧,因为我是用红米测的所以可能是手机原因还要继续改些其他的代码。
1、我这里先贴出网上改的,就不用再找了,然后我再说我自己又改了哪些。
1) 在AndroidManifest.xml中把 标签 CaptureActivity 的screenOrientation修改为
android:screenOrientation="portrait"
2) 在CameraManager.java类中的getFramingRectInPreview()替换掉原先的 left right top bottom
//竖屏
rect.left = rect.left * cameraResolution.y / screenResolution.x;
rect.right = rect.right * cameraResolution.y / screenResolution.x;
rect.top = rect.top * cameraResolution.x / screenResolution.y;
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
3) 在CameraConfigurationManager.java中void setDesiredCameraParameters(Camera camera)方法在setParameters之前增加
camera.setDisplayOrientation(90);
4) 在DecodeHandler.java中的 decode(byte[] data, int width, int height)方法在
PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(data, width, height);之前添加:
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
rotatedData[x * height + height - y - 1] = data[x + y * width];
}
int tmp = width; // Here we are swapping, that's the difference to #11
width = height;
height = tmp;
data = rotatedData;
我这是2.2的里面代码是 PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);
以免有的人找不到。
5)进入com.google.zxing.client.android.camera包下的CameraConfigurationManager类:在Log.i(TAG, “Screen resolution: ” + screenResolution)的下面添加:
Point screenResolutionForCamera = new Point();
screenResolutionForCamera.x = screenResolution.x;
screenResolutionForCamera.y = screenResolution.y;
if (screenResolution.x < screenResolution.y) {
screenResolutionForCamera.x = screenResolution.y;
screenResolutionForCamera.y = screenResolution.x;
}
cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolutionForCamera);
加上最后一句发现有报错,我自己是直接把最后一句注释掉。
6)进入com.google.zxing.client.android包下的CaptureActivity类:注释以下代码:
if (prefs.getBoolean(PreferencesActivity.KEY_DISABLE_AUTO_ORIENTATION, true)) {
setRequestedOrientation(getCurrentOrientation());
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
}
但我在这个类中并没有找到这些内容,只注释掉
copyToClipboard = prefs.getBoolean(PreferencesActivity.KEY_COPY_TO_CLIPBOARD, true)
&& (intent == null || intent.getBooleanExtra(Intents.Scan.SAVE_HISTORY, true));
这个,功能是一样的。
并且另外在这个类的onCreate方法最后加上
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
然后运行。。。。。。
发现横竖屏是切换了,但是取景框的位置却没在中间,另外取景框感觉太小了。而且扫描二维码却扫不出来,把屏幕再倒回横屏却意外发现可以扫描。解决这些问题方法如下:
在CameraConfigurationManager类中的initFromCameraParameters方法内注释掉这段代码:
//横竖屏切换后取不到值,注释掉测试
// if (width >height) {
// Log.i(TAG, "Display reports portrait orientation; assuming this is incorrect");
// int temp = width;
// width = height;
// height = temp;
// }
调整取景框大小以及位置:
在CameraManager类中把框高都设置成540
private static final int MIN_FRAME_WIDTH = 540;//original 240
private static final int MIN_FRAME_HEIGHT = 540; //original 240
private static final int MAX_FRAME_WIDTH = 540; // = 1920/2 original 960
private static final int MAX_FRAME_HEIGHT = 540; // = 1080/2 original 540
original后面的值是原本的内容。在getFramingRect方法中通过改变
int leftOffset = (screenResolution.x - width)/2;
int topOffset = (screenResolution.y - height)/2;
这个两个2个值就能改变取景框的位置了。
以上就是我实现扫描功能的发展史,取景界面仿微信那些还不会。。。正在研究中。
下载资源地址:http://download.csdn.net/detail/u012138137/9589939 要1积分,嘿嘿。。。
在com.google.zxing.client.android包下的WebViewAct类中的onCreate方法最下面加上finish();不然跳转到webkit后返回会先有空白页,再按返回才行。