Im is developing a barcode scanning application that has the following functionality:
• Open the camera device camera, SurfaceView preview camera and automatically refocus
• Attemtps for barcode decoding using 2 methods
a) When using SurfaceView touch, using onTouchEvent (MotionEvent event) , tries to take a barcode snapshot, but gets java.lang.RuntimeException: takePicture failed
b) Or Preferably , you can take a picture with the success of onAutoFocus (boolean success, camera camera) , but onAutoFocus () does not receive the call
Im implements "AutoFocusCallback" and returns the camera object to my scan activity called "ScanVinFromBarcodeActivity".
Below is my "ScanVinFromBarcodeActivity", which takes care of the camera features:
package com.t.t.barcode;
import com.t.t.R;
public class ScanVinFromBarcodeActivity extends Activity {
private Camera globalCamera;
private int cameraId = 0;
private TextView VINtext = null;
private Bitmap bmpOfTheImageFromCamera = null;
private boolean isThereACamera = false;
private RelativeLayout RelativeLayoutBarcodeScanner = null;
private CameraPreview newCameraPreview = null;
private SurfaceView surfaceViewBarcodeScanner = null;
private String VIN = null;
private boolean globalFocusedBefore = false;
@SuppressLint("InlinedApi")
private void initializeGlobalCamera() {
try {
if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device",
Toast.LENGTH_LONG).show();
} else {
cameraId = findFrontFacingCamera();
if (cameraId < 0) {
Toast.makeText(this, "No front facing camera found.",
Toast.LENGTH_LONG).show();
} else {
Log.d("ClassScanViewBarcodeActivity",
"camera was found , ID: " + cameraId);
isThereACamera = true;
globalCamera = getGlobalCamera(cameraId);
globalCamera.getParameters().setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
globalCamera.autoFocus (autoFocusCallback); // pass surfaceView to CameraPreview newCameraPreview = new CameraPreview (this, globalCamera) {
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("ClassScanViewBarcodeActivity"," onTouchEvent(MotionEvent event) ");
takePicture();
return super.onTouchEvent(event);
}
};
RelativeLayoutBarcodeScanner.addView(newCameraPreview);
globalCamera
.setPreviewDisplay(surfaceViewBarcodeScanner
.getHolder());
globalCamera.startPreview();
Log.d("ClassScanViewBarcodeActivity",
"camera opened & previewing");
}
}
}
catch (Exception exc) {
if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;
}
Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() exception:",
exc.getMessage());
exc.printStackTrace();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_barcode_vin_scanner);
Log.d("ClassScanViewBarcodeActivity", "onCreate ");
RelativeLayoutBarcodeScanner = (RelativeLayout) findViewById(R.id.LayoutForPreview);
surfaceViewBarcodeScanner = (SurfaceView) findViewById(R.id.surfaceViewBarcodeScanner);
initializeGlobalCamera();
}
@Override
protected void onResume() {
Log.d("ClassScanViewBarcodeActivity, onResume() globalCamera:",
String.valueOf(globalCamera));
initializeGlobalCamera();
super.onResume();
}
@Override
protected void onStop() {
if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;
}
super.onStop();
}
@Override
protected void onPause() {
if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;
}
super.onPause();
}
@SuppressLint("NewApi")
public void onPictureTaken(byte[] imgData, Camera camera) {
BinaryBitmap bitmap = null ;
try {
Log.d("ClassScanViewBarcodeActivity", "onPictureTaken()");
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
options.inPreferQualityOverSpeed =true;
bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
imgData, 0, imgData.length, options);
if (bmpOfTheImageFromCamera != null) {
Matrix rotationMatrix90CounterClockWise = new Matrix();
rotationMatrix90CounterClockWise.postRotate(90);
bmpOfTheImageFromCamera = Bitmap.createBitmap(
bmpOfTheImageFromCamera, 0, 0,
bmpOfTheImageFromCamera.getWidth(),
bmpOfTheImageFromCamera.getHeight(),
rotationMatrix90CounterClockWise, true);
guidanceRectangleCoordinatesCalculations newguidanceRectangleCoordinatesCalculations = new guidanceRectangleCoordinatesCalculations(
bmpOfTheImageFromCamera.getWidth(),
bmpOfTheImageFromCamera.getHeight());
Bitmap croppedBitmap = Bitmap
.createBitmap(
bmpOfTheImageFromCamera,
newguidanceRectangleCoordinatesCalculations
.getGuidanceRectangleStartX(),
newguidanceRectangleCoordinatesCalculations
.getGuidanceRectangleStartY(),
newguidanceRectangleCoordinatesCalculations
.getGuidanceRectangleEndX()
- newguidanceRectangleCoordinatesCalculations
.getGuidanceRectangleStartX(),
newguidanceRectangleCoordinatesCalculations
.getGuidanceRectangleEndY()
- newguidanceRectangleCoordinatesCalculations
.getGuidanceRectangleStartY());
bitmap = cameraBytesToBinaryBitmap(croppedBitmap);
croppedBitmap.recycle();
croppedBitmap = null;
if (bitmap != null) {
VIN = decodeBitmapToString(bitmap);
Log.("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ",
VIN);
if (VIN!=null)
{
byte [] bytesImage = bitmapToByteArray ( croppedBitmap );
savePicture(bytesImage, 0 , "original");
croppedBitmap = sharpeningKernel (croppedBitmap);
bytesImage = bitmapToByteArray ( croppedBitmap );
savePicture(bytesImage, 0 , "sharpened");
Toast toast= Toast.makeText(getApplicationContext(),
"VIN:"+VIN, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP|Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();
}
} else {
Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=",
String.valueOf(bitmap));
}
} else {
Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ",
String.valueOf(bmpOfTheImageFromCamera));
}
}
catch (Exception exc) {
exc.getMessage();
Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ",
exc.getMessage());
}
finally {
globalCamera.startPreview();
bitmap = null;
}
}
};
AutoFocusCallback autoFocusCallback = new AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
Log.d("***onAutoFocus(boolean success, Camera camera)","success: "+success);
if (success)
{
globalFocusedBefore = true;
takePicture();
}
}
};
public Camera getGlobalCamera(int CameraId)
{
if (globalCamera==null)
{
globalCamera = Camera.open( CameraId);
}
return globalCamera;
}
public static int findFrontFacingCamera() {
int cameraId = -1;
int numberOfCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numberOfCameras; i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == CameraInfo.CAMERA_FACING_BACK) {
Log.d("ClassScanViewBarcodeActivity , findFrontFacingCamera(): ",
"Camera found");
cameraId = i;
break;
}
}
return cameraId;
}
public void savePicture(byte[] data, double sizeInPercent , String title) {
Log.d("ScanVinFromBarcodeActivity ", "savePicture(byte [] data)");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_sample_sizePercent_" + sizeInPercent + "_" + title + "_"
+ date + ".jpg";
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String filename = sdDir + File.separator + photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Toast.makeText(this, "New Image saved:" + photoFile,
Toast.LENGTH_LONG).show();
} catch (Exception error) {
Log.d("File not saved: ", error.getMessage());
Toast.makeText(this, "Image could not be saved.", Toast.LENGTH_LONG)
.show();
}
}
@SuppressWarnings("finally")
public String decodeBitmapToString(BinaryBitmap bitmap) {
Log.d("ClassScanViewBarcodeActivity",
"decodeBitmapToString(BinaryBitmap bitmap");
Reader reader = null;
Result result = null;
String textResult = null;
Hashtable<DecodeHintType, Object> decodeHints = null;
try {
decodeHints = new Hashtable<DecodeHintType, Object>();
decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
decodeHints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
reader = new MultiFormatReader();
if (bitmap != null) {
result = reader.decode(bitmap, decodeHints);
if (result != null) {
Log.d("decodeBitmapToString (BinaryBitmap bitmap): result = ",
String.valueOf(result));
Log.d("decodeBitmapToString (BinaryBitmap bitmap): result = ",
String.valueOf(result.getBarcodeFormat().toString()));
textResult = result.getText();
} else {
Log.d("decodeBitmapToString (BinaryBitmap bitmap): result = ",
String.valueOf(result));
}
} else {
Log.d("decodeBitmapToString (BinaryBitmap bitmap): bitmap = ",
String.valueOf(bitmap));
}
} catch (NotFoundException e) {
textResult = "Unable to decode. Please try again.";
e.printStackTrace();
Log.d("ClassScanViewBarcodeActivity, NotFoundException:",
e.getMessage());
} catch (ChecksumException e) {
textResult = "Unable to decode. Please try again.";
e.printStackTrace();
Log.d("ClassScanViewBarcodeActivity, ChecksumException:",
e.getMessage());
} catch (FormatException e) {
textResult = "Unable to decode. Please try again.";
e.printStackTrace();
Log.d("ClassScanViewBarcodeActivity, FormatException:",
e.getMessage());
}
finally {
reader = null;
result = null;
decodeHints = null;
return textResult;
}
}
@SuppressWarnings("finally")
public BinaryBitmap cameraBytesToBinaryBitmap(Bitmap bitmap) {
Log.d("ClassScanViewBarcodeActivity , cameraBytesToBinaryBitmap (Bitmap bitmap):",
"");
BinaryBitmap binaryBitmap = null;
RGBLuminanceSource source = null;
HybridBinarizer bh = null;
try {
if (bitmap != null) {
source = new RGBLuminanceSource(bitmap);
bh = new HybridBinarizer(source);
binaryBitmap = new BinaryBitmap(bh);
} else {
Log.d("ClassScanViewBarcodeActivity , cameraBytesToBinaryBitmap (Bitmap bitmap): bitmap = ",
String.valueOf(bitmap));
}
} catch (Exception exc) {
exc.printStackTrace();
} finally {
source = null;
bh = null;
return binaryBitmap;
}
}
@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public int getScreenOrientation() {
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
Display getOrient = getWindowManager().getDefaultDisplay();
int orientation = Configuration.ORIENTATION_UNDEFINED;
if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
if (getOrient.getWidth() == getOrient.getHeight()) {
orientation = Configuration.ORIENTATION_SQUARE;
} else {
if (getOrient.getWidth() < getOrient.getHeight()) {
orientation = Configuration.ORIENTATION_PORTRAIT;
} else {
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
} else {
Point size = new Point();
this.getWindowManager().getDefaultDisplay().getSize(size);
int width = size.x;
int height = size.y;
if (width < height) {
orientation = Configuration.ORIENTATION_PORTRAIT;
} else {
orientation = Configuration.ORIENTATION_LANDSCAPE;
}
}
return orientation;
}
public Bitmap sharpeningKernel (Bitmap bitmap)
{
if (bitmap!=null)
{
int result = 0 ;
int pixelAtXY = 0;
for (int i=0 ; i<bitmap.getWidth(); i++)
{
for (int j=0 ; j<bitmap.getHeight(); j++)
{
pixelAtXY = bitmap.getPixel(i, j);
result = ((pixelAtXY * -1) + (pixelAtXY * -1) + (pixelAtXY * 5)+ (pixelAtXY * -1) + (pixelAtXY * -1));
bitmap.setPixel(i, j,result);
}
}
}
return bitmap;
}
public byte [] bitmapToByteArray (Bitmap bitmap)
{
ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100,
baoStream);
return baoStream.toByteArray();
}
public void takePicture()
{
Log.d("ClassScanViewBarcodeActivity","takePicture()");
try {
if (isThereACamera) {
Log.d("ClassScanViewBarcodeActivity",
"setOnClickListener() isThereACamera: "
+ isThereACamera);
globalCamera.getParameters().setPictureFormat(ImageFormat.JPEG);
if ( globalFocusedBefore = true)
{
globalCamera.takePicture(null, null, jpegCallback);
globalFocusedBefore = false;
}
}
}
catch (Exception exc) {
if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;
}
Log.d("ClassScanViewBarcodeActivity setOnClickListener() exceprtion:",
exc.getMessage());
exc.printStackTrace();
}
}
}
Below is my preview class, which displays live images from the camera
package com.t.t.barcode;
package com.t.t.barcode;
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Context context;
private int guidanceRectangleStartX;
private int guidanceRectangleStartY;
private int guidanceRectangleEndX;
private int guidanceRectangleEndY;
private ImageView imageView = null;
private Bitmap guidanceScannerFrame = null;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
this.context = context;
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
setWillNotDraw(false);
setFocusable(true);
requestFocus();
guidanceScannerFrame = getBitmapFromResourcePath("res/drawable/scanner_frame.png");
}
public void drawGuidance(Canvas canvas)
{
Paint paintRed = new Paint();
paintRed.setStyle(Paint.Style.STROKE);
paintRed.setStrokeWidth(6f);
paintRed.setAntiAlias(true);
paintRed.setColor(Color.RED);
canvas.drawLine(0,this.getHeight()/2, this.getWidth(),this.getHeight()/2, paintRed);
if (guidanceScannerFrame!=null)
{
Paint paint = new Paint();
paint.setFilterBitmap(true);
int diffInWidth =0;
int diffInHeight = 0;
try
{
diffInWidth = this.getWidth() - guidanceScannerFrame.getScaledWidth(canvas);
diffInHeight = this.getHeight() - guidanceScannerFrame.getScaledHeight(canvas);
canvas.drawBitmap(guidanceScannerFrame,(diffInWidth/2),(diffInHeight/2) , paint);
}
catch (NullPointerException exc)
{
exc.printStackTrace();
}
Paint paintGray = new Paint();
paintGray.setStyle(Paint.Style.STROKE);
paintGray.setStrokeWidth(2f);
paintGray.setAntiAlias(true);
paintGray.setColor(Color.GRAY);
canvas.drawRect((diffInWidth/2), (diffInHeight/2), (diffInWidth/2)+guidanceScannerFrame.getScaledWidth(canvas),(diffInHeight/2)+guidanceScannerFrame.getScaledHeight(canvas), paintGray);
this.guidanceRectangleStartX = this.getWidth()/12;
this.guidanceRectangleStartY= this.getHeight()/3;
this.guidanceRectangleEndX = this.getWidth()-this.getWidth()/12;
this.guidanceRectangleEndY =(this.getHeight()/3)+( 2 *(this.getHeight()/3));
}
}
@Override
public void onDraw(Canvas canvas) {
drawGuidance(canvas);
}
public void surfaceCreated(SurfaceHolder holder) {
try {
Camera.Parameters p = mCamera.getParameters();
int SurfaceViewWidth = this.getWidth();
int SurfaceViewHeight = this.getHeight();
List<Size> sizes = p.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, SurfaceViewWidth, SurfaceViewHeight);
p.setPreviewSize(optimalSize.width, optimalSize.height);
p.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
mCamera.setDisplayOrientation(90);
mCamera.setParameters(p);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
}
@SuppressLint("InlinedApi")
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (mHolder.getSurface() == null) {
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
}
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d("CameraPreview , surfaceCreated() , orientation: ",
String.valueOf(e.getMessage()));
}
}
static Size getOptimalPreviewSize(List <Camera.Size>sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
final double MAX_DOWNSIZE = 1.5;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
double downsize = (double) size.width / w;
if (downsize > MAX_DOWNSIZE) {
continue;
}
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
double downsize = (double) size.width / w;
if (downsize > MAX_DOWNSIZE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public Bitmap getBitmapFromResourcePath (String path)
{
InputStream in =null;
Bitmap guidanceBitmap = null;
try
{
if (path!=null)
{
in = this.getClass().getClassLoader().getResourceAsStream(path);
guidanceBitmap = BitmapFactory.decodeStream(in);
}
}
catch (Exception exc)
{
exc.printStackTrace();
}
finally
{
if (in!=null)
{
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return guidanceBitmap;
}
public int getGuidanceRectangleStartX() {
return guidanceRectangleStartX;
}
public int getGuidanceRectangleStartY() {
return guidanceRectangleStartY;
}
public int getGuidanceRectangleEndX() {
return guidanceRectangleEndX;
}
public int getGuidanceRectangleEndY() {
return guidanceRectangleEndY;
}
}
GUI Activity Screenshots:

Any help would be appreciated, thanks.