Wie kann ich mit AccessibilityService ein Ziehen (basierend auf X-, Y-Mauskoordinaten) auf Android durchführen?


39

Ich möchte wissen, wie man ein Ziehen auf Android basierend auf X-, Y-Mauskoordinaten durchführt. Betrachten Sie als zwei einfache Beispiele den Team Viewer / QuickSupport, der das "Kennwortmuster" auf dem Remote-Smartphone bzw. dem Stift von Windows Paint zeichnet.

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Alles was ich machen kann ist eine Berührung zu simulieren (mit dispatchGesture()und auch AccessibilityNodeInfo.ACTION_CLICK).

Ich habe diese relevanten Links gefunden, weiß aber nicht, ob sie nützlich sein können:

Unten ist mein Arbeitscode, der verwendet wird, um Mauskoordinaten (innerhalb der PictureBoxSteuerung) an ein entferntes Telefon zu senden und Berührungen zu simulieren.

Windows Forms-Anwendung:

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));
    }
}

Bearbeiten:

Mein letzter Versuch war ein "Wischbildschirm" mit Mauskoordinaten (C # Windows Forms-Anwendung) und eine benutzerdefinierte Android-Routine (unter Bezugnahme auf den oben verlinkten Code des "Wischbildschirms"):

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);
}

}

Dies führt zu folgendem Ergebnis (kann jedoch immer noch kein "Musterkennwort" wie z. B. TeamViewer zeichnen). Aber wie im Kommentar unten erwähnt, denke ich, dass dies mit einem ähnlichen Ansatz wahrscheinlich mit fortgesetzten Gesten erreicht werden kann . Vorschläge in diese Richtung sind willkommen.

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein


Bearbeiten 2:

Auf jeden Fall ist die Lösung weiterhin Gesten wie bei der vorherigen Bearbeitung gesagt .

Und unten ist ein angeblicher fester Code, den ich hier gefunden habe =>

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);

Dann ist mein Zweifel: Wie kann man richtig Mauskoordinaten für den obigen Code senden, wie man in jede Richtung ziehen kann? Irgendeine Idee?


Edit 3:

Ich habe zwei Routinen gefunden, die zum Ziehen verwendet werden, aber UiAutomation + verwenden injectInputEvent(). AFAIK, Injection von Event funktioniert nur in einer System-App wie hier und hier gesagt und ich will es nicht.

Dies sind Routinen gefunden:

Um mein Ziel zu erreichen, ist die 2. Routine meiner Meinung nach besser geeignet, um (gemäß der Logik, ohne Ereignisinjektion) den in Edit 2 gezeigten Code zu verwenden und alle Punkte von pictureBox1_MouseDownund pictureBox1_MouseMove(C # Windows Forms-Anwendung) zu senden , um sie Point[]dynamisch und beim pictureBox1_MouseUpSenden zu füllen cmd, um die Routine auszuführen und dieses gefüllte Array zu verwenden. Wenn Sie eine Idee zur ersten Routine haben, lassen Sie es mich wissen: D.

Wenn Sie nach dem Lesen dieses Edits eine mögliche Lösung haben, zeigen Sie mir bitte eine Antwort, während ich versuchen werde, diese Idee zu testen.


1
TeamViewer verwendet höchstwahrscheinlich nicht das Barrierefreiheits-Framework. Sie haben spezielle Angebote mit Geräteherstellern, weshalb ihr Produkt nicht für alle Geräte verfügbar ist.
CommonsWare

@ CommonsWare danke. Aber ich denke, das StrokeDescription.continueStroke()kann eine wahrscheinliche Lösung sein. Siehe Abschnitt Fortsetzung Gesten hier .
BrowJr

2
In Bezug auf Ihren ersten Ansatz. pictureBox1_MouseDowndarf die Koordinaten nicht senden. Es sollte nur die Anfangskoordinaten speichern, und dann pictureBox1_MouseUpsenden Sie sie weiter, da dies das Ende der Mausbewegung markiert
Greggz

Antworten:


1

Hier ist ein Beispiel für eine Lösung, die auf Edit 3 der Frage basiert .


C # Windows Froms-Anwendung " formMain.cs ":

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);
}

Android-Dienst " 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

Haben Sie versucht, AutoIt- Scripting zu verwenden?

Sie können Koordinaten in bestimmten Fenstern / Bildschirmen speichern. Sie können den Mausklick gedrückt halten, während Sie das Muster zeichnen.

Ich habe auch einige Beispielcodes / Skripte für Sie, wenn Sie sie wollen!


BEARBEITEN:

Gemäß diesem Tutorial können Sie Auto-IT auf C # verwenden.

Folge diesen Schritten:

  1. Installieren Sie Auto-IT
  2. Fügen Sie Auto-IT als Referenz im Referenzmanager hinzu (AutoItX3.dll).
  3. Importieren Sie dann die Bibliothek, die Sie hinzugefügt haben mit: Using AutoItX3Lib;
  4. Erstellen Sie ein neues AutoItX3-Objekt mit dem Namen 'auto': AutoItX3 auto = new AutoItX3();
  5. Sie können jetzt Auto It-Befehle ausführen.

Dies ist das vollständige Beispiel für die Ausführung eines Mausklicks:

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


Mit AutoIt Window Info Toolkönnen Sie die Koordinaten überprüfen, die Sie verwenden möchten.

Bitte beachten Sie, dass es Unterschiede zwischen den Mauskoordinatenmodi gibt:

Beispiel: auto.AutoItSetOption("MouseCoordMode", 1)Verwendet absolute Bildschirmkoordinaten. Siehe Quelle hier .


Um den Mausklick gedrückt zu halten, können Sie die MouseDown-Funktion überprüfen


1
Das hat nicht geholfen. Ihr Vorschlag ist genau das, was meine C # Windows Form-Anwendung bereits macht.
BrowJr
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.