最新的物联网项目之前说过是安卓机顶盒的软探针项目,目前项目前期基本开发完了,这个时候就涉及到维护问题了,维护的时候由于是远程维护,不可能有一点问题就到出差去开发,而且最近疫情限制到现场都不现实,然后我们就考虑远程维护的问题,之前远程通过TeamViewer连接电脑然后视频去让远程的人操作电视机顶盒,但是这个很浪费人力资源,而且远程的人需要一直待命,这个就很麻烦。我们同事间讨论的时候就说他之前由于没有多余的遥控器发现了一个adb shell input的命令,可以通过adb shell命令行状态下控制机顶盒,上下左右啥的基本遥控器能做的都能做到,然后再加上adb shell screencap的Android屏幕截图功能,一个控制机顶盒,一个显示当前位置,这样配合着使用就能做到简单的无人值守可视化操作机顶盒了。考虑到安卓、pyQt程序执行时需要安装环境,最后综合考虑使用Qt来实现这个调试软件。
二、技术点前期查阅资料准备了下,QProcess实现执行adb等命令然后显示执行结果,简单的QPushbutton来模拟常用的遥控器按键,当按下按钮后调用adb shell input进行机顶盒控制,执行成功后再调用adb shell sreencap来抓取屏幕的截图,最后利用Qlabel显示截图即可,思路简单清晰。
1、QProcess执行命令 2、adb shell input发送安卓控制命令 3、adb shell sreencap截取屏幕 4、Qlabel显示图片 三、技术点实现及坑点记录 1、QProcess执行命令我们可以先用Qt助手了解一下QProcess类:
和串口操作类似,支持异步和同步方式,因为我们不需要执行长时间的命令,所以最后打算这里先使用同步阻塞式读写操作。
找到这个简单的例子:
然后,我们在windows下可以使用cmd执行指令,这个是个简单的例子:
QProcess pCmd;
//cmmand通过传参传进来
pCmd.start("cmd", QStringList()<<"/c"<textBrowser_DebugInfo->append(strTemp);
return true;
还有一些其它的用法,比如我们像调用写好的python、shell、bat脚本或者调用其它程序等,则可以按照最上面的示例去尝试:
QString program = "./path/to/Qt/examples/widgets/analogclock";
QStringList arguments;
arguments << "-style" <start(program, arguments);
2、adb shell input发送安卓控制命令
输入adb shell input了解一下用法:
example:example~$ adb shell input
Usage: input [] [...]
The sources are:
trackball(轨迹球)
joystick(操纵杆)
touchnavigation(触摸导航)
mouse(鼠标)
keyboard(键盘)
gamepad(游戏手柄)
touchpad(触摸板)
dpad(apad手柄)
stylus(输入笔)
touchscreen(触摸屏)
The commands and default sources are:
text (Default: touchscreen)
keyevent [--longpress] ... (Default: keyboard)
tap (Default: touchscreen)
swipe [duration(ms)] (Default: touchscreen)
press (Default: trackball)
roll (Default: trackball)
我们这里用的就是keyevent,前面的source就是默认的keyboard,所以基本上这里的指令会是:
adb shell input keyevent xxx
这里xxx的获取我们一般可以先用adb logcat | grep keycode来过滤keycode,然后使用遥控器按一下我们需要模拟的上下左右、ok、菜单、设置等键来获取对应的keycode值,比如我这里获取到的值如下:
#设置
adb shell input keyevent 176
#菜单
adb shell input keyevent 82
#上、下、左、右、ok
adb shell input keyevent 19
adb shell input keyevent 20
adb shell input keyevent 21
adb shell input keyevent 22
adb shell input keyevent 23
#首页
adb shell input keyevent 3
#返回
adb shell input keyevent 4
3、adb shell sreencap截取屏幕
先了解一下adb shell screencap的用法:
zy@ZY:~$ adb shell screencap ?
usage: screencap [-hp] [-d display-id] [FILENAME]
example: screencap -p /sdcard/screencap.png
-h: this message
-p: save the file as a png.
-d: specify the display id to capture, default 1.
If FILENAME ends with .png it will be saved as a png.
If FILENAME ends with .jpg it will be saved as a jpg.
If FILENAME is not given, the results will be printed to stdout.
例子也给了:
screencap -p /sdcard/screencap.png
-h和?一样都是显示这个命令的usage,-p是将截取保存为文件,文件的后缀是.png就是png图片,后缀是.jpg则是jpg图片,不给路径就输入到屏幕。
adb shell screencap -p /sdcard/1.jpg
或者
adb shell screencap -p /sdcard/1.png
或者
adb shell screencap(输出到终端,基本就是乱码)
注意:这里我之前都是存了png图片,但是在Qt中用label显示的时候一直加载识别不了,找了很久都不行,最后改成存jpg才正确显示出来。
4、Qlabel显示图片这个其实很简单,将图片转换成像素后用label显示即可:
QPixmap pixmap("1.jpg");
screen_label.setWindowTitle("机顶盒屏幕截图");
screen_label.setPixmap(pixmap);
screen_label.show();
screen_label就是显示图片的label,会自动根据图片大小进行调整。
理论上QPixmap可以读取png图片,但是我在处理的时候一直不行,这个注意一下。
5、坑点主要就是label显示截图的时候,开始我一直截图是png格式,但是一直空白的,最后查了很久觉得很可能是由于png透明显示了,还以为哪里没有设置好,最后改成jpg正常显示了,如果png没有显示出来可以看下换个jpg是不是可以正常显示。
四、最后展示一下效果吧,思路说完了,其实实现起来很简单的,大家可以自己想想实现一下。