Android: trying to call virtual method (onTouch) on null object reference
I am trying to set up gesture detection on one of the line layouts in a view in my application. The problem is my apps crash every time I test it with gestures. The error message I'm getting is the notorious "trying to call a virtual method on a null object reference". I have done some research and I understand that the problem is with trying to call methods on the Activity that are not properly propagated to the desired scope within the same code. That being said, I don't understand how to fix this in my code. Here are the relevant bits of code:
Playfrets.java
public class PlayFrets extends Activity {
LinearLayout gestureOverlay;
GestureListener gestureListener;
public void configGestureRecognition(){ //Toolbar gesture recognition
gestureOverlay = (LinearLayout) findViewById(R.id.toolbarGestureOverlay);
gestureListener = new GestureListener(PlayFrets.this);
if (gestureOverlay == null){
Toast.makeText(PlayFrets.this, "gestureOverlay object is null bro" ,Toast.LENGTH_SHORT).show();
}
gestureOverlay.setOnTouchListener(gestureListener);
}
}
LoadNoteFiles.java
public class LoadNoteFiles extends AsyncTask<Void, Void, Void>{
private Context mContext;
Activity instance;
public LoadNoteFiles(Context context){ //constructor
mContext = context;
}
@Override
protected void onPreExecute(){
PlayFrets.viewSwitch = new ViewSwitcher(mContext);
PlayFrets.viewSwitch.addView(ViewSwitcher.inflate(mContext, R.layout.splash_screen, null));
instance = (Activity)mContext; //cast context from main activity into an activity to access setContentView method
instance.setContentView(PlayFrets.viewSwitch);
}
...//do in background code omitted
@Override
protected void onPostExecute(Void v){
PlayFrets.viewSwitch.addView(ViewSwitcher.inflate(mContext, R.layout.activity_play_frets, null));
PlayFrets.viewSwitch.showNext();
((PlayFrets)mContext).configFretboard();
((PlayFrets)mContext).configGestureRecognition(); //test gesture recognition
}
GestureListener.java
class GestureListener extends SimpleOnGestureListener implements OnTouchListener {
Context mContext;
GestureDetector gDetector;
static final double SWIPE_MIN_DISTANCE = PlayFrets.getActualHeight()*(0.80); //must swipe across at least 80% of screen height to register a gesture
static final int SWIPE_MAX_OFF_PATH = 150;
static final int SWIPE_THRESHOLD_VELOCITY = 300;
public GestureListener(Context context) {
this.mContext = context;
}
public GestureListener(Context c, AttributeSet attrs) {
super();
}
public GestureListener(Context context, GestureDetector gDetector) {
if (gDetector == null){
gDetector = new GestureDetector(context, this);
}
this.mContext = context;
this.gDetector = gDetector;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
//Log.e("gesture", String.valueOf(SWIPE_MIN_DISTANCE));
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH|| Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) {
return false;
}
else if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE) {
//float traveled = e1.getY() - e2.getY();
//Toast.makeText(context, Float.toString(traveled) + ">" +String.valueOf(SWIPE_MIN_DISTANCE),Toast.LENGTH_SHORT).show();
Toast.makeText(mContext, "Swiped Up",Toast.LENGTH_SHORT).show();
}
else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE) {
//float traveled = e2.getY() - e1.getY();
//Toast.makeText(context, Float.toString(traveled) + ">" +String.valueOf(SWIPE_MIN_DISTANCE),Toast.LENGTH_SHORT).show();
Toast.makeText(mContext, "Swiped Down",Toast.LENGTH_SHORT).show();
}
}
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gDetector.onTouchEvent(event);
}
public GestureDetector getDetector() {
return gDetector;
}
}
Do I need to use a different constructor for GestureListener.java in order to properly pass the action instance? What exactly calls the onTouch () method to call the null object? Below is a log describing the error.
log file
06-15 21:59:46.721: E/InputEventReceiver(6972): Exception dispatching input event.
06-15 21:59:46.721: E/MessageQueue-JNI(6972): Exception in MessageQueue callback: handleReceiveCallback
06-15 21:59:46.741: E/MessageQueue-JNI(6972): java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.view.GestureDetector.onTouchEvent(android.view.MotionEvent)' on a null object reference
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at com.example.guitarsim.GestureListener.onTouch(GestureListener.java:59)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.View.dispatchTouchEvent(View.java:8914)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2673)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2385)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2684)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2346)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2552)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1767)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.app.Activity.dispatchTouchEvent(Activity.java:2840)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2513)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.View.dispatchPointerEvent(View.java:9125)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4636)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4474)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4024)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4077)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4043)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4157)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4051)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4214)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4024)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4077)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4043)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4051)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4024)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6485)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6384)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6355)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6575)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.os.MessageQueue.nativePollOnce(Native Method)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.os.MessageQueue.next(MessageQueue.java:143)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.os.Looper.loop(Looper.java:130)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at android.app.ActivityThread.main(ActivityThread.java:5835)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at java.lang.reflect.Method.invoke(Native Method)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at java.lang.reflect.Method.invoke(Method.java:372)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
source to share
Learn to read the logarithm, it tells you what the problem is ...
06-15 21:59:46.741: E/MessageQueue-JNI(6972): java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.view.GestureDetector.onTouchEvent(android.view.MotionEvent)' on a null object reference
06-15 21:59:46.741: E/MessageQueue-JNI(6972): at com.example.guitarsim.GestureListener.onTouch(GestureListener.java:59)
The problem is line 59 of your class GestureListener
in the method onTouch(...)
...
@Override
public boolean onTouch(View v, MotionEvent event) {
return gDetector.onTouchEvent(event);
}
Basically yours gDetector
should be null and there is an attempt to call its method onTouchEvent(...)
calling NPE.
The problem is that you are instantiating GestureListener
in your method Activity
configGestureRecognition()
like this ...
gestureListener = new GestureListener(PlayFrets.this);
Constructor version GestureListener(Context context)
does not initializeGestureDetector
Use a constructor that takes GestureDetector
as a parameter ...
public GestureListener(Context context, GestureDetector gDetector) {...}
... and either pass initialized GestureDetector
or null
so it can build GestureDetector
for you.
source to share