Bagaimana cara melakukan drag (berbasis di koordinat X, Y mouse) di Android menggunakan AccessibilityService?

39

Saya ingin tahu cara melakukan drag pada android yang berbasis di X, koordinat mouse Y? pertimbangkan sebagai dua contoh sederhana, Penampil Tim / QuickSupport menggambar "pola kata sandi" pada smartphone jarak jauh dan Pena Windows Paint.

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Yang bisa saya lakukan hanyalah mensimulasikan sentuhan (dengan dispatchGesture()dan juga AccessibilityNodeInfo.ACTION_CLICK).

Saya menemukan tautan yang relevan ini, tetapi tidak tahu apakah itu dapat berguna:

Di bawah ini adalah kode kerja saya yang digunakan untuk mengirim koordinat mouse (di dalam PictureBoxkendali) ke telepon jarak jauh dan mensimulasikan sentuhan.

Aplikasi Formulir Windows:

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

Edit:

Upaya terakhir saya adalah "layar gesek" menggunakan koordinat mouse (C # Aplikasi Formulir Windows) dan rutin android khusus (dengan mengacu pada kode "layar gesek" yang terhubung di atas), masing-masing:

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

Layanan Aksesibilitas Android :

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

}

yang menghasilkan hasil berikut (tetapi masih tidak dapat menggambar "kata sandi pola" seperti TeamViewer misalnya). Tetapi seperti dikatakan pada komentar di bawah, saya pikir bahwa dengan pendekatan yang sama ini dapat dicapai dengan menggunakan gerakan Lanjutan mungkin. Setiap saran dalam arah ini akan diterima.

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini


Edit 2:

Pastinya, solusinya adalah melanjutkan gerakan seperti yang dikatakan pada Edit sebelumnya .

Dan di bawah ini adalah kode tetap yang seharusnya saya temukan di sini =>

Layanan Aksesibilitas Android:

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

Lalu, keraguan saya adalah: bagaimana cara mengirim koordinat mouse dengan benar untuk kode di atas, dari cara yang dapat melakukan drag ke arah mana pun? Beberapa ide?


Edit 3:

Saya menemukan dua rutinitas yang digunakan untuk melakukan drag, tetapi mereka menggunakan UiAutomation + injectInputEvent(). AFAIK, injeksi acara hanya berfungsi dalam aplikasi sistem seperti yang dikatakan di sini dan di sini dan saya tidak menginginkannya.

Ini adalah rutinitas yang ditemukan:

Kemudian untuk mencapai tujuan saya, saya pikir rutin ke-2 lebih tepat untuk digunakan (mengikuti logika, tidak termasuk injeksi peristiwa) dengan kode yang ditunjukkan pada Edit 2 dan mengirim semua titik pictureBox1_MouseDowndan pictureBox1_MouseMove(C # Aplikasi Windows Forms) masing-masing untuk mengisi Point[]secara dinamis dan pictureBox1_MouseUpmengirim cmd untuk menjalankan rutin dan menggunakan array yang diisi ini. Jika Anda memiliki ide untuk rutinitas pertama, beri tahu saya: D.

Jika setelah membaca Sunting ini Anda memiliki solusi yang memungkinkan, tolong tunjukkan saya dalam jawaban, sementara saya akan mencoba dan menguji ide ini.

BrowJr
sumber
1
Kemungkinan besar TeamViewer tidak menggunakan kerangka kerja aksesibilitas. Mereka memiliki penawaran khusus dengan produsen perangkat, itulah sebabnya produk mereka tidak tersedia untuk semua perangkat.
CommonsWare
@CommonsWare terima kasih. Tetapi saya pikir itu StrokeDescription.continueStroke()bisa menjadi solusi yang memungkinkan. Lihat bagian Gerakan lanjutan di sini .
BrowJr
2
Mengenai pendekatan pertamamu. pictureBox1_MouseDowntidak boleh mengirim koordinat. Seharusnya hanya menyimpan koordinat awal, dan kemudian pada pictureBox1_MouseUpAnda mengirimnya, karena itu menandai akhir gerakan mouse
Greggz

Jawaban:

1

Berikut adalah contoh solusi berdasarkan Edit 3 pertanyaan.


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

layanan 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);
        }
    }
}
BrowJr
sumber
0

Sudahkah Anda mencoba menggunakan skrip AutoIt ?

Anda dapat menyimpan koordinat dalam jendela / layar tertentu. Anda dapat menahan mouseclick ditekan saat menggambar polanya.

Saya juga punya beberapa contoh kode / skrip untuk Anda jika Anda menginginkannya!


EDIT:

Menurut tutorial ini Anda dapat menggunakan Auto-IT di C #.

Ikuti langkah ini:

  1. Instal Auto-IT
  2. Tambahkan Auto-IT sebagai referensi dalam referensi manajer (AutoItX3.dll)
  3. Kemudian impor perpustakaan yang Anda tambahkan dengan: Using AutoItX3Lib;
  4. Buat objek AutoItX3 baru yang disebut 'otomatis': AutoItX3 auto = new AutoItX3();
  5. Anda sekarang dapat menjalankan perintah Auto It.

Ini adalah contoh lengkap untuk menjalankan mouseclick:

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


Dengan AutoIt Window Info ToolAnda dapat memeriksa koordinat yang ingin Anda gunakan.

Harap perhatikan ada perbedaan antara mode koordinat mouse:

misalnya: auto.AutoItSetOption("MouseCoordMode", 1)akan menggunakan koordinat layar absolut. Lihat sumber di sini .


Untuk menahan mouseklik, Anda dapat memeriksa Fungsi MouseDown

JaFizz
sumber
1
Ini tidak membantu. Saran Anda adalah apa yang sudah dibuat oleh Aplikasi C # Windows Form saya.
BrowJr