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


39

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

entrez la description de l'image ici

entrez la description de l'image ici

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:

Voici mon code de travail qui est utilisé pour envoyer les coordonnées de la souris (à l'intérieur du PictureBoxcontrôle) 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));
    }
}

Éditer:

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 personnalisée (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 probablement des gestes continus . Toute suggestion dans ce sens sera la bienvenue.

entrez la description de l'image ici

entrez la description de l'image ici


Modifier 2:

Certainement, la solution consiste à poursuivre les gestes comme dit lors de l' édition précédente .

Et ci-dessous est un supposé code fixe 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 vous pouvez effectuer le glisser dans n'importe quelle direction? Une idée?


Modifier 3:

J'ai trouvé deux routines utilisées pour effectuer un glissement, mais elles utilisent UiAutomation + 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 (en suivant la logique, à l'exception de l'injection d'événements) avec le code affiché sur Edit 2 et envoyer tous les points de pictureBox1_MouseDownet pictureBox1_MouseMove(C # Windows Forms Application) respectivement pour remplir Point[]dynamiquement et lors de l' pictureBox1_MouseUpenvoi cmd pour exécuter la routine et utiliser ce tableau rempli. Si vous avez une idée de la 1ère routine, faites le moi savoir: D.

Si après avoir lu cette édition, vous avez une solution possible, montrez-moi une réponse s'il vous plaît, pendant que j'essaierai de tester cette idée.


1
TeamViewer n'utilise pas le cadre d'accessibilité, très probablement. Ils ont des offres spéciales avec les fabricants d'appareils, c'est pourquoi leur produit n'est pas disponible pour tous les appareils.
CommonsWare

@CommonsWare merci. Mais je pense que cela StrokeDescription.continueStroke()peut être une solution probable. Voir la section Gestes continus ici .
BrowJr

2
Concernant votre première approche. pictureBox1_MouseDownne doit pas envoyer les coordonnées. Il ne doit stocker que les coordonnées initiales, puis pictureBox1_MouseUpvous les envoyez, car cela marque la fin du mouvement de la souris
Greggz

Réponses:


1

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

0

Avez-vous essayé d'utiliser les 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 didacticiel, 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éez 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 Toolvous 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 d'écran absolues. Voir la source ici .


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


1
Cela n'a pas aidé. Votre suggestion est exactement ce que ma demande de formulaire Windows C # fait déjà.
BrowJr
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.