AccessibilityService를 사용하여 Android에서 드래그 (X, Y 마우스 좌표 기반)를 어떻게 수행합니까?


39

X, Y 마우스 좌표를 기반으로 안드로이드에서 드래그를 수행하는 방법을 알고 싶습니다. 원격 스마트 폰과 Windows Paint 펜에 각각 "비밀번호 패턴"을 그리는 Team Viewer / QuickSupport의 두 가지 간단한 예를 생각해보십시오.

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

내가 메이크업의 수있어 그 모든입니다 시뮬레이션 터치 (와 dispatchGesture()도하고 AccessibilityNodeInfo.ACTION_CLICK).

관련 링크를 찾았지만 유용한 지 알 수 없습니다.

아래는 마우스 좌표 ( PictureBox제어 내부 )를 원격 전화 로 보내고 터치를 시뮬레이션 하는 데 사용되는 작업 코드입니다 .

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

편집하다:

마지막 시도는 각각 마우스 좌표 (C # Windows Forms 응용 프로그램)와 사용자 지정 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));
        }
    }
}

안드로이드 접근성 서비스 :

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 :

확실히, 해결책은 이전 Edit에서 언급 한 것처럼 계속되는 제스처 입니다.

그리고 아래에 내가 발견하는 가정 고정 코드 여기가 =>

안드로이드 접근성 서비스 :

// 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 :

드래그를 수행하는 데 사용되는 두 가지 루틴을 찾았지만 UiAutomation +를 사용하고 있습니다 injectInputEvent(). AFAIK, 이벤트 주입은 여기여기에서 말한 것과 같은 시스템 앱에서만 작동하며 원하지 않습니다.

이것은 발견 된 루틴입니다.

그럼 내 목표를 달성하기 위해, 그 2rd 루틴이 더에 보여 주었다 코드 (이벤트 주입을 제외한 논리 다음) 사용에 충당 생각 편집 2 그리고 모든 포인트를 전송 pictureBox1_MouseDown하고 pictureBox1_MouseMove각각 기입 (C #의 Windows Forms 응용 프로그램) Point[]동적에 pictureBox1_MouseUp보내기 cmd를 사용하여 루틴을 실행하고 채워진이 배열을 사용하십시오. 첫 번째 루틴에 대한 아이디어가 있다면 : D를 알려주십시오.

편집 을 읽은 후에 가능한 해결책 이 있다면 답을 알려주십시오.이 아이디어를 시험 해보고 시험해보십시오.


1
TeamViewer는 접근성 프레임 워크를 사용하지 않습니다. 그들은 장치 제조업체와 특별 계약을 맺고 있으므로 모든 장치에서 해당 제품을 사용할 수 없습니다.
CommonsWare

@CommonsWare 감사합니다. 그러나 나는 그것이 StrokeDescription.continueStroke()가능한 해결책 일 수 있다고 생각합니다 . 여기에서 계속되는 제스처 섹션을 참조 하십시오 .
BrowJr

2
첫 번째 aproach에 관해. pictureBox1_MouseDown좌표를 보내서는 안됩니다. 초기 좌표 만 저장 한 다음 pictureBox1_MouseUp보내야합니다. 마우스 이동이
끝났기

답변:


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

안드로이드 서비스 " 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);
                }
            }
        }
    }
}

안드로이드 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 스크립팅 을 사용해 보셨습니까 ?

특정 창 / 화면 내에서 좌표를 저장할 수 있습니다. 패턴을 그리는 동안 마우스 클릭을 길게 누를 수 있습니다.

또한 원하는 경우 예제 코드 / 스크립트가 있습니다!


편집하다:

이 자습서 에 따르면 C #에서 Auto-IT를 사용할 수 있습니다.

이 단계를 따르세요:

  1. 자동 IT 설치
  2. 참조 관리자 (AutoItX3.dll)에서 참조로 Auto-IT 추가
  3. 그런 다음 추가 한 라이브러리를 가져 오십시오. Using AutoItX3Lib;
  4. 'auto'라는 새 AutoItX3 객체를 만듭니다. AutoItX3 auto = new AutoItX3();
  5. 이제 자동 It 명령을 실행할 수 있습니다.

마우스 클릭을 실행하기위한 완전한 예제입니다.

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


AutoIt Window Info Tool사용하려는 좌표를 확인할 수 있습니다.

마우스 좌표 모드에는 차이점이 있습니다.

예를 들어, auto.AutoItSetOption("MouseCoordMode", 1)절대 화면 좌표를 사용합니다. 여기 소스를 참조 하십시오 .


마우스 클릭을 누른 상태에서 MouseDown 기능을 확인할 수 있습니다


1
이것은 도움이되지 않았습니다. 귀하의 제안은 C # Windows Form Application이 이미 작성한 것입니다.
BrowJr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.