Я хочу знать, как выполнить перетаскивание на Android на основе координат мыши X, Y? Рассмотрим два простых примера: Team Viewer / QuickSupport рисует «шаблон пароля» на удаленном смартфоне и перо Windows Paint соответственно.
Все, что я могу сделать, это симулировать прикосновение ( 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));
}
}
}
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:
Определенно, решение заключается в продолжении жестов, как сказано в предыдущем редактировании .
- Имитация движения джойстика с помощью AccessibilityService
- Почему функция continueStroke не работает
И ниже приведен предполагаемый фиксированный код, который я нашел здесь =>
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:
Я нашел две подпрограммы, которые используются для выполнения перетаскивания, но они используют UiAutomation + injectInputEvent()
. AFAIK, внедрение события работает только в системном приложении, как сказано здесь и здесь, и я не хочу этого.
Это подпрограммы найдены:
- публичный логический удар (int downX, int downY, int upX, int upY, int шаги, логическое перетаскивание)
- public boolean swipe (Point [] сегменты, int сегментSteps)
Затем, чтобы достичь своей цели, я думаю, что 2-я подпрограмма более подходит для использования (следуя логике, исключая внедрение событий) с кодом, показанным в Edit 2, и отправляет все точки pictureBox1_MouseDown
и pictureBox1_MouseMove
(C # Windows Forms Application) соответственно для Point[]
динамического заполнения и при pictureBox1_MouseUp
отправке. cmd для выполнения процедуры и использования заполненного массива. Если у вас есть идея для 1-й процедуры, дайте мне знать: D.
Если после прочтения этого Редактирования у вас есть возможное решение, покажите мне, пожалуйста, ответ, а я постараюсь проверить эту идею.
StrokeDescription.continueStroke()
может быть вероятным решением. Смотрите раздел Продолженные жесты здесь .
pictureBox1_MouseDown
не должны отправлять координаты. В нем должны храниться только начальные координаты, а затем pictureBox1_MouseUp
вы их отправляете, потому что это знаменует собой конец движения мыши