最近有用到扫描二维码和条形码的需求,看到当前主要有两个比较有名的开源库ZBar和ZXing,怀着对Google的仰慕之心,并且凭着对二维码扫码的优势,最终决定使用ZXing来进行开发。
至于具体实现,本人由于水平有限,思前想后,最终采用广播来实现(如有大神有更好的实现方式,欢迎指教)。核心思想是用一个Scanner类来进行对扫码Activity的管理,包括该Activity的启动、扫码结果的处理、扫码错误以及用户取消事件的处理和最终Activity的关闭等。
Scanner类中的处理
1. Scanner 打开时的处理:启动扫码的Activity,注册广播,该广播接收器中实现了对ScannerListener的监听回调
public void open(){
Intent intent = new Intent(context, MipcaActivityCapture.class);
intent.putExtra(TIMEOUT, mTimeout);
context.startActivity(intent);
registerMyBroadcastReceiver();
}
private void registerMyBroadcastReceiver(){
if(!isBroadcastRegistered) {
isBroadcastRegistered = !isBroadcastRegistered;
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(QRCodeScanner.SCAN_INTENT_ACTION);
context.registerReceiver(receiver, intentFilter);
}
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().endsWith(SCAN_INTENT_ACTION)) {
int flag = intent.getIntExtra("FLAGS", ERROR_FLAG);
switch ( flag ){
case SUCCESS_FLAG:
qrCodeStr = intent.getStringExtra("QR_CODE_STR");
if(listener != null) {
listener.onReadSuccess(qrCodeStr);
}
break;
case CANCEL_FLAG:
if(listener != null){
listener.onCancel();
}
break;
case ERROR_FLAG:
default:
if(listener != null){
listener.onReadError();
}
break;
}
}
}
};
2. Scanner开始扫码时的处理:实现监听器接口
public void start(ScannerListener listener){
this.listener = listener;
}
public interface ScannerListener{
void onReadSuccess(String result);
void onReadError();
void onCancel();
}
3. Scanner关闭时的处理:取消广播的注册,并向扫码Actiivty发送关闭自身的广播(该Scanner的设计思想是只能通过此种方式关闭扫码Activity,禁止其他方式来关闭)
public void close(){
unRegisterMyBroadcastReceiver();
Intent intent = new Intent(MipcaActivityCapture.CLOSE_SCANNER_INTENT_ACTION);
context.sendBroadcast(intent);
}
private void unRegisterMyBroadcastReceiver(){
if(isBroadcastRegistered) {
isBroadcastRegistered = !isBroadcastRegistered;
context.unregisterReceiver(receiver);
}
}
扫码Activity中的处理
1. 在该Activity 的onCreate方法中注册自己的销毁广播
private void registerDestroyActivityReceiver(){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CLOSE_SCANNER_INTENT_ACTION);
registerReceiver(mDestroyActivityReceiver, intentFilter);
}
private BroadcastReceiver mDestroyActivityReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(CLOSE_SCANNER_INTENT_ACTION)){
finish();
}
}
};
2.在扫码结果处理的代码中根据扫码结果发送扫码成功或失败的广播
/**
* 处理扫描结果
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
if(TextUtils.isEmpty(resultString)){
Toast.makeText(MipcaActivityCapture.this, "Scan failed!", Toast.LENGTH_SHORT).show();
sendScanErrorBroadcast();
}else{
sendSuccessBroadcast(resultString);
}
}
private void sendSuccessBroadcast(String qrcodeStr){
Intent intent = new Intent(QRCodeScanner.SCAN_INTENT_ACTION);
intent.putExtra("FLAGS", QRCodeScanner.SUCCESS_FLAG);
intent.putExtra("QR_CODE_STR", qrcodeStr);
sendBroadcast(intent);
}
public void sendScanErrorBroadcast(){
Intent intent = new Intent(QRCodeScanner.SCAN_INTENT_ACTION);
intent.putExtra("FLAGS", QRCodeScanner.ERROR_FLAG);
sendBroadcast(intent);
}
3.在用户点击“返回”按钮或“返回”键时发送“用户取消操作事件”的广播
private void sendCancelBroadcast(){
Intent intent = new Intent(QRCodeScanner.SCAN_INTENT_ACTION);
intent.putExtra("FLAGS", QRCodeScanner.CANCEL_FLAG);
sendBroadcast(intent);
}
4.在扫码Activity的onDestroy()方法中取消销毁广播的注册
@Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
unregisterReceiver(mDestroyActivityReceiver);
}
至此,Scanner的封装已经完成,让我们来体会一下该Scanner使用时的简洁和优雅吧
private void startScanner(){
final QRCodeScanner qrCodeScanner = new QRCodeScanner(this);
qrCodeScanner.open();
qrCodeScanner.start(new QRCodeScanner.ScannerListener() {
@Override
public void onReadSuccess(String result) {
qrCodeScanner.close();
tvQRCode.setText(result);
Log.i("Tag", "read success...");
}
@Override
public void onReadError() {
qrCodeScanner.close();
Log.i("Tag", "read error or time out...");
}
@Override
public void onCancel() {
qrCodeScanner.close();
Log.i("Tag", "user canceled...");
}
});
}
源码下载地址:
对ZXing封装的Scanner源码