X、Yマウス座標に基づいてAndroidでドラッグを実行する方法を知りたいですか?2つの単純な例として、チームビューア/ QuickSupportがそれぞれリモートのスマートフォンと「ペンオブウィンドウズペイント」で「パスワードパターン」を描画するとします。
私が作ることができるすべてはタッチをシミュレートすることです(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フォームアプリケーション)とカスタム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:
間違いなく、解決策は以前のEditで述べたようなジェスチャーを継続することです。
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:
ドラッグの実行に使用される2つのルーチンを見つけましたが、それらはUiAutomation + を使用していinjectInputEvent()
ます。AFAIK、イベントの注入は、こことここで言ったようなシステムアプリでのみ機能し、私はそれを望んでいません。
これは見つかったルーチンです:
- public boolean swipe(int downX、int downY、int upX、int upY、int steps、boolean drag)
- パブリックブールスワイプ(ポイント[]セグメント、intセグメントステップ)
次に、私の目標を達成するために、編集2に示されたコードで(ロジックに従って、イベントインジェクションを除く)2番目のルーチンを使用する方が適切であると考え、動的に、pictureBox1_MouseDown
およびpictureBox1_MouseMove
(C#Windowsフォームアプリケーション)のすべてのポイントをそれぞれ送信しますPoint[]
pictureBox1_MouseUp
送信cmdを実行してルーチンを実行し、この配列を埋めて使用します。あなたが最初のルーチンにアイデアを持っているなら、私に知らせてください:D。
この編集を読んだ後、考えられる解決策がある場合は、答えを教えてください。このアイデアをテストしてみます。
StrokeDescription.continueStroke()
がありそうな解決策になることができると思います。セクションを参照してください続きジェスチャーを ここに。
pictureBox1_MouseDown
座標を送信してはなりません。pictureBox1_MouseUp
マウスの動きの終わりを示すので、最初の座標のみを保存してから送信します