Chcę wiedzieć, jak wykonać przeciąganie na Androidzie oparte na współrzędnych myszy X, Y? rozważ jako dwa proste przykłady, Team Viewer / QuickSupport rysujący odpowiednio „wzorzec hasła” na zdalnym smartfonie i piórze Windows Paint.
Wszystko, co jestem w stanie zrobić, to symulacja dotyku (z dispatchGesture()
i również AccessibilityNodeInfo.ACTION_CLICK
).
Znalazłem te linki, ale nie wiem, czy mogą być przydatne:
Poniżej znajduje się mój działający kod, który służy do wysyłania współrzędnych myszy (wewnątrz PictureBox
sterowania) do zdalnego telefonu i symulowania dotyku.
Aplikacja 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));
}
}
Edytować:
Moją ostatnią próbą było „przesunięcie ekranu” przy użyciu współrzędnych myszy (aplikacja C # Windows Forms) i niestandardowej procedury Androida (w odniesieniu do kodu „przesunięcia ekranu”, który znajduje się powyżej), odpowiednio:
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);
}
}
co daje następujący wynik (ale nadal nie jest w stanie narysować „hasła wzorcowego” takiego jak na przykład TeamViewer). Ale jak powiedziano w komentarzu poniżej, myślę, że przy podobnym podejściu można to osiągnąć prawdopodobnie za pomocą Gestów kontynuowanych . Wszelkie sugestie w tym kierunku będą mile widziane.
Edycja 2:
Zdecydowanie rozwiązaniem są kontynuowane gesty, jak wspomniano w poprzedniej edycji .
- Symulowanie ruchu joysticka za pomocą usługi AccessibilityService
- Dlaczego funkcja ContinueStroke nie działa
Poniżej znajduje się przypuszczalny naprawiony kod, który znalazłem tutaj =>
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);
Wątpię zatem : jak poprawnie przesłać współrzędne myszy dla powyższego kodu, jak można przeciągać w dowolnym kierunku? Jakiś pomysł?
Edycja 3:
Znalazłem dwie procedury, które służą do przeciągania, ale używają UiAutomation + injectInputEvent()
. AFAIK, wstrzyknięcie zdarzenia działa tylko w aplikacji systemowej, jak powiedziano tu i tutaj i nie chcę tego.
Oto znalezione procedury:
- publiczne przesunięcie logiczne (int downX, int downY, int upX, int upY, int steps, boolean drag)
- publiczne przesunięcie boolowskie (segmenty Point [], int segmentSteps)
Następnie, aby osiągnąć mój cel, uważam, że druga procedura jest bardziej odpowiednia do użycia (zgodnie z logiką, z wyłączeniem wstrzykiwania zdarzeń) z kodem pokazanym w Edycji 2 i wysłania wszystkich punktów pictureBox1_MouseDown
i pictureBox1_MouseMove
(C # Windows Forms Application) odpowiednio do wypełnienia Point[]
dynamicznego i przy pictureBox1_MouseUp
wysyłaniu cmd, aby wykonać procedurę i użyć tej tablicy wypełnionej. Jeśli masz pomysł na pierwszą rutynę, daj mi znać: D.
Jeśli po przeczytaniu tej edycji masz możliwe rozwiązanie, pokaż mi odpowiedź, a ja spróbuję przetestować ten pomysł.
StrokeDescription.continueStroke()
może to być prawdopodobne rozwiązanie. Zobacz sekcję „ Gesty kontynuowane” tutaj .
pictureBox1_MouseDown
nie wolno wysyłać współrzędnych. Powinien on przechowywać tylko początkowe współrzędne, a następnie pictureBox1_MouseUp
je wysyłać, ponieważ oznacza to koniec ruchu myszy