最近有这样一个需求,多台手机之间,手机B,手机C,手机D全部显示手机A的屏幕或摄像头画面。
一开始为了快速实现,方案为手机A截屏,然后用socket发送给其余手机,效果实现,但是非常卡顿。
后来,想用流实现其功能,类似于直播的感觉。但是无奈流媒体服务器搭建不太熟悉。
最后,改用实时获取h264流,然后实时通过socket发送。已实现
实现步骤:
1获取MediaProjection对象:
mMediaProjectionManager = (MediaProjectionManager)getSystemService(Context.MEDIA_PROJECTION_SERVICE);Intent intent = mMediaProjectionManager.createScreenCaptureIntent();startActivityForResult(intent, REQUEST_CODE);
2.开启屏幕录制线程ScreenRecorderThread
2.1创建编码器
2.2录制视频
2.3发送(先发送sps,pps)
后来又有一个需求,让接收的屏幕的手机控制发送屏幕的手机
方案:
1.获取当前手机屏幕大小,在和发送屏幕手机的手机屏幕大小做一下比例。确定点击坐标,点击滑动动作
2.发送给服务器,让服务器根据数据转换成adb控制手机的语句
3.手机通过usb与pc相连,pc执行adb语句,手机受到虚拟触控
后续,今天是7月18日,我好久没有关注博客了,今天有时间看到这篇博客被大家看了好多遍,但是方案已经完全不一样了,所以我更新。如果你看到这请继续向下看,因为这个项目用下边的这种方法做出来想过更好,同局域网下屏幕同步上至少600毫秒以下,控制上说毫秒可能大家没有概念,效果上能够做到画线绘制上的同步,比如输入法上的手写输入不能说完全同步,但是延时也是很小的。但是不得不承认我还不能做到像total control的效果。由于代码的保密性,这里只提供方案,后期我会写一个删减版的dome。
1屏幕同步上
如果你只有自己一个人或者要求不太高的话,建议采用udp的方式,这样的话延时一般在200到600毫秒之间,这个延时是个什么概念尼?可以这样理解,你将2个手机放在一起,你操作一个手机A,操作完这个手机A,你就看手机B,这时手机B正在执行你的点击滑动的操作。这里的udp发送是的将h264的btye数组封成一个包,然后直接发送,但是请注意udp包的最大限制为64k,这意味着你可能(不是可能,是一定现在手机的分辨率会发生发送数据包超过限制导致那个超大包发送不过去的情况),但是这时你可以先不管这个,先把通过比特率,录制分辨率压缩分辨率,关键帧间隔等(比特率降低,将视频压缩到480*640等)让发送的包变小(就是发送的数据不清楚了),先暂时暂时暂时忽略这个问题(如果你看完效果决定用这个方法了解决方案,那么你就研究下udp的组包吧,但是组包也不是万能的呦,因为它丢包,要是你解决不好的话我只能用tcp的socket了),先看效果。(注意了:如果效果你能接受,你就测测大概的延时,用手机A打开秒表,然后你点击暂停的时候,看看手机B此时跑到了哪里,你就能知道了)。
如果你不是自己在做这个项目,或者你有一个很高的要求,请看这里。用rtsp吧,局域网下延时能稳定到200ms内,外网就得看网速了。
关于控制的方法:
不知道大家注意没注意过,目前市场上(不算同一厂商的手机,而且手机不需要root),没有一款软件能够跨网控制手机,就算是total control等都不能。当然这不是绝对的,只是不能面向大众。这里我们说能够面向大众的,在局域网下的情况,那我们来说一个像total control是怎么样实现的。请先仔细注意一下total control这类软件不差数据线和插数据线时的不同。当插上数据线时,怎么控都行,但想wifi控制时是需要先插一下数据线的,而且当你重启手机后也是需要插数据线的。找到个问题的关键么,就是说每次重启手机后,都需要插一下数据线,那么为啥需要插一下数据线尼?因为它要做一个初始化的工作。我目前采用的就是这样的方式。
写一个dex文件,然后用pc写一个启动器,然后让dex监听一个固定的端口,这个dex文件的功能就是接受某一个触控消息然后将它转变为MotionEvent事件,然后执行。这就能理解为给手机一个我写的MotionEvent事件,然后从PhoneView等向下传递。下边开始一个思路的讲解,具体代码大家百度一下就知道了。
我将整个流程分为4部分:1数据源(手机A发送数据) 2被控制的手机(接收数据源,并转化) 3dex文件(接收自定义协议,执行协议) 4pc启动器
编写dex文件,先写一个java文件,然后再转dex文件。Java文件中绑定udp的服务,并将按自定义通信协议完成转换,如果你是一个小白,请你注意用最简单的方式(使用!@#等进行协议之间的分隔符,不要用json等传统协议,因为最简单的运行在手机的dex文件有好多依赖不能用)然后将有用的信息取出来后进行生成MotionEvent事件(请先打印多种情况下的MotionEvent事件看一看)至于怎么编写MotionEvent事件去百度就好,再此指出能够支持屏幕的多指,长按和音量键,开机键等。
pc启动器。2个功能,最好有adb命令的基础,没有的话就只要什么查一下命令吧,1首先检测手机sd卡的指定位置有没有你的dex文件,没有就传一个过去。2将这个dex文件运行起来。
手机A(pc,平板)等采集点击滑动点,并按照协议进行发送(注意注意注意:请不要用分辨率点,因为每个手机的分辨率不同,建议才用比例的方法)。被控手机B将手机A的数据源进行解析,并转化,再发送给dex文件。(关于手机中这2部分怎么传输,就涉及到了linux的传输,但是直接用udp吧我感觉还是最好的,像什么心跳之类的自己去想吧,想的越多优化越好)
整体流程就是这样,那些优化想的越多,效果就越好,我也不一 一指出了。按照流程去查一下,就ok了。写的优点乱,但是具体思路已经写下了。