Above android 2.3 we can use the method 'obtain' to get multitouch event.
public static MotionEvent obtain (long downTime, long eventTime, int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords, int metaState, float xPrecision, float yPrecision, int deviceId, int edgeFlags, int source, int flags)
//action is an int variable indicate what event type to send. (DOWN, UP, POINIT_DOWN....) //point is an PointF array to indecate all coordinates touch on screen.
int[] pointCoordsID = new int[point.length];
PointerCoords[] pointCoords = new PointerCoords[point.length];
for (int i = 0; i < point.length; i++)
{
pointerIds[i] = i;
pointerCoords[i] = new PointerCoords();
pointerCoords[i].x = point[i].x;
pointerCoords[i].y = point[i].y;
}
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, point.lenth, pointCoordsID, pointCoords, 0, 1, 1, 0, 0, 0, 0);
#########################################################
If your device or sdk is android 2.2 or lower, you have to create MotionEvent from Parcel as below to perform it.
//action is an int variable indicate what event type to send. (DOWN, UP, POINIT_DOWN....)
//point is an PointF array to indecate all coordinates touch on screen.
Parcel inParcel = Parcel.obtain();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
inParcel.writeLong(downTime); //DownTime
inParcel.writeLong(eventTime); //EventTime
inParcel.writeInt(action); //Action
inParcel.writeInt(0); //MetaState
inParcel.writeFloat(point[0].x); //RawX
inParcel.writeFloat(point[0].y); //RawY
final int NP = m_point.length; //NumPointers
inParcel.writeInt(NP);
final int NS = m_point.length; //NumSamples
inParcel.writeInt(NS);
final int NI = NP*NS;
if (NI > 0)
{
int i;
//set point index
for (i=0; i<NP; i++)
{
inParcel.writeInt(i);
}
// set location, pressure, size for each sampleData
int NUM_SAMPLE_DATA = 4;
final int ND = NI*NUM_SAMPLE_DATA;
float[] history = new float[ND];;
for (i = 0; i < m_point.length; i++)
{
history[i*NUM_SAMPLE_DATA] = point[i].x;
history[i*NUM_SAMPLE_DATA + 1] = point[i].y;
history[i*NUM_SAMPLE_DATA + 2] = 0;
history[i*NUM_SAMPLE_DATA + 3] = 0;
}
for (i=0; i<ND; i++)
{
inParcel.writeFloat(history[i]);
}
// set event time for each sampleData
for (i=0; i<NS; i++)
{
inParcel.writeLong(eventTime);
}
}
inParcel.writeFloat(1); //PrecisionX
inParcel.writeFloat(1); //PrecisionY
inParcel.writeInt(0); //DeviceID
inParcel.writeInt(0); //EdgeFlags
inParcel.setDataPosition(0);
MotionEvent event = MotionEvent.CREATOR.createFromParcel(inParcel);
###########################################
Reference:
http://stackoverflow.com/questions/3637044/generating-multitouch-motionevents-for-testing
Hi,
回覆刪除I reference your code to generate multitouch event for 2.3, but it still can't be generate. Here is my code.
PointerCoords[] coords = new PointerCoords[2];
int[] pointerIds = new int[2];
pointerIds[0] = 0;
pointerIds[1] = 1;
coords[0] = new PointerCoords();
coords[1] = new PointerCoords();
coords[0].x = 400;
coords[0].y = 200;
coords[1].x = 400;
coords[1].y = 380;
MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(),eventTime,MotionEvent. ACTION_POINTER_DOWN,2,pointerIds,coords,0,1,1,0,0,0,0);
inst.sendPointerSync(me);
eventTime+=500;
coords[0].y = 0;
coords[1].y += 120;
me = MotionEvent.obtain(SystemClock.uptimeMillis(),eventTime,MotionEvent.ACTION_MOVE,2,pointerIds,coords,0,1,1,0,0,0,0);
inst.sendPointerSync(me);
eventTime+=100;
me = MotionEvent.obtain(SystemClock.uptimeMillis(),eventTime,MotionEvent.ACTION_UP,2,pointerIds,coords,0,1,1,0,0,0,0);
inst.sendPointerSync(me);
I believe the problem is wrong action type.
回覆刪除I simulate the pinch gesture for zoom-in in turn as below.
ACTION_DOWN: the first finger down.
ACTION_POINTER_2_DOWN: the second finger down.
ACTION_MOVE: two fingers move to more closed.
ACTION_POINTER_1_UP: two fingers up simultaneously.
Hope it works for you.
hi , my sdk is 2.2, and my code like that, but it doesn't work
回覆刪除public MotionEvent constructMotionEvent(int action, Point[] point){
Parcel inParcel = Parcel.obtain();
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis();
inParcel.writeLong(downTime); //DownTime
inParcel.writeLong(eventTime); //EventTime
inParcel.writeInt(action); //Action
inParcel.writeInt(0); //MetaState
inParcel.writeFloat(0); //RawX
inParcel.writeFloat(0); //RawY
final int NP = point.length; //NumPointers
inParcel.writeInt(NP);
final int NS = point.length; //NumSamples
inParcel.writeInt(NS);
final int NI = NP*NS;
if (NI > 0)
{
int i;
//set point index
for (i=0; i<NP; i++)
{
inParcel.writeInt(i);
}
// set location, pressure, size for each sampleData
int NUM_SAMPLE_DATA = 4;
final int ND = NI*NUM_SAMPLE_DATA;
float[] history = new float[ND];;
for (i = 0; i < point.length; i++)
{
history[i*NUM_SAMPLE_DATA] = point[i].x;
history[i*NUM_SAMPLE_DATA + 1] = point[i].y;
history[i*NUM_SAMPLE_DATA + 2] = 0;
history[i*NUM_SAMPLE_DATA + 3] = 0;
}
for (i=0; i<ND; i++)
{
inParcel.writeFloat(history[i]);
}
// set event time for each sampleData
for (i=0; i<NS; i++)
{
inParcel.writeLong(eventTime);
}
}
inParcel.writeFloat(1); //PrecisionX
inParcel.writeFloat(1); //PrecisionY
inParcel.writeInt(0); //DeviceID
inParcel.writeInt(0); //EdgeFlags
inParcel.setDataPosition(0);
MotionEvent event = MotionEvent.CREATOR.createFromParcel(inParcel);
return event;
}
MotionEvent event = constructMotionEvent(MotionEvent.ACTION_DOWN, ps);
inst.waitForIdleSync();
inst.sendPointerSync(event);
event = constructMotionEvent(MotionEvent.ACTION_UP, ps);
inst.waitForIdleSync();
inst.sendPointerSync(event);
i wanna click one point down, then second point down, release point_1, release point_2, but the code above only press the first point, i'm sure, the value points are both ok
I'm not sure, but try it.
刪除MotionEvent event = constructMotionEvent(MotionEvent.ACTION_DOWN, ps);
TheObjectActivity.dispatchTouchEvent(event);
inst.waitForIdleSync();
MotionEvent event = constructMotionEvent(MotionEvent.ACTION_POINTER_2_DOWN, ps);
TheObjectActivity.dispatchTouchEvent(event);
inst.waitForIdleSync();
MotionEvent event = constructMotionEvent(MotionEvent.ACTION_POINTER_1_UP, ps);
TheObjectActivity.dispatchTouchEvent(event);
inst.waitForIdleSync();