I have created an application where i have a camera preview. I am trying to create a touch event such that when i touch the preview, something will happen (let say, a toast will appear).
The problem is that when i am touching the preview, after 2 seconds the application crashes.
I have two classes:
CameraActivity:
public class CameraActivity extends Activity {
private static final String TAG = "CameraDemo";
Preview preview;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
preview = new Preview(this);
((FrameLayout) findViewById(R.id.preview)).addView(preview);
((FrameLayout) findViewById(R.id.preview)).setOnTouchListener(preview);
Log.d(TAG, "Camera Activity Created.");
}
}
and Preview:
class Preview extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
private static final String TAG = "Preview";
SurfaceHolder mHolder;
public Camera camera;
Preview(Context context) {
super(context);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
// Called once the holder is ready
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
camera.setDisplayOrientation(90);
camera.setPreviewDisplay(holder);
camera.setPreviewCallback(new PreviewCallback() {
// Called for each frame previewed
public void onPreviewFrame(byte[] data, Camera camera) {
Log.d(TAG, "onPreviewFrame called at: " + System.currentTimeMillis());
Preview.this.invalidate();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
// Called when the holder is destroyed
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
// Called when holder has changed
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
camera.startPreview();
}
public boolean onTouch(View v, MotionEvent event) {
Toast.makeText(findViewById(R.id.preview).getContext(), "BEFORE SHUTTER", Toast.LENGTH_LONG).show();
return false;
}
}
Can someone please help and tell me what i am doing wrong?
Here is the LogCat (the part where the crash appears):
03-08 12:11:48.335: D/AndroidRuntime(1167): Shutting down VM
03-08 12:11:48.335: W/dalvikvm(1167): threadid=1: thread exiting with uncaught exception (group=0x40015578)
03-08 12:11:48.343: E/AndroidRuntime(1167): FATAL EXCEPTION: main
03-08 12:11:48.343: E/AndroidRuntime(1167): java.lang.NullPointerException
03-08 12:11:48.343: E/AndroidRuntime(1167): at com.marakana.Preview.onTouch(Preview.java:80)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.View.dispatchTouchEvent(View.java:3934)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:903)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:869)
03-08 12:11:48.343: E/AndroidRuntime(1167): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1733)
03-08 12:11:48.343: E/AndroidRuntime(1167): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1151)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.app.Activity.dispatchTouchEvent(Activity.java:2096)
03-08 12:11:48.343: E/AndroidRuntime(1167): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1717)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2215)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.view.ViewRoot.handleMessage(ViewRoot.java:1886)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.os.Handler.dispatchMessage(Handler.java:99)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.os.Looper.loop(Looper.java:123)
03-08 12:11:48.343: E/AndroidRuntime(1167): at android.app.ActivityThread.main(ActivityThread.java:3687)
03-08 12:11:48.343: E/AndroidRuntime(1167): at java.lang.reflect.Method.invokeNative(Native Method)
03-08 12:11:48.343: E/AndroidRuntime(1167): at java.lang.reflect.Method.invoke(Method.java:507)
03-08 12:11:48.343: E/AndroidRuntime(1167): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
03-08 12:11:48.343: E/AndroidRuntime(1167): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
03-08 12:11:48.343: E/AndroidRuntime(1167): at dalvik.system.NativeStart.main(Native Method)
03-08 12:11:48.378: D/dalvikvm(1167): GC_FOR_MALLOC freed 943K, 59% free 2633K/6407K, external 1596K/2108K, paused 15ms
03-08 12:11:48.531: D/dalvikvm(1167): GC_CONCURRENT freed 21K, 52% free 3084K/6407K, external 1596K/2108K, paused 2ms+26ms
03-08 12:11:56.109: I/Process(1167): Sending signal. PID: 1167 SIG: 9
Thanks
You have an issue with context
You cannot get context this way. In your constructor you pass in context:
I would create a private instance of context
and then in the constructor add
and then change the toast message to
This will also give you context in most other places in your class too therefore making life a little easier.