6

I want to accomplish following:

I have two buttons. When first button is pressed,
it will fire onTouchEvent on second button, thus pressing second button.

Here is the excerpt of code that fires event:

int test1[] = new int[2];
button2.getLocationInWindow(test1);   //--->getting coordinates of second button
Instrumentation m_Instrumentation = new Instrumentation();
//firing event
m_Instrumentation.sendPointerSync(MotionEvent.obtain(android.os.SystemClock.uptimeMillis(),android.os.SystemClock.uptimeMillis(),MotionEvent.ACTION_DOWN,test1[0]+10, test1[1]+10, 0));

Note: I use genymotion emulator.

Error log:

07-08 12:47:38.743: E/InputEventReceiver(6849): Exception dispatching input event.
07-08 12:47:38.743: E/MessageQueue-JNI(6849): Exception in MessageQueue callback: handleReceiveCallback
07-08 12:47:38.743: E/MessageQueue-JNI(6849): java.lang.RuntimeException: This method can not be called from the main application thread
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.app.Instrumentation.validateNotAppThread(Instrumentation.java:1651)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.app.Instrumentation.sendPointerSync(Instrumentation.java:933)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at com.example.touchtest1.MainActivity.fireEvent(MainActivity.java:55)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at com.example.touchtest1.MainActivity$MyTouchListener.onTouch(MainActivity.java:75)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.View.dispatchTouchEvent(View.java:7701)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2068)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1515)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.dispatchTouchEvent(ActionBarActivityDelegateICS.java:260)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2016)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.View.dispatchPointerEvent(View.java:7886)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at  android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3954)
07-08 12:47:38.743: E/MessageQueue-JNI(6849):   at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3833)

However, it is not going as intended. Where can be problem?

With regards

nurgasemetey
  • 752
  • 3
  • 15
  • 39

2 Answers2

3

Based on the error and the excerpt at the bottom of this documentation, it looks like you can't run this on the main thread (in other words, the UI thread).

A possible solution would be to run it in another thread. It would look like this:

int test1[] = new int[2];
button2.getLocationInWindow(test1);   //--->getting coordinates of second button
final Instrumentation m_Instrumentation = new Instrumentation();
//firing event

new Thread(new Runnable() {
    @Override
    public void run() {
        m_Instrumentation.sendPointerSync(MotionEvent.obtain(
               android.os.SystemClock.uptimeMillis(),
               android.os.SystemClock.uptimeMillis(),
               MotionEvent.ACTION_DOWN,test1[0]+10, test1[1]+10, 0));
    }
}).start();

Note that I changed your m_Instrumentation to a final variable so that it could be used in a different thread.

Andrew Schuster
  • 3,229
  • 2
  • 21
  • 32
0

Instrumentation can't work on main (UI) thread.

You can try to implement an AsyncTask class which can do the work for you in background. After implementation, all you need is to call it from a method in your class;

 private void CREATE_EVENT()
 {
    long action_time = SystemClock.uptimeMillis();

    //MotionEvent.obtain(long downTime, long eventTime, int action, float x, float y, int metaState);
    MotionEvent motion_event = MotionEvent.obtain(action_time, action_time, MotionEvent.ACTION_DOWN, 250, 150, 0); 

    new INJECT_EVENTS().execute(motion_event);
  }

 public class INJECT_EVENTS extends AsyncTask<MotionEvent, MotionEvent, MotionEvent>
 {
    @Override
    protected MotionEvent doInBackground(MotionEvent ... event) {

        Instrumentation inject_event = new Instrumentation();
        event[0].recycle();
        inject_event.sendPointerSync(event[0]);
        Log.i("TEST", event[0].toString() + " __________________________EVENT CREATED!");
        return null;
    }
 }
Burak Day
  • 907
  • 14
  • 28