Firstly, I'm crap at English.
I'm working on a project which uses Android camera.
My team is using CWAC-camera, so does my project.
So far I think it's really good. I'm displaying the preview of my camera. The thing is, when I try to close the application (with the physical "return" button), it crashes. Not always.
In fact it seems it's crashing when I'm closing BEFORE the src.release() in CameraPreviewFragment. However, if I close the app after the src.release(), it seems it's working well. It's not 100% sure, I said that thanks to the loggers.
Here is the error :
5529-5529/net.personal.opencv_tester W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41a222a0)
06-10 10:04:50.960 30241-30241/net.personal.opencv_tester E/MINE DEBUG﹕ Beginning
06-10 10:04:51.015 30241-30241/net.personal.opencv_tester E/MINE DEBUG﹕ Just Before Release
06-10 10:04:51.015 30241-30241/net.personal.opencv_tester E/MINE DEBUG﹕ Just After Release
06-10 10:04:51.015 30241-30241/net.personal.opencv_tester E/MINE DEBUG﹕ End
06-10 10:04:51.555 30241-30241/net.personal.opencv_tester E/AndroidRuntime﹕
FATAL EXCEPTION: main
> java.lang.RuntimeException: Method called after release()
at android.hardware.Camera.setHasPreviewCallback(Native Method)
at android.hardware.Camera.access$600(Camera.java:139)
at android.hardware.Camera$EventHandler.handleMessage(Camera.java:867)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:5419)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862)
at dalvik.system.NativeStart.main(Native Method)
And here is when it works:
06-10 10:06:56.480 32508-32508/net.personal.opencv_tester E/MINE DEBUG﹕ Beginning
06-10 10:06:56.495 32508-32508/net.personal.opencv_tester E/MINE DEBUG﹕ Just Before Release
06-10 10:06:56.495 32508-32508/net.personal.opencv_tester E/MINE DEBUG﹕ Just After Release
06-10 10:06:56.495 32508-32508/net.personal.opencv_tester E/MINE DEBUG﹕ End
06-10 10:06:57.225 32508-32508/net.personal.opencv_tester E/MINE DEBUG﹕ On detach
Here's my code :
MainActivity.java
package net.personal.opencv_tester;
import org.opencv.android.OpenCVLoader;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;
import com.commonsware.cwac.camera.CameraHost;
import com.commonsware.cwac.camera.CameraHostProvider;
import com.commonsware.cwac.camera.SimpleCameraHost;
public class MainActivity
extends Activity
implements CameraHostProvider
{
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate( Bundle savedInstanceState )
{
super.onCreate( savedInstanceState );
requestWindowFeature( Window.FEATURE_NO_TITLE );
getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN );
setContentView( R.layout.activity_main );
}
static {
if (!OpenCVLoader.initDebug()) {
// Handle initialization error
}
}
@Override
public CameraHost getCameraHost()
{
SimpleCameraHost.Builder builder =
new SimpleCameraHost.Builder( new CustomCameraHost( this ) );
builder.useFullBleedPreview( true );
return builder.build();
}
}
CustomCameraHost.java
package net.personal.opencv_tester;
import java.io.File;
import android.content.Context;
import com.commonsware.cwac.camera.SimpleCameraHost;
public class CustomCameraHost
extends SimpleCameraHost
{
private final File outFile;
public CustomCameraHost( File outFile, Context context )
{
super( context );
this.outFile = outFile;
}
public CustomCameraHost( Context context )
{
super( context );
this.outFile = new File(context.getFilesDir(), "test.jpg");
}
@Override
public boolean useSingleShotMode()
{
return true;
}
@Override
protected File getPhotoPath()
{
return outFile;
}
@Override
protected boolean scanSavedImage()
{
return false;
}
}
And finally, where the bug is situated:
CameraPreviewFragment.java
package net.personal.opencv_tester;
import org.opencv.core.Core;
[...]
import com.commonsware.cwac.camera.CameraFragment;
import com.commonsware.cwac.camera.CameraView;
import com.jjoe64.graphview.BarGraphView;
import com.jjoe64.graphview.GraphView;
public class CameraPreviewFragment
extends CameraFragment
implements Camera.PreviewCallback, SensorEventListener, OnClickListener
{
private CameraView mCameraView;
private TextView mTextView;
private GraphView mGraphView;
private TextView mInfosTextView;
private long mLastCheck = System.currentTimeMillis();
@Override
public void onAttach( Activity activity )
{
Log.e("MINE DEBUG", "On attach");
super.onAttach( activity );
}
@Override
public void onDetach()
{
Log.e("MINE DEBUG", "On detach");
super.onDetach();
}
@Override
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState )
{
View view = LayoutInflater.from( getActivity() ).inflate( R.layout.fragment_preview, container, false );
view.setOnClickListener( this );
mTextView = ( TextView ) view.findViewById( R.id.cameraWarningTextView );
mCameraView = ( CameraView ) view.findViewById( R.id.cameraSurfaceView );
mCameraView.setHost( getHost() );
//Camera.open(getHost().getCameraId()).setOneShotPreviewCallback(this);
mCameraView.setPreviewCallback( this );
setCameraView( mCameraView );
FrameLayout graphLayout = ( FrameLayout ) view.findViewById( R.id.cameraHistLayout );
mGraphView = new BarGraphView( getActivity(), "Histogram" );
mGraphView.getGraphViewStyle().setTextSize( 17f );
mGraphView.getGraphViewStyle().setHorizontalLabelsColor( 0xffffffff );
mGraphView.getGraphViewStyle().setVerticalLabelsColor( 0xffffffff );
mGraphView.setVisibility( View.GONE );
graphLayout.addView( mGraphView );
mInfosTextView = ( TextView ) view.findViewById( R.id.cameraInfosTextView );
mInfosTextView.setVisibility( View.GONE );
return view;
}
@Override
public void onClick( View v )
{
autoFocus();
}
@Override
public void onSensorChanged( SensorEvent event )
{
}
@Override
public void onAccuracyChanged( Sensor sensor, int accuracy )
{
}
@Override
public void onPreviewFrame( byte[] data, Camera camera )
{
Log.e("MINE DEBUG", "Begining");
long now = System.currentTimeMillis();
// Check an image every 500ms
if (mLastCheck + 500 > now) {
return;
}
mLastCheck = now;
int frameHeight = camera.getParameters().getPreviewSize().height;
int frameWidth = camera.getParameters().getPreviewSize().width;
// Create default grayscale matrix
Mat src = new Mat( frameHeight, frameWidth, CvType.CV_8UC1 );
src.put( 0, 0, data );
// Resize if image is too large (for performances)
if (src.width() > 640) {
double ratio = ( double ) src.width() / ( double ) src.height();
Imgproc.resize( src, src, new Size( 640, 640 / ratio ), 0, 0, Imgproc.INTER_LINEAR );
}
// Remove noise
Imgproc.GaussianBlur( src, src, new Size( 3, 3 ), 0.5 );
try {
mTextView.setText( "Valid image" );
mTextView.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.ic_capture_ok), null,
null, null);
} finally {
Log.e("CHECK DEBUG", "Just Before Release");
src.release();
Log.e("CHECK DEBUG", "Just After Release");
}
Log.e("MINE DEBUG", "End");
}
}
I browed StackOverflow and found a "fix", but it isn't working
mCameraView.setPreviewCallback(null);
Thank you very much for your patience. I can't find the fix.