本文的目的只有一个,在两分钟之内教你做二维码识别,不涉及任何相机方面的实时识别,或是长按识别。
仅仅只是从图库选一张图片,然后做识别。
最终效果如下:

本文用到了Github上面一个开源库,QR Code decoding library written in Java。
此库使用*** GNU GENERAL PUBLIC LICENSE***协议,使用需要谨慎,发布的产品不能作为商业产品收费使用。
好了教程开始
下载他提供的jar包


按Ctrl+Alt+Shift+S,打开Project Structure


这时候就能在app模块的build.gradle中看见所示的compile了,忽略上一步,直接在这里敲上这么一句也是可以的

接下来,同步一下你的gradle文件,进入第二步
在需要的地方,使用你喜欢的方式获取到需要识别的二维码图片
这里使用ButterKnife,您使用findViewById当然也是一样的啦~

@OnClick(R.id.image_view_qr_code)
void loadQRCode() {
Intent albumIntent = new Intent(Intent.ACTION_PICK);
albumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(albumIntent, REQUEST_ALBUM);
}
在onActivityResult中处理获取来的图片

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_ALBUM:
if (resultCode == RESULT_OK) {
Log.i(TAG, "onActivityResult: " + data.toString());
Uri uri = data.getData();
mQrCodeImageView.setImageURI(uri);
new ReadQRCodeTask().execute(uri);
}
break;
default:break;
}
super.onActivityResult(requestCode, resultCode, data);
}
这里还必须写一个类
用来做解码的适配,将Bitmap转化为一种QRCodeImage,做成内部类即可

这里使用了异步的任务处理
new ReadQRCodeTask().execute(uri);
,关于这个类的使用,详细参考AsyncTask | Android Developers,看完就会懂的,很实用。
如果不想看的话,我简单的说几句:这个类的作用就是,“把事情分开做”,逻辑更清晰。在我们想要后台访问网络或是其他费事的操作的时候,更新UI用runOnUIThread的话,就会产生很多谜之tab,可读性较差,使用AsyncTask 可以有效避免这个问题,更有甚者,可以去了解一下RxJava、RxAndroid,这里不再赘述。

private class ReadQRCodeTask extends AsyncTask<Uri, Void, String>{
private static final String DECODE_FAILED = "decode_failed";
private ProgressDialog progressDialog;
@Override
protected void onPreExecute() {
progressDialog = new ProgressDialog(getContext());
progressDialog.setTitle("识别中");
progressDialog.setMessage(getString(R.string.reading_qr_code));
progressDialog.show();
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
}
@Override
protected String doInBackground(Uri... uris) {
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(),
uris[0]);
} catch (IOException e) {
e.printStackTrace();
}
QRCodeDecoder decoder = new QRCodeDecoder();
byte[] qrCodeContent;
try {
qrCodeContent = decoder.decode(new Image(bitmap));
}catch (DecodingFailedException e){
return DECODE_FAILED;
}
return new String(qrCodeContent);
}
@Override
protected void onPostExecute(String s) {
progressDialog.dismiss();
Log.i(TAG, "onPostExecute: 读取结果是:"+s);
if (s.equals(DECODE_FAILED)){
Toast.makeText(getContext(), R.string.read_failed, Toast.LENGTH_SHORT).show();
return;
}
mIdCodeEditText.setText(s.substring(s.lastIndexOf("/")+1));
Toast.makeText(getContext(), R.string.read_succeed, Toast.LENGTH_SHORT).show();
}
}
好啦教程到这里就差不多结束啦
网友评论