gpt4 book ai didi

java - Android camera , onPictureTaken(byte[] imgData, Camera camera) 方法和 PictureCallback 从未调用过

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:37:41 29 4
gpt4 key购买 nike

我有一个自定义相机应用程序,它在 SurfaceView 上预览相机视频输出并尝试拍照,照片应该由“xzing”扫描仪 API 处理以解码图像中的任何条形码。

我的应用程序预览正确并且没有抛出任何错误或预期,但是我的 onPictureTaken(byte[] imgData, Camera camera) 方法和 PictureCallback 从未被调用,因此我无法获取图像并继续进一步扫描。

下面是负责相机逻辑的 Activity 的实际代码。 onPictureTaken(byte[] imgData, Camera camera) 方法和 PictureCallback 都在这个类中(ScanVinFromBarcodeActivity.java) 见下文:

package com.ty.tyownerspoc.barcode;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.FormatException;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Point;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceView;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.ty.tyownerspoc.R;

public class ScanVinFromBarcodeActivity extends Activity {

private Camera globalCamera;
private int cameraId = 0;
private TextView VINtext = null;
private View scanButton = null;
// bitmap from camera
private Bitmap bmpOfTheImageFromCamera = null;
// global flag whether a camera has been detected
private boolean isThereACamera = false;
// surfaceView for preview object
private FrameLayout frameLayoutBarcodeScanner = null;
private CameraPreview newCameraPreview = null;
private SurfaceView surfaceViewBarcodeScanner = null;
private int counter = 0;
private volatile boolean finishedPictureTask = false;
/*
* This method , finds FEATURE_CAMERA, opens the camera, set parameters ,
* add CameraPreview to layout, set camera surface holder, start preview
*/
private void initializeGlobalCamera() {
try {
if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_CAMERA)) {
Toast.makeText(this, "No camera on this device",
Toast.LENGTH_LONG).show();
} else { // check for front camera ,and get the ID
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);
// camera was found , set global camera flag to true
isThereACamera = true;
// OPEN
globalCamera = Camera.open(cameraId);

// pass surfaceView to CameraPreview
newCameraPreview = new CameraPreview(this, globalCamera);
// pass CameraPreview to Layout
frameLayoutBarcodeScanner.addView(newCameraPreview);
try {
globalCamera
.setPreviewDisplay(surfaceViewBarcodeScanner
.getHolder());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// PREVIEW
globalCamera.startPreview();

Log.d("ClassScanViewBarcodeActivity",
"camera opened & previewing");
}
}// end else ,check for front camera
}// end try
catch (Exception exc) {

// in case of exception release resources & cleanup
if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;

}
Log.d("ClassScanViewBarcodeActivity initializeGlobalCamera() exception:",
exc.getMessage());
}// end catch
}

// onCreate, instantiates layouts & surfaceView used for video preview
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_barcode_vin_scanner);
Log.d("ClassScanViewBarcodeActivity", "onCreate ");

// create surfaceView for previewing of camera image
frameLayoutBarcodeScanner = (FrameLayout) findViewById(R.id.FrameLayoutForPreview);
surfaceViewBarcodeScanner = (SurfaceView) findViewById(R.id.surfaceViewBarcodeScanner);

initializeGlobalCamera();

// create text area & scan button
VINtext = (TextView) findViewById(R.id.mytext);
scanButton = findViewById(R.id.webbutton);
// on click listener, onClick take a picture
scanButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {

// if true take a picture
if (isThereACamera) {
Log.d("ClassScanViewBarcodeActivity",
"setOnClickListener() isThereACamera: "+ isThereACamera);

//set picture format to JPEG, everytime makesure JPEg callback is called
Parameters parameters = globalCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
globalCamera.setParameters(parameters);
//take pic , should call Callback
globalCamera.takePicture(null, null, jpegCallback);
// wait 1 sec , than start preview again
Thread.sleep(1000);
//STOP
globalCamera.stopPreview();
//start previewing again onthe SurfaceView in case use wants to take another pic/scan
globalCamera.startPreview();

}

}// end try
catch (Exception exc) {

// in case of exception release resources & cleanup
if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;

}
Log.d("ClassScanViewBarcodeActivity setOnClickListener() exceprtion:",
exc.getMessage());
}// end catch

}// end on Click
});// end OnClickListener() implementation

}// end onCreate

@Override
protected void onResume() {

Log.d("ClassScanViewBarcodeActivity, onResume() globalCamera:",
String.valueOf(globalCamera));

if (globalCamera != null) {
// START PREVIEW
globalCamera.startPreview();
} else {
initializeGlobalCamera();
}

super.onResume();
}

@Override
protected void onStop() {

if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;
}
super.onStop();
}

//callback used by takePicture()
PictureCallback jpegCallback = new PictureCallback() {



public void onPictureTaken(byte[] imgData, Camera camera) {
BinaryBitmap bitmap = null;
try {



Log.d("ClassScanViewBarcodeActivity" ,"onPictureTaken()");

//save image to sd card
savePicture(imgData);

// get the bitmap from camera imageData
bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
imgData, 0, imgData.length);


if (bmpOfTheImageFromCamera != null) {
//Galaxy S3 , incorrect rotation issue rotate to correct rotation
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera, 0, 0, bmpOfTheImageFromCamera.getWidth(), bmpOfTheImageFromCamera.getHeight(), matrix, true);
// convert bitmap to binary bitmap
bitmap = cameraBytesToBinaryBitmap(rotatedBitmap);


if (bitmap != null) {
// decode the VIN
String VIN = decodeBitmapToString(bitmap);
Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ",
VIN);
VINtext.setText(VIN);
} else {
Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=",String.valueOf(bitmap));

}
} else {
Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ",
String.valueOf(bmpOfTheImageFromCamera));

}
}// end try

catch (Exception exc) {
exc.getMessage();

Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ",
exc.getMessage());
}

}// end onPictureTaken()
};// jpegCallback implementation


/*
* created savePicture(byte [] data) for testing
*/
public void savePicture(byte [] data)
{
Log.d( "ScanVinFromBarcodeActivity " , "savePicture(byte [] data)");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "Picture_"+counter+"_"+ 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();
}
counter++;
}



private int findFrontFacingCamera() {
int cameraId = -1;
// Search for the front facing camera
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;
}// end findFrontFacingCamera()

@Override
protected void onPause() {
if (globalCamera != null) {
globalCamera.stopPreview();
globalCamera.setPreviewCallback(null);
globalCamera.release();
globalCamera = null;
}
super.onPause();
}// end onPause()

public String decodeBitmapToString(BinaryBitmap bitmap) {
Reader reader = null;
Result result = null;
String textResult = null;
try {

reader = new MultiFormatReader();
if (bitmap != null) {
result = reader.decode(bitmap);
if (result != null) {
textResult = result.getText();
} else {
Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): result = ",
String.valueOf(result));
}
} else {
Log.d("ClassScanViewBarcodeActivity , String decodeBitmapToString (BinaryBitmap bitmap): bitmap = ",
String.valueOf(bitmap));
}
/*
* byte[] rawBytes = result.getRawBytes(); BarcodeFormat format =
* result.getBarcodeFormat(); ResultPoint[] points =
* result.getResultPoints();
*/

} catch (NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ChecksumException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();

}

return textResult;
}// end decodeBitmapToString (BinaryBitmap bitmap)

public BinaryBitmap cameraBytesToBinaryBitmap(Bitmap bitmap) {
BinaryBitmap binaryBitmap = null;
if (bitmap != null) {

int[] pixels = new int[bitmap.getHeight() * bitmap.getWidth()];
bitmap.getPixels(pixels, 0, 0, bitmap.getWidth() - 1,
bitmap.getHeight() - 1, bitmap.getWidth(),
bitmap.getHeight());

RGBLuminanceSource source = new RGBLuminanceSource(
bitmap.getWidth(), bitmap.getHeight(), pixels);

HybridBinarizer bh = new HybridBinarizer(source);
binaryBitmap = new BinaryBitmap(bh);
} else {
Log.d("ClassScanViewBarcodeActivity , cameraBytesToBinaryBitmap (Bitmap bitmap): bitmap = ",
String.valueOf(bitmap));
}

return binaryBitmap;
}

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
/*
* The method getScreenOrientation() return screen orientation either
* landscape or portrait. IF width < height , than orientation = portrait,
* ELSE landscape For backwards compatibility we use to methods to detect
* the orientation. The first method is for API versions prior to 13 or
* HONEYCOMB.
*/
public int getScreenOrientation() {

int currentapiVersion = android.os.Build.VERSION.SDK_INT;
// if API version less than 13
Display getOrient = getWindowManager().getDefaultDisplay();
int orientation = Configuration.ORIENTATION_UNDEFINED;

if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
// Do something for API version less than 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 {
// Do something for API version greater or equal to HONEYCOMB

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;

}// end getScreenOrientation()
}// end class ScanVinFromBarcodeActivity

用于在 SurfaceView 上显示实时摄像头的预览类 (CameraPreview.java):

package com.ty.tyownerspoc.barcode;

import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.hardware.Camera.CameraInfo;

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Context context;

public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
this.context = context;

// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the
// preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {

}
}

public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.

if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}

// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
Camera.Parameters p = mCamera.getParameters();

// get width & height of the SurfaceView
int SurfaceViewWidth = this.getWidth();
int SurfaceViewHeight = this.getHeight();

List<Size> sizes = p.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, SurfaceViewWidth, SurfaceViewHeight);


// set parameters
p.setPreviewSize(optimalSize.width, optimalSize.height);

/*rotate the image by 90 degrees clockwise , in order to correctly displayed the image , images seem to be -90 degrees (counter clockwise) rotated
* I even tried setting it to p.setRotation(0); , but still no effect.
*/
mCamera.setDisplayOrientation(90);

mCamera.setParameters(p);

// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();

} catch (Exception e) {
Log.d("CameraPreview , surfaceCreated() , orientation: ",
String.valueOf(e.getMessage()));
}
}// end surfaceChanged()
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;

// Try to find an size match aspect ratio and size
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
double downsize = (double) size.width / w;
if (downsize > MAX_DOWNSIZE) {
//if the preview is a lot larger than our display surface ignore it
//reason - on some phones there is not enough heap available to show the larger preview sizes
continue;
}
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
//keep the max_downsize requirement
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);
}
}
}
//everything else failed, just take the closest match
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;
}

}//end Preview class

“ScanVinFromBarcodeActivity” Activity (activity_barcode_vin_scanner.xml) 的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="20dip" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="20dip"
android:text="@string/decode_label"
android:textColor="@color/mbackground1" />

<TextView
android:id="@+id/mytext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/mbackground2"
android:gravity="center_horizontal"
android:padding="20dip"
android:textColor="@color/mytextcolor" />

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="20dip"
android:text="@string/continue_label"
android:textColor="@color/mytextcolor" />

<Button
android:id="@+id/webbutton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/web_button"
android:textColor="@color/mytextcolor" />

<FrameLayout
android:id="@+id/FrameLayoutForPreview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">

<SurfaceView
android:id="@+id/surfaceViewBarcodeScanner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</FrameLayout>
</LinearLayout>

任何帮助将不胜感激。

谢谢

Updated & working onTakePicturen method, the that works , the PictureCallback returns (stopPreview & StartPreview were moved to inside this method in its finally block).


public void onPictureTaken(byte[] imgData, Camera camera) {
BinaryBitmap bitmap;
try {



Log.d("ClassScanViewBarcodeActivity" ,"onPictureTaken()");

//save image to sd card
savePicture(imgData);

// get the bitmap from camera imageData

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
//down sample
bmpOfTheImageFromCamera = BitmapFactory.decodeByteArray(
imgData, 0, imgData.length,options);


if (bmpOfTheImageFromCamera != null) {

Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): bmpOfTheImageFromCamera getByteCount(): ",
String.valueOf(bmpOfTheImageFromCamera.getByteCount()));
//Galaxy S3 , incorrect rotation issue rotate to correct rotation
/*Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bmpOfTheImageFromCamera, 0, 0, bmpOfTheImageFromCamera.getWidth(), bmpOfTheImageFromCamera.getHeight(), matrix, true);*/
// convert bitmap to binary bitmap
bitmap = cameraBytesToBinaryBitmap(bmpOfTheImageFromCamera);


if (bitmap != null) {
// decode the VIN
String VIN = decodeBitmapToString(bitmap);
Log.d("***ClassScanViewBarcodeActivity ,onPictureTaken(): VIN ",
VIN);
VINtext.setText(VIN);
} else {
Log.d("ClassScanViewBarcodeActivity ,onPictureTaken(): bitmap=",String.valueOf(bitmap));

}
} else {
Log.d("ClassScanViewBarcodeActivity , onPictureTaken(): bmpOfTheImageFromCamera = ",
String.valueOf(bmpOfTheImageFromCamera));

}


}// end try

catch (Exception exc) {
exc.getMessage();

Log.d("ClassScanViewBarcodeActivity , scanButton.setOnClickListener(): exception = ",
exc.getMessage());
}

finally
{
globalCamera.stopPreview();
//start previewing again onthe SurfaceView in case use wants to take another pic/scan
globalCamera.startPreview();
}

}// end onPictureTaken()
};// jpegCallback implementation

最佳答案

我能找到的唯一可能是罪魁祸首是您在 jpegCallback 返回之前再次开始预览。根据javadoc ,这是不允许的:

After calling this method, you must not call startPreview() or take another picture until the JPEG callback has returned.

回调实际上放在 UI 线程队列上 - 它将在您的 Thread.sleep() 中暂停并且同一线程将调用 stopPreview() 并且startPreview() 在真正进入回调之前。一般来说,如果您在 UI 线程上调用 Thread.sleep() - 您做错了。因此,希望如果您删除 sleep() 并将它后面的内容放入 jpegCallback 中,您的问题应该得到解决。

关于java - Android camera , onPictureTaken(byte[] imgData, Camera camera) 方法和 PictureCallback 从未调用过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19504893/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com