I need to have a QR scanner in my project. I use ZBar for doing this task. Mainly I did a very small change on the example code given by ZBar git example to do the job. I need to show the scanned result in a browser(if url) or in a dialog(if normal information).
Every thing working well with my code given bellow except if I try to show the url after scan a qr code in browser. When I come back to my app from the browser the camera viewport turns black and remain inactive. I tried to get back the camera active to scan another qr code but i failed. I tried to reopen the camera in my onResume() function but that causes error and forcefully exited from the app. Please help me on that issue.
package com.myapp;
import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.Size;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.URLUtil;
import android.widget.FrameLayout;
import com.myapp.CameraPreview;
/* Import ZBar Class files */
public class QRScannerActivity extends Activity
{
private Camera mCamera;
private CameraPreview mPreview;
private Handler autoFocusHandler;
ImageScanner scanner;
private boolean barcodeScanned = false;
private boolean previewing = true;
static {
System.loadLibrary("iconv");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.qr_scanner_main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
autoFocusHandler = new Handler();
mCamera = getCameraInstance();
/* Instance barcode scanner */
scanner = new ImageScanner();
scanner.setConfig(0, Config.X_DENSITY, 3);
scanner.setConfig(0, Config.Y_DENSITY, 3);
mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
preview.addView(mPreview);
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
//finish();
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open();
} catch (Exception e){
}
return c;
}
private void releaseCamera() {
//Toast.makeText(QRScannerActivity.this, "Paused State", Toast.LENGTH_SHORT).show();
if (mCamera != null) {
previewing = false;
mCamera.setPreviewCallback(null);
mPreview.getHolder().removeCallback(mPreview);
mCamera.release();
mCamera = null;
}
}
private Runnable doAutoFocus = new Runnable() {
public void run() {
if (previewing)
mCamera.autoFocus(autoFocusCB);
}
};
PreviewCallback previewCb = new PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Size size = parameters.getPreviewSize();
Image barcode = new Image(size.width, size.height, "Y800");
barcode.setData(data);
int result = scanner.scanImage(barcode);
String QRScannerResult;
if (result != 0) {
previewing = false;
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
SymbolSet syms = scanner.getResults();
for (Symbol sym : syms) {
QRScannerResult = sym.getData();
showResultAction(QRScannerResult);
barcodeScanned = true;
}
}
}
};
// Mimic continuous auto-focusing
AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
autoFocusHandler.postDelayed(doAutoFocus, 1000);
}
};
private void showResultAction(String QRScannerResult){
if (URLUtil.isValidUrl(QRScannerResult)) {
if (barcodeScanned) {
barcodeScanned = false;
mCamera.setPreviewCallback(previewCb);
mCamera.startPreview();
previewing = true;
mCamera.autoFocus(autoFocusCB);
}
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(QRScannerResult));
startActivity(i);
}else {
new AlertDialog.Builder(this)
.setTitle("QR Data")
.setMessage(QRScannerResult)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (barcodeScanned) {
barcodeScanned = false;
mCamera.setPreviewCallback(previewCb);
mCamera.startPreview();
previewing = true;
mCamera.autoFocus(autoFocusCB);
}
}
})
.show();
}
}
}
Thanks in advance. Sakib
At last I succeeded to find out the problem of my code and got the solution. When i try to reopen the camera in my onResume()
method I missed a part. When I create/open a new camera in onResume()
, the FrameLayout still has my previous camera. So All I do is remove my previous camera from FrameLayout on onPause()
method and then recreate everything on onResume() method. That solve my problem and now it is working nicely without any error. Here is my onPause()
and onResume()
method with the fix. Hope this might help somebody in future.
public void onPause() {
super.onPause();
releaseCamera();
FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
preview.removeView(mPreview);
}
public void onResume(){
super.onResume();
try {
if(mCamera==null){
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
autoFocusHandler = new Handler();
mCamera = getCameraInstance();
this.getWindowManager().getDefaultDisplay().getRotation();
scanner = new ImageScanner();
scanner.setConfig(0, Config.X_DENSITY, 3);
scanner.setConfig(0, Config.Y_DENSITY, 3);
mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
preview.addView(mPreview);
}
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open();
} catch (Exception e){
}
return c;
}
private void releaseCamera() {
//Toast.makeText(QRScannerActivity.this, "Paused State", Toast.LENGTH_SHORT).show();
if (mCamera != null) {
previewing = false;
mCamera.setPreviewCallback(null);
mPreview.getHolder().removeCallback(mPreview);
mCamera.release();
mCamera = null;
mPreview= null;
}
}
Thanks, Sakib
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With