Voglio sapere come eseguire un trascinamento su Android basato sulle coordinate X, Y del mouse? considera come due semplici esempi, il Team Viewer / QuickSupport che disegna rispettivamente il "modello di password" sullo smartphone remoto e la Penna di Windows Paint.
Tutto quello che sono in grado di fare è simulare il tocco (con dispatchGesture()
e anche AccessibilityNodeInfo.ACTION_CLICK
).
Ho trovato questi collegamenti rilevanti, ma non so se possono essere utili:
Di seguito è riportato il mio codice di lavoro che viene utilizzato per inviare le coordinate del mouse (all'interno del PictureBox
controllo) al telefono remoto e simulare il tocco.
Applicazione Windows Form:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
foreach (ListViewItem item in lvConnections.SelectedItems)
{
// Remote screen resolution
string[] tokens = item.SubItems[5].Text.Split('x'); // Ex: 1080x1920
int xClick = (e.X * int.Parse(tokens[0].ToString())) / (pictureBox1.Size.Width);
int yClick = (e.Y * int.Parse(tokens[1].ToString())) / (pictureBox1.Size.Height);
Client client = (Client)item.Tag;
if (e.Button == MouseButtons.Left)
client.sock.Send(Encoding.UTF8.GetBytes("TOUCH" + xClick + "<|>" + yClick + Environment.NewLine));
}
}
Modificare:
Il mio ultimo tentativo è stato una "schermata di scorrimento" utilizzando le coordinate del mouse (Applicazione Windows Forms C #) e una routine Android personalizzata (con riferimento al codice di "schermata di scorrimento" collegato sopra), rispettivamente:
private Point mdownPoint = new Point();
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
foreach (ListViewItem item in lvConnections.SelectedItems)
{
// Remote screen resolution
string[] tokens = item.SubItems[5].Text.Split('x'); // Ex: 1080x1920
Client client = (Client)item.Tag;
if (e.Button == MouseButtons.Left)
{
xClick = (e.X * int.Parse(tokens[0].ToString())) / (pictureBox1.Size.Width);
yClick = (e.Y * int.Parse(tokens[1].ToString())) / (pictureBox1.Size.Height);
// Saving start position:
mdownPoint.X = xClick;
mdownPoint.Y = yClick;
client.sock.Send(Encoding.UTF8.GetBytes("TOUCH" + xClick + "<|>" + yClick + Environment.NewLine));
}
}
}
private void PictureBox1_MouseMove(object sender, MouseEventArgs e)
{
foreach (ListViewItem item in lvConnections.SelectedItems)
{
// Remote screen resolution
string[] tokens = item.SubItems[5].Text.Split('x'); // Ex: 1080x1920
Client client = (Client)item.Tag;
if (e.Button == MouseButtons.Left)
{
xClick = (e.X * int.Parse(tokens[0].ToString())) / (pictureBox1.Size.Width);
yClick = (e.Y * int.Parse(tokens[1].ToString())) / (pictureBox1.Size.Height);
client.sock.Send(Encoding.UTF8.GetBytes("MOUSESWIPESCREEN" + mdownPoint.X + "<|>" + mdownPoint.Y + "<|>" + xClick + "<|>" + yClick + Environment.NewLine));
}
}
}
Android AccessibilityService :
public void Swipe(int x1, int y1, int x2, int y2, int time) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
System.out.println(" ======= Swipe =======");
GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
Path path = new Path();
path.moveTo(x1, y1);
path.lineTo(x2, y2);
gestureBuilder.addStroke(new GestureDescription.StrokeDescription(path, 100, time));
dispatchGesture(gestureBuilder.build(), new GestureResultCallback() {
@Override
public void onCompleted(GestureDescription gestureDescription) {
System.out.println("SWIPE Gesture Completed :D");
super.onCompleted(gestureDescription);
}
}, null);
}
}
che produce il seguente risultato (ma non è ancora in grado di disegnare "pattern password" come ad esempio TeamViewer). Ma come detto nel commento qui sotto, penso che con un approccio simile questo possa essere ottenuto probabilmente con gesti continui . Eventuali suggerimenti in questa direzione saranno i benvenuti.
Modifica 2:
Sicuramente, la soluzione è gesti continui come detto nella precedente modifica .
- Simulazione del movimento del joystick tramite AccessibilityService
- Perché la funzione continueStroke non funziona
E sotto c'è un presunto codice fisso che ho trovato qui =>
Android AccessibilityService:
// Simulates an L-shaped drag path: 200 pixels right, then 200 pixels down.
Path path = new Path();
path.moveTo(200,200);
path.lineTo(400,200);
final GestureDescription.StrokeDescription sd = new GestureDescription.StrokeDescription(path, 0, 500, true);
// The starting point of the second path must match
// the ending point of the first path.
Path path2 = new Path();
path2.moveTo(400,200);
path2.lineTo(400,400);
final GestureDescription.StrokeDescription sd2 = sd.continueStroke(path2, 0, 500, false); // 0.5 second
HongBaoService.mService.dispatchGesture(new GestureDescription.Builder().addStroke(sd).build(), new AccessibilityService.GestureResultCallback(){
@Override
public void onCompleted(GestureDescription gestureDescription){
super.onCompleted(gestureDescription);
HongBaoService.mService.dispatchGesture(new GestureDescription.Builder().addStroke(sd2).build(),null,null);
}
@Override
public void onCancelled(GestureDescription gestureDescription){
super.onCancelled(gestureDescription);
}
},null);
Quindi, il mio dubbio è: come inviare correttamente le coordinate del mouse per il codice sopra, del modo in cui può eseguire il trascinamento in qualsiasi direzione? Qualche idea?
Modifica 3:
Ho trovato due routine che vengono utilizzate per eseguire il trascinamento, ma utilizzano UiAutomation + injectInputEvent()
. AFAIK, l'iniezione dell'evento funziona solo in un'app di sistema come quella qui e qui e non la voglio.
Queste sono le routine trovate:
- swipe pubblico booleano (int downX, int downY, int upX, int upY, int steps, boolean drag)
- colpo booleano pubblico (segmenti Point [], int segmentSteps)
Quindi per raggiungere il mio obiettivo, penso che la seconda routine sia più appropriata da usare (seguendo la logica, esclusa l'iniezione di eventi) con il codice mostrato su Modifica 2 e invio di tutti i punti pictureBox1_MouseDown
e pictureBox1_MouseMove
(Applicazione Windows Forms #) rispettivamente da riempire in Point[]
modo dinamico e su pictureBox1_MouseUp
invio cmd per eseguire la routine e utilizzare questo array riempito. Se hai un'idea della prima routine, fammi sapere: D.
Se dopo aver letto questo Modifica hai una possibile soluzione, mostrami in una risposta per favore, mentre proverò a testare questa idea.
StrokeDescription.continueStroke()
possa essere una soluzione probabile. Vedi la sezione Gesti continui qui .
pictureBox1_MouseDown
non deve inviare le coordinate. Dovrebbe solo memorizzare le coordinate iniziali e poi pictureBox1_MouseUp
inviarle, perché ciò segna la fine del movimento del mouse