Tôi muốn biết cách thực hiện thao tác kéo trên Android dựa trên tọa độ chuột X, Y? xem xét như hai ví dụ đơn giản, Team Viewer / QuickSupport vẽ "mẫu mật khẩu" trên điện thoại thông minh từ xa và Pen of Windows Paint tương ứng.
Tất cả những gì tôi có thể làm là mô phỏng cảm ứng (có dispatchGesture()
và cũng có AccessibilityNodeInfo.ACTION_CLICK
).
Tôi tìm thấy các liên kết liên quan này, nhưng không biết liệu chúng có hữu ích không:
Dưới đây là mã làm việc của tôi được sử dụng để gửi tọa độ chuột (bên trong PictureBox
điều khiển) đến điện thoại từ xa và mô phỏng cảm ứng.
Ứng dụng 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));
}
}
Biên tập:
Lần thử cuối cùng của tôi là "màn hình vuốt" bằng cách sử dụng tọa độ chuột (Ứng dụng biểu mẫu C # Windows) và thói quen tùy chỉnh Android (có tham chiếu đến mã "màn hình vuốt" được liên kết ở trên), tương ứng:
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));
}
}
}
Dịch vụ truy cập 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);
}
}
tạo ra kết quả sau (nhưng vẫn không thể vẽ "mật khẩu mẫu" như TeamViewer chẳng hạn). Nhưng giống như đã nói trên bình luận bên dưới, tôi nghĩ rằng với một cách tiếp cận tương tự, điều này có thể đạt được bằng cách sử dụng cử chỉ Tiếp tục . Bất kỳ đề xuất theo hướng này sẽ được hoan nghênh.
Chỉnh sửa 2:
Chắc chắn, giải pháp là tiếp tục cử chỉ như đã nói trên Chỉnh sửa trước đó .
- Mô phỏng chuyển động của phím điều khiển bằng AccessService
- Tại sao chức năng continueStroke không hoạt động
Và dưới đây là một mã cố định được cho là tôi tìm thấy ở đây =>
Dịch vụ truy cập 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);
Sau đó, nghi ngờ của tôi là: làm thế nào để gửi tọa độ chuột chính xác cho mã ở trên, về cách có thể thực hiện kéo đến bất kỳ hướng nào? Một số ý tưởng?
Chỉnh sửa 3:
Tôi đã tìm thấy hai thói quen được sử dụng để thực hiện kéo, nhưng chúng đang sử dụng UiAutomation + injectInputEvent()
. AFAIK, tiêm sự kiện chỉ hoạt động trong một ứng dụng hệ thống như đã nói ở đây và ở đây và tôi không muốn nó.
Đây là thói quen được tìm thấy:
- vuốt boolean công khai (int downX, int downY, int upX, int upY, int step, boolean drag)
- vuốt boolean công khai (các đoạn [], int SegSteps)
Sau đó, để đạt được mục tiêu của mình, tôi nghĩ rằng thói quen thứ 2 được sử dụng nhiều hơn (theo logic, không bao gồm nội dung sự kiện) với mã được hiển thị trên Chỉnh sửa 2 và gửi tất cả các điểm pictureBox1_MouseDown
và pictureBox1_MouseMove
(Ứng dụng Biểu mẫu Windows C) tương ứng để điền Point[]
động và pictureBox1_MouseUp
gửi cmd để thực hiện các thường trình và sử dụng mảng này điền. Nếu bạn có ý tưởng về thói quen thứ 1, hãy cho tôi biết: D.
Nếu sau khi đọc Chỉnh sửa này, bạn có một giải pháp khả thi, vui lòng cho tôi xem câu trả lời, trong khi tôi sẽ thử và kiểm tra ý tưởng này.
StrokeDescription.continueStroke()
có thể là một giải pháp có thể. Xem phần Cử chỉ tiếp tục ở đây .
pictureBox1_MouseDown
không được gửi tọa độ. Nó chỉ nên lưu trữ các tọa độ ban đầu, và sau đó pictureBox1_MouseUp
bạn gửi chúng, bởi vì điều đó đánh dấu sự kết thúc của chuyển động chuột