Come eseguire un trascinamento (basato sulle coordinate del mouse X, Y) su Android utilizzando AccessibilityService?


39

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.

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

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 PictureBoxcontrollo) 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.

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


Modifica 2:

Sicuramente, la soluzione è gesti continui come detto nella precedente modifica .

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:

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_MouseDowne pictureBox1_MouseMove(Applicazione Windows Forms #) rispettivamente da riempire in Point[]modo dinamico e su pictureBox1_MouseUpinvio 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.


1
TeamViewer non utilizza il framework di accessibilità, molto probabilmente. Hanno accordi speciali con i produttori di dispositivi, motivo per cui il loro prodotto non è disponibile per tutti i dispositivi.
CommonsWare il

@CommonsWare grazie. Ma penso che StrokeDescription.continueStroke()possa essere una soluzione probabile. Vedi la sezione Gesti continui qui .
BrowJr

2
Per quanto riguarda il tuo primo approccio. pictureBox1_MouseDownnon deve inviare le coordinate. Dovrebbe solo memorizzare le coordinate iniziali e poi pictureBox1_MouseUpinviarle, perché ciò segna la fine del movimento del mouse
Greggz,

Risposte:


1

Ecco un esempio di una soluzione basata su Modifica 3 della domanda.


Applicazione Windows Froms " formMain.cs " in C # :

using System.Net.Sockets;

private List<Point> lstPoints;

private void pictureBox1_MouseDown(object sender, MouseEventArgs e) 
{
    if (e.Button == MouseButtons.Left)
    {
        lstPoints = new List<Point>();
        lstPoints.Add(new Point(e.X, e.Y));
    }
}

private void PictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        lstPoints.Add(new Point(e.X, e.Y));
    }
}

private void PictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    lstPoints.Add(new Point(e.X, e.Y));

    StringBuilder sb = new StringBuilder();

    foreach (Point obj in lstPoints)
    {
        sb.Append(Convert.ToString(obj) + ":");
    }

    serverSocket.Send("MDRAWEVENT" + sb.ToString() + Environment.NewLine);
}

servizio Android " SocketBackground.java ":

import java.net.Socket;

String xline;

while (clientSocket.isConnected()) {

    BufferedReader xreader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8));

    if (xreader.ready()) {

        while ((xline = xreader.readLine()) != null) {
                xline = xline.trim();

            if (xline != null && !xline.trim().isEmpty()) {

                if (xline.contains("MDRAWEVENT")) {

                    String coordinates = xline.replace("MDRAWEVENT", "");
                    String[] tokens = coordinates.split(Pattern.quote(":"));
                    Point[] moviments = new Point[tokens.length];

                    for (int i = 0; i < tokens.length; i++) {
                       String[] coordinates = tokens[i].replace("{", "").replace("}", "").split(",");

                       int x = Integer.parseInt(coordinates[0].split("=")[1]);
                       int y = Integer.parseInt(coordinates[1].split("=")[1]);

                       moviments[i] = new Point(x, y);
                    }

                    MyAccessibilityService.instance.mouseDraw(moviments, 2000);
                }
            }
        }
    }
}

Android AccessibilityService" MyAccessibilityService.java ":

public void mouseDraw(Point[] segments, int time) {
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

        Path path = new Path();
        path.moveTo(segments[0].x, segments[0].y);

        for (int i = 1; i < segments.length; i++) {

            path.lineTo(segments[i].x, segments[i].y);

            GestureDescription.StrokeDescription sd = new GestureDescription.StrokeDescription(path, 0, time);

            dispatchGesture(new GestureDescription.Builder().addStroke(sd).build(), new AccessibilityService.GestureResultCallback() {

                @Override
                public void onCompleted(GestureDescription gestureDescription) {
                    super.onCompleted(gestureDescription);
                }

                @Override
                public void onCancelled(GestureDescription gestureDescription) {
                    super.onCancelled(gestureDescription);
                }
            }, null);
        }
    }
}

0

Hai provato a utilizzare gli script AutoIt ?

È possibile salvare le coordinate all'interno di finestre / schermate specifiche. È possibile tenere premuto il clic del mouse mentre si disegna il disegno.

Ho anche alcuni esempi di codice / script per te se li vuoi!


MODIFICARE:

Secondo questo tutorial è possibile utilizzare Auto-IT su C #.

Segui questi passi:

  1. Installa Auto-IT
  2. Aggiungi Auto-IT come riferimento nel gestore dei riferimenti (AutoItX3.dll)
  3. Quindi importa la libreria che hai aggiunto con: Using AutoItX3Lib;
  4. Crea un nuovo oggetto AutoItX3 chiamato 'auto': AutoItX3 auto = new AutoItX3();
  5. Ora puoi eseguire i comandi Auto It.

Questo è l'esempio completo per l'esecuzione di un clic del mouse:

Using AutoItX3Lib;
AutoItX3 auto = new AutoItX3();
auto.MouseClick("left", 78, 1133, 1, 35)


Con il AutoIt Window Info Toolpuoi controllare le coordinate che vuoi usare.

Si noti che esistono differenze tra le modalità delle coordinate del mouse:

ad esempio: auto.AutoItSetOption("MouseCoordMode", 1)utilizzerà le coordinate dello schermo assolute. Vedi fonte qui .


Per tenere premuto il clic del mouse, è possibile selezionare la funzione MouseDown


1
Questo non ha aiutato. Il tuo suggerimento è esattamente ciò che già fa la mia applicazione Windows Form per C #.
BrowJr
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.