原文地址:http://www.jianshu.com/p/988021487b5b

公司做的IM软件基于webrtc实现了音视频通话功能基础功能,新需求是要求通话的同时也可以处理别的东西,即在通话页面点击最小化按钮后视频通话页面变成了一个不大的窗口悬浮在窗口上且是全局的,即使回到home页面依然存在;

这种需求非常合理,符合大家一贯的使用习惯,体验性也很棒;

刚拿到需求在技术实现上并没有头绪,因为原本的视频通话展示逻辑是用的Activity,一开始想着通过改变Activity的尺寸来实现,但是基于Activity本身的生命周期特性决定了这样并不能达成缩小后的view界面悬浮在所有其他界面之上的要求;而安卓本身能够干这个的事情已知的是一个叫悬浮窗的东东,可以验证下;

好在这个功能像微信优酷都有实现,我们不妨试着看看他们是怎么做的。以QQ为例,正常视频通话点击最小化通话界面会缩小成一个很小的区域放在界面顶部

图来自网络

去系统那查看权限发现应用显示悬浮窗权限是允许的,我们把改权限设置为不允许,再次视频通话后点击最小化,显示悬浮窗权限未获取的对话框!果然!

那接下来的事情就好办了,将webrtc连接控制和流控制的逻辑抽取出来写成一个工具类,activity界面只做展示逻辑,点击最小化关闭activity,跳转到悬浮窗逻辑。悬浮窗逻辑这为了逻辑清晰我们可以放在一个service里创建,代码如下

public class VoipFloatService extends Service {private static finalStringTAG="FloatService";private WindowManager mWindowManager;private WindowManager.LayoutParams mLayoutParams;/*** float的布局view*/private ViewmFloatView;private GLSurfaceView glSurfaceView;private intmFloatWinWidth,mFloatWinHeight;//悬浮窗的宽高private intmFloatWinMarginTop,mFloatWinMarginRight;private intmLastX=0,mLastY=0;private intmStartX=0,mStartY=0;@Overridepublic void onCreate() {super.onCreate();LogEx.d(TAG,"onCreate: ");createWindowManager();createFloatView();}@Overridepublic void onDestroy() {super.onDestroy();LogEx.d(TAG,"onDestroy: ");removeFloatView();}private void createWindowManager() {LogEx.d(TAG,"createWindowManager: ");// 取得系统窗体mWindowManager= (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);//计算得出悬浮窗口的宽高DisplayMetrics metric =newDisplayMetrics();mWindowManager.getDefaultDisplay().getMetrics(metric);intscreenWidth = metric.widthPixels;mFloatWinWidth = (int) (screenWidth *0.8/3);mFloatWinHeight=mFloatWinWidth*4/3;mFloatWinMarginTop= (int)this.getResources().getDimension(R.dimen.rkcloud_av_floatwin_margintop);mFloatWinMarginRight= (int)this.getResources().getDimension(R.dimen.rkcloud_av_floatwin_marginright);// 窗体的布局样式// 获取LayoutParams对象mLayoutParams=newWindowManager.LayoutParams();// 确定爱悬浮窗类型,表示在所有应用程序之上,但在状态栏之下//TODO? 在android2.3以上可以使用TYPE_TOAST规避权限问题mLayoutParams.type= WindowManager.LayoutParams.TYPE_TOAST;//TYPE_PHONEmLayoutParams.format= PixelFormat.RGBA_8888;mLayoutParams.flags= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;// 悬浮窗的对齐方式mLayoutParams.gravity= Gravity.RIGHT| Gravity.TOP;// 悬浮窗的位置mLayoutParams.x=mFloatWinMarginRight;mLayoutParams.y=mFloatWinMarginTop;mLayoutParams.width=mFloatWinWidth;mLayoutParams.height=mFloatWinHeight;}/*** 创建悬浮窗*/private void createFloatView() {LogEx.d(TAG,"createFloatView: ");LayoutInflater inflater = LayoutInflater.from(VoipFloatService.this);mFloatView= inflater.inflate(R.layout.voip_float_layout, null);glSurfaceView= (GLSurfaceView)mFloatView.findViewById(R.id.float_gl_surface_view);glSurfaceView.setPreserveEGLContextOnPause(true);glSurfaceView.setKeepScreenOn(true);mWindowManager.addView(mFloatView,mLayoutParams);mFloatView.setOnTouchListener(newView.OnTouchListener() {@Overridepublic booleanonTouch(View v,MotionEvent event) {intaction = event.getAction();if(MotionEvent.ACTION_DOWN== action) {mStartX=mLastX= (int) event.getRawX();mStartY=mLastY= (int) event.getRawY();}else if(MotionEvent.ACTION_UP== action) {intdx = (int) event.getRawX() -mStartX;intdy = (int) event.getRawY() -mStartY;if(Math.abs(dx) >5|| Math.abs(dy) >5) {return true;}}else if(MotionEvent.ACTION_MOVE== action) {intdx = (int) event.getRawX() -mLastX;intdy = (int) event.getRawY() -mLastY;mLayoutParams.x=mLayoutParams.x- dx;mLayoutParams.y=mLayoutParams.y+ dy;mWindowManager.updateViewLayout(mFloatView,mLayoutParams);mLastX= (int) event.getRawX();mLastY= (int) event.getRawY();}return false;}});mFloatView.setOnClickListener(newView.OnClickListener() {@Overridepublic void onClick(View v) {maxZoom2WebRtcActivity();VoipFloatService.this.stopSelf();}});VideoRendererGui.setView(glSurfaceView, newRunnable() {@Overridepublic void run() {LogEx.d(TAG,"createFloatView: VideoRendererGui.setView localVideo run: ");if(WebRtcHelperEx.getInstance().isWebRtcChanelAlive()) {WebRtcHelperEx.getInstance().updateVideoUI(WebRtcHelperEx.latestLocalVideoSize,WebRtcHelperEx.latestRemoteVideoSize);}}});if(WebRtcHelperEx.getInstance().isWebRtcChanelAlive()) {LogEx.d(TAG,"createFloatView: webrtc instance is alive and we will call resetRenders");WebRtcHelperEx.getInstance().resetRenders();WebRtcHelperEx.getInstance().updateVideoUI(WebRtcHelperEx.VIDEOSIZE_SMALL,WebRtcHelperEx.VIDEOSIZE_BIG);}}private void removeFloatView() {LogEx.d(TAG,"removeFloatView: ");if(mFloatView!=null&&mWindowManager!=null) {mWindowManager.removeView(mFloatView);}}/*** 单击后回到@WebRTCActivity以切换为大尺寸页面*/private void maxZoom2WebRtcActivity() {//TODO? 跳转到Activity}}

当点击最小化后关闭了视频通话中的WebRtcActivity,并创建FloatService,在其中创建悬浮窗口并设置Touch事件使其可以随手指滑动,将webrtc流渲染到悬浮窗口内的glSurfaceView上。

当点击该窗口时,关闭floatService,移除悬浮窗口,跳转打开WebRtcActivity。

以上就是Activity视频页面和悬浮窗口页面互相切换的逻辑,效果如下图

思考像微信QQ视频通话最小化后悬浮展现实现思路相关推荐

  1. Android基于腾讯云实时音视频实现类似微信视频通话最小化悬浮

    最近项目中有需要语音.视频通话需求,看到这个像环信.融云等SDK都有具体Demo实现,但咋的领导对腾讯情有独钟啊,IM要用腾讯云IM,不妙的是腾讯云IM并不包含有音视频通话都要自己实现,没办法深入了解 ...

  2. 窗口最小化后不出现在任务栏上

    问题:网页和QQ对话框以及所有的东西一最小化后就不见了.感觉像是被关闭了一样,其实,窗口虽然没有在任务栏上出现,但还是处于打开的状态的. 测试:作一个最简单的测试,在桌面上新建一个Excel文档,最小 ...

  3. 程序最小化后释放了很多的内存的原因

    程序最小化后释放了很多的内存的原因 http://soartomato.iteye.com/blog/726135 博客分类: expr Windows.net应用服务器虚拟机软件测试 偶然发现程序最 ...

  4. win10 通过xrdp远程连接到ubuntu后,显示顶端快捷工具栏,显示最小化后的应用

    问题描述: win10 通过xrdp远程连接到ubuntu后,屏幕顶端的快捷工具栏消失了,导致打开应用不方便,且打开的应用最小化后也不容易找到. 解决方法: 自己一共找到了两种解决方法,其中推荐方法1 ...

  5. Qt4 到Qt5 最小化后 点击任务栏不显示问题

    1.在Qt4 中  QML  传递信号到QWidget   设置  setWindowState(Qt::WindowMinimized);   点击任务栏显示没有问题 2.在Qt5 中  QML 传 ...

  6. 窗口最小化后在任务栏上看不到

    本文出自Simmy的个人blog:西米在线  http://simmyonline.com/archives/645.html 症状:用户反应其程序点窗口最小化后,在任务栏上没有显示,如word, e ...

  7. C# picturebox在form_load和最小化后内容无法显示

    用C#写个picturebox,代码如下: private void paint2(){Graphics g = pictureBox.CreateGraphics();g.Clear(Color.W ...

  8. PyQt5窗口最小化后,任务栏窗口预览(Windows速览)持续刷新(C++ Qt同理)

    PyQt5 / Qt窗口最小化后,鼠标悬停,任务栏窗口预览(Windows速览)继续保持刷新状态 问题描述 解决方案 完整代码 问题描述 最近在做一个PyQt5项目,其中有一个功能是窗口启动后开始计时 ...

  9. win10程序最小化后任务栏没有显示的解决方法

    通常情况下我们会在电脑打开很多应用程序,当我们暂时不需要使用的时候我们会将它最小化,最小化后会以缩略图的形式出现在任务栏中,等我们有需要的时候再打开就行.但是今天用电脑时发现将程序最小化之后任务栏中却 ...

  10. 网页音乐 最小化后自动暂停_当其他声音开始播放时,如何自动暂停音乐

    网页音乐 最小化后自动暂停 You're listening to music, but then you click a video. Now both things are playing at ...

最新文章

  1. postgres语法_SQL Create Table解释了MySQL和Postgres的语法示例
  2. a标签跳页传参,以及截取URL参数
  3. OpenCASCADE:使用 XDE 文档
  4. JQuery--事件
  5. Java之WeakReference与SoftReference使用讲解
  6. matlab 可视化 —— 高级 api(montage)、insertObjectAnnotation、insertMaker
  7. 邮票面值设计java_邮票面值设计
  8. java实现爬虫_手把手教你从零开始用Java写爬虫
  9. 信息安全制度(用户篇)
  10. Git捷径,游戏搞定!
  11. 十大常用经典排序算法总结!!!
  12. html5微信mp3播放器代码,[微信音频播放器] html5 audio 制做的微信播放器
  13. 全屏网页时钟屏保flipclock-beautify,简约风格,电脑手机均支持访问
  14. 2020-08-31 ubuntu18.04下安装gitlab,以及使用邮箱注册
  15. Hdu--5064(DP)
  16. 轻量级任务调度中间件
  17. 慕课乐学python单元测试答案_中国大学慕课答案第五章单元测试答案_乐学软件工程完整答案...
  18. 2021年全国Python程序员薪资曝光,网友:吹的不多.....
  19. 怎么把pdf转换成excel转换器免费版
  20. QT 之 编译错误总结(2)

热门文章

  1. 2021-1-30最短路入门
  2. Linux中的Cat命令–如何使用Cat或Touch创建文本文件
  3. js经纬度打开腾讯地图
  4. 外贸工具WhatsApp
  5. el-upload手动上传图片并限制图片数量、大小和格式
  6. ACM779-兰州烧饼
  7. NYOJ779 兰州烧饼
  8. 电脑qq如何发送html消息,电脑QQ如何设置按Enter键发送消息
  9. Offer是否具有法律效力
  10. pg PostGIS教程:几何图形(geometry)