首页
社区
课程
招聘
[原创]通过sendevent实现多点连续滑动
发表于: 2019-6-18 17:31 10778

[原创]通过sendevent实现多点连续滑动

2019-6-18 17:31
10778

最近在瞎琢磨Android设备的云控,想要实现一个多点滑动的功能。我们知道通过shell执行input swipe x1 y1 x2 y2 t可以实现t毫秒内从坐标(x1, y1)滑动到(x2, y2),滑动完成后模拟的动作就“被抬起”,很难直接通过input实现滑动”转弯“。于是花了半天时间看了一下sendevent的参数含义,简单实现了连续滑动的功能。

sendevent需要4个参数,如下:
use: sendevent device type code value
含义分别是设备、事件类型、事件代码以及传递的数据。
在分析之前可以通过getevent获取事件的数据以便参照,如下为简单滑动后获取的数据:

type和code的含义可参照内核源码中的input.h,笔者用的Nexus6P,msm-android-msm-angler-3.10-nougat-mr2,该头文件位于include/uapi/linux/input.h。

滑动所需的type含义如下:

type 0000 Synchronization events
type 0001 Keys and buttons
type 0003 Absolute axes,即描述运动事件的值

code含义如下

0000 0000 SYN_REPORT,这里笔者简单理解为与io的flush类似
0003 0039 开始接触设备的唯一标识号,这里为0xc3a, 0xffffffff代表结束接触
0001 014a 标明触摸事件,1代表按下,0代表放开
0001 0145 表明是用手指触摸的,同样1代表按下,0代表放开
0003 0035 触摸的x坐标
0003 0036 触摸的y坐标
0003 0030 接触面椭圆长轴,非必需
0003 0031 接触面椭圆短轴,非必需

其实到这里已经很清晰了,开始接触->按下->一系列坐标移动->结束接触->放开,通过坐标的移动可以控制滑动的痕迹,sendevent执行的快慢控制滑动的快慢。要注意最好执行在同一个shell,并且不要阻塞(waitfor)。
给出的代码直接调用即可:

即从(357, 2054)滑动到(1112, 1308),接着又滑到(1112, 2032)。代码写得很粗糙。

如果需要改变滑动的速度,可以将代码里控制坐标间隔次数的值SWIPE_RUN_INTERVAL改小一点,间隔次数越少,滑动越快。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-11-20 10:02 被Umiade编辑 ,原因:
上传的附件:
收藏
免费 3
支持
分享
最新回复 (10)
雪    币: 2907
活跃值: (1301)
能力值: ( LV12,RANK:215 )
在线值:
发帖
回帖
粉丝
2
2019-6-19 13:21
0
雪    币: 457
活跃值: (328)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢楼主。
2019-6-19 13:48
0
雪    币: 2484
活跃值: (3152)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
谢谢
2019-11-19 14:21
0
雪    币: 2484
活跃值: (3152)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
雨天不带鱼 谢谢
为啥滑动的时候会停顿一下然后继续滑动、好像不太流畅。是因为shell的问题?
2019-11-19 20:22
0
雪    币: 4005
活跃值: (2188)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
雨天不带鱼 为啥滑动的时候会停顿一下然后继续滑动、好像不太流畅。是因为shell的问题?

之前测试的时候影响速度的一个是shell,一个是移动坐标间隔的次数
shell就是我上面说的用同一个进程,直接将命令写入流

    public static Process nonBlockShell;
    public static DataOutputStream nonBlockOutputStream;

    public static BufferedReader nonBlockSuccessResult = null;
    public static BufferedReader nonBlockErrorResult = null;

    static {
        initNonBlockShell();
    }

    public static int initNonBlockShell() {
        try {
            nonBlockShell = Runtime.getRuntime().exec("su");
            nonBlockOutputStream = new DataOutputStream(nonBlockShell.getOutputStream());
            nonBlockSuccessResult = new BufferedReader(new InputStreamReader(nonBlockShell.getInputStream()));
            nonBlockErrorResult = new BufferedReader(new InputStreamReader(nonBlockShell.getErrorStream()));
            readNonBlockStream();
        } catch (Throwable e) {
            e.printStackTrace();
            return -1;
        }
        return 0;
    }

    public static void readNonBlockStream() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (nonBlockSuccessResult != null) {

                        String s;
                        while ((s = nonBlockSuccessResult.readLine()) != null) {
                            Logger.i("[<< EXEC SUCCESS]" + s);
                        }
                    }
                } catch (Exception e) {
                    Logger.e("read nonBlockSuccessResult error:", e);
                }
            }
        }).start();


        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    while (nonBlockErrorResult != null) {
                        String e;
                        while ((e = nonBlockErrorResult.readLine()) != null) {
                            Logger.e("[<< EXEC ERROR]" + e);
                        }
                    }
                } catch (Exception e) {
                    Logger.e("read nonBlockErrorResult error:", e);
                }
            }
        }).start();

    }

    public static int execNonBlockRootCmd(String cmd) {
        int ret = 0;
        if (null == nonBlockShell || null == nonBlockOutputStream) {
            if (initNonBlockShell() < 0) {
                Logger.e("execNonBlockRootCmd getRuntime for su error!");
                return -1;
            }
        }
        Logger.d("[>>]" + cmd);
        try {
            nonBlockOutputStream.writeBytes(cmd + "\n");
            nonBlockOutputStream.flush();

        } catch (Exception e) {
            Logger.e("execNonBlockRootCmd error:", e);
            ret = -1;
        }
        return ret;
    }

至于坐标之间的间隔,将上面代码里面SWIPE_RUN_INTERVAL改小一点,可以明显提高滑动速度。

2019-11-20 09:54
0
雪    币: 2484
活跃值: (3152)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
Umiade 之前测试的时候影响速度的一个是shell,一个是移动坐标间隔的次数 shell就是我上面说的用同一个进程,直接将命令写入流 ``` public static Process nonBlock ...
好的、我试试!谢谢!
2019-11-20 10:10
0
雪    币: 1385
活跃值: (5609)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
8
能用不?,听说发送要把,16进制改成10进制?
2019-11-21 10:59
0
雪    币: 4005
活跃值: (2188)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
supperlitt 能用不?,听说发送要把,16进制改成10进制?
都用字符串写入流了默认当然是十进制的
2019-11-21 13:53
0
雪    币: 2484
活跃值: (3152)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
supperlitt 能用不?,听说发送要把,16进制改成10进制?
可以使用、项目已经跑起来了 很不错的!
2019-11-21 18:30
0
雪    币: 266
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gqm
11
老兄可以找你定做个这 控制器吗?
2019-12-16 18:28
0
游客
登录 | 注册 方可回帖
返回
//