web-dev-qa-db-fra.com

Comment effectuer un glissement (basé sur les coordonnées X, Y de la souris) sur Android en utilisant AccessibilityService?

Je veux savoir comment effectuer un glissement sur Android basé sur les coordonnées de la souris X, Y? Considérez comme deux exemples simples, Team Viewer/QuickSupport dessinant le "modèle de mot de passe" sur le smartphone distant et le stylet de Windows Paint respectivement.

enter image description here

enter image description here

Tout ce que je peux faire, c'est simuler le toucher (avec dispatchGesture() et aussi AccessibilityNodeInfo.ACTION_CLICK).

J'ai trouvé ces liens pertinents, mais je ne sais pas s'ils peuvent être utiles:

Ci-dessous mon code de travail qui est utilisé pour envoyer les coordonnées de la souris (à l'intérieur du contrôle PictureBox) au téléphone distant et simuler le toucher.

Application Windows Forms:

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

Modifier:

Ma dernière tentative a été un "écran de balayage" utilisant les coordonnées de la souris (application Windows Forms C #) et une routine Android routine (en référence au code de "l'écran de balayage" lié ci-dessus), respectivement):

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

}

qui produit le résultat suivant (mais n'est toujours pas capable de dessiner un "mot de passe de modèle" comme TeamViewer par exemple). Mais comme dit dans le commentaire ci-dessous, je pense qu'avec une approche similaire, cela peut être réalisé en utilisant gestes continus probablement. Toute suggestion dans ce sens sera la bienvenue.

enter image description here

enter image description here


Édition 2:

Certainement, la solution est gestes continus comme dit sur le précédent Edit .

Et ci-dessous est un code fixe supposé que j'ai trouvé ici =>

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

Ensuite, mon doute est: comment envoyer correctement les coordonnées de la souris pour le code ci-dessus, de la façon dont on peut faire glisser dans n'importe quelle direction? Une idée?


Édition 3:

J'ai trouvé deux routines utilisées pour effectuer un glissement, mais elles utilisent iAutomation + injectInputEvent() . AFAIK, l'injection d'événement ne fonctionne que dans une application système comme dit ici et ici et je ne le veux pas.

Ce sont des routines trouvées:

Ensuite, pour atteindre mon objectif, je pense que la 2ème routine est plus appropriée à utiliser (suivant la logique, à l'exception de l'injection d'événement) avec le code affiché sur Edit 2 et envoyer tous les points de pictureBox1_MouseDown et pictureBox1_MouseMove (Application Windows Forms C #) respectivement pour remplir Point[] dynamiquement et sur pictureBox1_MouseUp envoyer cmd pour exécuter la routine et l'utiliser tableau rempli. Si vous avez une idée de la 1ère routine, faites le moi savoir: D.

Si après avoir lu ceci Edit vous avez une solution possible, montrez-moi une réponse s'il vous plaît, alors que je vais essayer de tester cette idée.

39
BrowJr

Voici un exemple de solution basée sur Edit 3 de question.


Application C # Windows Froms " 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);
}

Service 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);
        }
    }
}
2
BrowJr

Avez-vous essayé d'utiliser des scripts AutoIt ?

Vous pouvez enregistrer des coordonnées dans des fenêtres/écrans spécifiques. Vous pouvez maintenir le clic de souris enfoncé tout en dessinant le motif.

J'ai aussi quelques exemples de code/scripts pour vous si vous les voulez!


ÉDITER:

Selon ce tutoriel vous pouvez utiliser Auto-IT sur C #.

Suivez ces étapes:

  1. Installer Auto-IT
  2. Ajouter Auto-IT comme référence dans le gestionnaire de références (AutoItX3.dll)
  3. Importez ensuite la bibliothèque que vous avez ajoutée avec: Using AutoItX3Lib;
  4. Créer un nouvel objet AutoItX3 appelé 'auto': AutoItX3 auto = new AutoItX3();
  5. Vous pouvez maintenant exécuter les commandes Auto It.

Voici l'exemple complet pour exécuter un clic de souris:

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


Avec le AutoIt Window Info Tool, Vous pouvez vérifier les coordonnées que vous souhaitez utiliser.

Veuillez noter qu'il existe des différences entre les modes de coordonnées de la souris:

par exemple: auto.AutoItSetOption("MouseCoordMode", 1) utilisera les coordonnées absolues de l'écran. Voir source ici .


Pour maintenir le clic de souris enfoncé, vous pouvez vérifier Fonction MouseDown

0
JaFizz