前言
通过Websocket进行图片流传输来实现
现在要实现Android采集屏幕通过Websocket在另一个Android设备上显示
那么我们就要采集屏幕
=>生成二进制
=>ws传输
=>ws接收
=>二进制转图片
=>播放图片
本地测试
在接入websocket之前 我们现在本地实现采集屏幕
=>生成二进制
=>二进制转图片
=>播放图片
这样的流程
图片工具类
1 | import android.graphics.Bitmap; |
先看下BitmapFactory.Options里我们使用的主要属性
- inBitmap:如果该值不等于空,则在解码时重新使用这个Bitmap。
- inMutable:Bitmap是否可变的,如果设置了
inBitmap
,该值必须为true
。 - inPreferredConfig:指定解码颜色格式。
- inJustDecodeBounds:如果设置为
true
,将不会将图片加载到内存中,但是可以获得宽高。 - inSampleSize:图片缩放的倍数,如果设置为2代表加载到内存中的图片大小为原来的2分之一,这个值总是和
inJustDecodeBounds
配合来加载大图片,在这里我直接设置为1,这样做实际上是有问题的,如果图片过大很容易发生OOM。
注意
我们在用BitmapFactory生成图片的时候如果不设置的option的话,每次都会生成新的Bitmap对象,频繁的生成释放会导致内存抖动,所以可以用inBitmap来防止,我这里暂时还没用,如果使用的话,我们可以定义一个图片池,循环利用其中的对象,但是一定要保证正在展示的对象不能被同时被修改,会导致显示有横线。
图片的编码格式用png和webp都可以,不知道为啥jpeg不行,很是奇怪!
图片播放器
1 | import android.content.Context; |
注意
图片播放是可以用ImageView来直接加载,但是问题是如果接收到的图片的间隔不一致的时候会感觉明显的卡顿,所以用自定义TextureView来处理,里面缓存要保存的图片,以每秒25帧播放,但是如果图片的产生速度较快的话,会导致缓存的图片越来越多,从而oom了,所以我在缓存中至多保留最新的三个,其它的丢弃
Activity
1 | private fun initTask() { |
注意
image.copy(Bitmap.Config.ARGB_8888, true)
这句代码非常关键 在我们采集view的图片的时候,获取到的Bitmap对象的指针是不变的,如果不做copy,那么在我们异步转换二进制的时候就会中途Bitmap对象被修改,导致图片中会产生横线。
通过WS传输
考虑到以后二进制传输其它类型的数据,所以我这里定义了数据的格式
数据头
+JSON数据
+传输数据
数据头
用来保存JSON数据的长度,方便截取JSONJSON数据
中保存要传输的参数传输数据
才是真正要传输的二进制数据
数据传输
1 | var msg = JSON.toJSONString(obj) |
数据接收
1 | val dataHead = ByteArray(6) |
方法介绍
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
代码解释:
- Object src : 原数组
- int srcPos : 原数组的起始位置
- Object dest : 目标数组
- int destPos : 目标数组的起始位置
- int length : 要Copy的数组的长度