I am attempting to take a picture, and in the onPictureTaken I atempt to make some layout changes and then pass the image data to a new activity. When making layout changes the app crashes with an illegal argument error that traces back to the cameraworker CameraWorker thread running in javacameraview. Can anyone help JavaCameraView.
I know this is kind of long but I'm really stumped. I'd really appreciate any help.
The idea is like this: When the onPictureTaken is called i freeze the preview (to show the user the image he captured) and display an "ok" button and a "retry" button. However when I attempt to change the layout (i.e make the buttons visible) the app crashes wit the above error and the following stacktrace:
E/SurfaceHolder: Exception locking surface
java.lang.IllegalArgumentException
at android.view.Surface.nativeLockCanvas(Native Method)
at android.view.Surface.lockCanvas(Surface.java:267)
at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:973)
at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:941)
at org.opencv.android.CameraBridgeViewBase.deliverAndDrawFrame(CameraBridgeViewBase.java:405)
at org.opencv.android.JavaCameraView$CameraWorker.run(JavaCameraView.java:308)
at java.lang.Thread.run(Thread.java:818)
The methods are in CameraBridgeViewBase and are called via a thread that is running in JavaCameraView which is why I think this is a thread issue. Unfortunately I dont know where to go from here.
My methods that cause the crash are here:
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.i(TAG, "Saving a bitmap to file");
Toast.makeText(context,"Not Starting New Activity. Look at me now error!",Toast.LENGTH_LONG).show();;
//attempt to export all this to JavaCameraView, i have a feeling that there is a conflict with his thread....maybe that will help
buttonManager(data);
}
private void buttonManager(byte[] data) {
//find buttons
final byte[] img_data = data;
final int width = this.getWidth();
final int height = this.getHeight();
okButton.setVisibility(View.VISIBLE);
retryButton.setVisibility(View.VISIBLE);
captureImageButton.setVisibility(View.GONE);
okButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent startImgProc = new Intent(context,ImageProcessing.class);
startImgProc.putExtra("image",img_data);
startImgProc.putExtra("width",width);
startImgProc.putExtra("height",height);
disconnectCamera();
context.startActivity(startImgProc);
((Activity) context).finish();
}
});
retryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
captureImageButton.setVisibility(View.VISIBLE);
okButton.setVisibility(View.GONE);
retryButton.setVisibility(View.GONE);
}
});
}
The call to deliverAndDrawFrame is from JavaCameraView here:
private class CameraWorker implements Runnable {
@Override
public void run() {
do {
boolean hasFrame = false;
synchronized (JavaCameraView.this) {
try {
while (!mCameraFrameReady && !mStopThread) {
JavaCameraView.this.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
if (mCameraFrameReady)
{
mChainIdx = 1 - mChainIdx;
mCameraFrameReady = false;
hasFrame = true;
}
}
if (!mStopThread && hasFrame) {
if (!mFrameChain[1 - mChainIdx].empty())
deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]);
}
} while (!mStopThread);
Log.d(TAG, "Finish processing thread");
}
}
and the proper way to handle this issue?method itself
Any help would be immensely appreciated. For more information.
https://stackoverflow.com/questions/52076862/why-is-lockcanvas-throwing-illegal-argument-exceptions
protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
Mat modified;
if (mListener != null) {
modified = mListener.onCameraFrame(frame);
} else {
modified = frame.rgba();
}
boolean bmpValid = true;
if (modified != null) {
try {
Utils.matToBitmap(modified, mCacheBitmap);
} catch(Exception e) {
Log.e(TAG, "Mat type: " + modified);
Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
bmpValid = false;
}
}
if (bmpValid && mCacheBitmap != null) {
Canvas canvas = getHolder().lockCanvas();
if (canvas != null) {
canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
Log.d(TAG, "mStretch value: " + mScale);
if (mScale != 0) {
canvas.drawBitmap(mCacheBitmap, new Rect(0, 0, mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
new Rect((int) ((canvas.getWidth() - mScale * mCacheBitmap.getWidth()) / 2),
(int) ((canvas.getHeight() - mScale * mCacheBitmap.getHeight()) / 2),
(int) ((canvas.getWidth() - mScale * mCacheBitmap.getWidth()) / 2 + mScale * mCacheBitmap.getWidth()),
(int) ((canvas.getHeight() - mScale * mCacheBitmap.getHeight()) / 2 + mScale * mCacheBitmap.getHeight())), null);
} else {
canvas.drawBitmap(mCacheBitmap, new Rect(0, 0, mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
new Rect((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2,
(canvas.getWidth() - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(),
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null);
}
if (mFpsMeter != null) {
mFpsMeter.measure();
mFpsMeter.draw(canvas, 20, 30);
}
getHolder().unlockCanvasAndPost(canvas);
}
}