ทำการลาก (อ้างอิงจากพิกัดเมาส์ X และ Y) บน Android โดยใช้ AccessibilityService อย่างไร


39

ฉันต้องการรู้วิธีลาก Android บนพิกัด X, Y ของเมาส์หรือไม่ พิจารณาว่าเป็นสองตัวอย่างง่ายๆ Team Viewer / QuickSupport วาด "รูปแบบรหัสผ่าน" บนสมาร์ทโฟนระยะไกลและ Pen of Windows Paint ตามลำดับ

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

สิ่งที่ฉันสามารถทำได้คือการจำลองการสัมผัส (ด้วยdispatchGesture()และยังAccessibilityNodeInfo.ACTION_CLICK)

ฉันพบลิงค์ที่เกี่ยวข้องเหล่านี้ แต่ไม่ทราบว่าจะมีประโยชน์หรือไม่:

ด้านล่างเป็นรหัสการทำงานของฉันที่ใช้ในการส่งพิกัดเมาส์ (ภายในPictureBoxการควบคุม) ไปยังโทรศัพท์ระยะไกลและจำลองการสัมผัส

แอปพลิเคชันฟอร์ม 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));
    }
}

แก้ไข:

ความพยายามครั้งสุดท้ายของฉันคือ "หน้าจอปัดนิ้ว" โดยใช้พิกัดเมาส์ (C # Windows Forms Application) และชุดคำสั่ง android แบบกำหนดเอง (อ้างอิงถึงรหัสของ "หน้าจอกวาดนิ้ว" ที่ลิงก์ด้านบน) ตามลำดับ:

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

}

ที่สร้างผลลัพธ์ต่อไปนี้ (แต่ยังไม่สามารถวาด "รหัสผ่านรูปแบบ" เช่น TeamViewer เป็นต้น) แต่ชอบกล่าวว่าในความคิดเห็นด้านล่างผมคิดว่าด้วยวิธีการที่คล้ายกันนี้สามารถทำได้โดยใช้ท่าทางอย่างต่อเนื่องอาจ ข้อเสนอแนะใด ๆ ในทิศทางนี้จะได้รับการต้อนรับ

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่


แก้ไข 2:

แน่นอนการแก้ปัญหาอยู่ในท่าทางยังคงชอบกล่าวว่าในวันก่อนหน้าแก้ไข

และด้านล่างเป็นรหัสคงที่ที่ฉันพบที่นี่ =>

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

จากนั้นข้อสงสัยของฉันคือการส่งพิกัดของเมาส์อย่างถูกต้องสำหรับรหัสด้านบนวิธีที่สามารถลากไปในทิศทางใดได้อย่างไรความคิดบางอย่าง?


แก้ไข 3:

ผมพบว่าทั้งสองงานประจำที่จะใช้ในการดำเนินการลาก แต่พวกเขาจะใช้UiAutomationinjectInputEvent() + AFAIK การฉีดเหตุการณ์ใช้งานได้เฉพาะในแอพระบบอย่างที่กล่าวไว้ที่นี่และที่นี่และฉันไม่ต้องการ

นี่เป็นงานประจำที่พบ:

จากนั้นเพื่อให้บรรลุเป้าหมายของฉันฉันคิดว่ารูทีนที่ 2 นั้นเหมาะสมกว่าที่จะใช้ (ตามตรรกะไม่รวมการฉีดอีเวนต์) ด้วยรหัสที่แสดงในEdit 2และส่งคะแนนทั้งหมดpictureBox1_MouseDownและpictureBox1_MouseMove(C # Windows Forms Application) ตามลำดับเพื่อเติมPoint[]แบบไดนามิกและpictureBox1_MouseUpส่ง cmd เพื่อรันรูทีนและใช้อาร์เรย์นี้ หากคุณมีความคิดที่จะทำกิจวัตรที่ 1 แจ้งให้เราทราบ: D

ถ้าหลังจากอ่านบทความนี้แก้ไขคุณมีวิธีการแก้ปัญหาที่เป็นไปได้แสดงให้ฉันในคำตอบของโปรดในขณะที่ฉันจะพยายามและทดสอบความคิดนี้


1
TeamViewer ไม่ได้ใช้กรอบการช่วยสำหรับการเข้าถึงเป็นไปได้มากที่สุด พวกเขามีข้อตกลงพิเศษกับผู้ผลิตอุปกรณ์ซึ่งเป็นสาเหตุที่ผลิตภัณฑ์ของพวกเขาไม่สามารถใช้ได้กับทุกอุปกรณ์
CommonsWare

@ คอมมอนส์ขอขอบคุณ แต่ฉันคิดว่านั่นStrokeDescription.continueStroke()อาจเป็นทางออกที่เป็นไปได้ ดูในส่วนท่าทางต่อ ที่นี่
BrowJr

2
เกี่ยวกับ aproach แรกของคุณ pictureBox1_MouseDownต้องไม่ส่งพิกัด มันควรจะเก็บพิกัดเริ่มต้นเท่านั้นและจากนั้นเมื่อpictureBox1_MouseUpคุณส่งพวกเขาเพราะนั่นเป็นจุดสิ้นสุดของการเคลื่อนไหวของเมาส์
Greggz

คำตอบ:


1

นี่คือตัวอย่างของโซลูชันที่ยึดตามการแก้ไข 3ของคำถาม


แอปพลิเคชัน 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);
}

บริการ 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

คุณเคยลองใช้การเขียนสคริปต์AutoItหรือไม่?

คุณสามารถบันทึกพิกัดภายในหน้าต่าง / หน้าจอเฉพาะ คุณสามารถกด mouseclick ค้างไว้ขณะวาดรูปแบบ

ฉันยังมีตัวอย่างโค้ด / สคริปต์ให้คุณถ้าคุณต้องการ!


แก้ไข:

ตามบทช่วยสอนนี้คุณสามารถใช้ Auto-IT ใน C #

ทำตามขั้นตอนเหล่านี้:

  1. ติดตั้ง Auto-IT
  2. เพิ่ม Auto-IT เป็นข้อมูลอ้างอิงในเครื่องมือจัดการการอ้างอิง (AutoItX3.dll)
  3. จากนั้นนำเข้าไลบรารีที่คุณเพิ่มด้วย: Using AutoItX3Lib;
  4. สร้างวัตถุ AutoItX3 ใหม่ที่เรียกว่า 'อัตโนมัติ': AutoItX3 auto = new AutoItX3();
  5. ตอนนี้คุณสามารถรันคำสั่ง Auto It

นี่คือตัวอย่างที่สมบูรณ์สำหรับการเรียกใช้ mouseclick:

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


ด้วยAutoIt Window Info Toolคุณสามารถตรวจสอบพิกัดที่คุณต้องการใช้

โปรดทราบว่ามีความแตกต่างระหว่างโหมดพิกัดของเมาส์:

ตัวอย่างเช่น: auto.AutoItSetOption("MouseCoordMode", 1)จะใช้พิกัดหน้าจอแบบสัมบูรณ์ แหล่งที่มาดูที่นี่


สำหรับการยึด mouseclick ลงคุณสามารถตรวจสอบMouseDown Function


1
สิ่งนี้ไม่ได้ช่วย คำแนะนำของคุณคือสิ่งที่แอปพลิเคชันแบบฟอร์ม Windows C # ของฉันสร้างไว้แล้ว
BrowJr
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.