美文网首页
App桌面浮窗实现

App桌面浮窗实现

作者: Magic旭 | 来源:发表于2021-01-11 17:34 被阅读0次

背景

在某些场景下,应用退到后台其实还需要保留与用户一定程度的交互,这时候就衍生出今天的主题,App桌面浮球的实现。具体内部实现其实也不难,下面我会带大家一步步分析整个流程。

基础知识

杂七杂八
  1. 有了解过App启动流程的同学肯定都或多或少接触过LaunchActivity的源码,LaunchActivity是继承与Activity的,手机桌面图标就是通过LaunchActivity来启动以安装的应用的。下面介绍个可以在线查看源码的网站👉在线查看源码

  2. 看过activity的setContent的源码都知道,内部主要是phoneWindow里面DecorView添加setContent里指定的布局,而布局类型是PhoneWindow的generateLayout方法里会根据当前用户设置的主题去设置对应的Feature,接着,根据对应的Feature来选择加载对应的布局文件。然后将刚刚inflate出来的View往DecorView里添加。详细的可以看这篇文章介绍👉setContent内部密码

  3. Window都是通过WindowManager创建、管理的,然而实现WindowManager唯一类是WindowManagerImpl,但实际做工作的是WindowManagerGlobal。可以看这篇文章介绍Window和WindowManager的创建与Activity关系👉Window和WindowManager的创建与Activity关系
    提示:里面会涉及到AIDL进程通信获取WindowServiceManager(行业话:Binder驱动获取client),可以先了解Linux的mmap和android binder驱动如何实现的。

浮球实现

实现原理分析
  1. 上面分析了我们桌面应用是一个继承Activity的类,那么如果我们调用WindowManager创建一个Window,然后塞入一个我们想要的展示在手机桌面的View;或者是说WindowManager能直接给个api让我们把想要展示的View塞入,就更完美了。

  2. 大胆假设后就要小心求证了,下面回到我们的代码中进行分析下。


    WindowManager搜addView方法

    上面通过WindowManager的接口搜全部function,我们搜到一个符合我们预想的function。

  3. ViewManager接口,ViewManager的注解是说,给一个Activity添加or移除一个View;可以通过Context.getSystemService(java.lang.String)获取到相应的对象。

核心代码
  1. 首先要获取到ViewManager的对象。刚刚基础知识补充道了LaunchActivity是一个Activity,所以这里通过WINDOW_SERVICE获取到桌面的LaunchActivity。WINDOW_SERVICE的注解:通过该字符串访问系统的窗口管理器。
private var mWindowManager: WindowManager =
        context.applicationContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
  1. 获取到系统管理器后,我们就要准备好我们addView的过程。了解过自定义View的童鞋都知道addView要准备的包括:View本身和LayoutParams。那我们要实现桌面浮窗也必须要准备好这两样。View的话没什么好详细讲解的,这个根据具体业务决定的。那么我们下面讲解下LayoutParams这部分。
private fun generateLayoutParams(): WindowManager.LayoutParams {
        val params = WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            getWindowType(),
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or // Keeps the button presses from going to the background window
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or // Enables the notification to recieve touch events
                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,// Draws over status bar
            PixelFormat.TRANSLUCENT
        )
        params.gravity = Gravity.LEFT or Gravity.TOP
        params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
        return params
    }

    /**
     * http://liaohuqiu.net/cn/posts/android-windows-manager/
     * @return Window的type类型
     */
    fun getWindowType(): Int {
        return if (isFloatWindowOpAllowed(mApplicationContext)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else WindowManager.LayoutParams.TYPE_SYSTEM_ERROR
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
        } else if (Build.VERSION.SDK_INT >= 25) {
            //7.1系统修复toast问题,导致悬浮球不能常驻
            WindowManager.LayoutParams.TYPE_PHONE
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams.TYPE_TOAST
        } else {
            WindowManager.LayoutParams.TYPE_SYSTEM_ERROR
        }
    }

上面getWindowType方法是设置window的type,那是因为window的type能决定在UI展示上层级问题。还有上面涉及到的gravity和softInputMode用处可以看这篇博客介绍👉Window详解

  1. 当View和LayoutParams都准备好以后,我们就可以进行我们的addView的操作了。
//显示桌面浮窗
mWindowManager.addView(view, layoutParams)
//移除桌面浮窗,注意上下两个view必须是同个对象,要不然你应该懂会出现什么问题的😼
mWindowManager.removeView(view)

大家想看详细的project可以自行clone来看:demo的github地址: feature_1.0.0分支

总结

  1. 当基础知识不断巩固后,你可以用一个更好理解的角度去想明白这段代码的含义。例如上面的浮窗实现,ViewManager接口注解提及到的给activity添加/移除View,当你没理解桌面app启动如何进行,没了解到LaunchActivity是集成Activity的时候,可能你就很难将ViewManager的注解意思理解通透。
  2. 学习是一个慢慢积累的过程,一起加油吧💪💪💪💪

相关文章

  • App桌面浮窗实现

    背景 在某些场景下,应用退到后台其实还需要保留与用户一定程度的交互,这时候就衍生出今天的主题,App桌面浮球的实现...

  • 【产品有感】虾米音乐

    1.桌面悬浮窗 桌面悬浮窗这个功能挺好的,让我们不用进入APP也可以换歌切歌,很方便。 2.在线播放品质 智能选择...

  • android----悬浮窗

    众所周知,像qq音乐,当退出qq音乐app时,歌词会在桌面上显示,这里可以用悬浮窗实现。 用一个很简单的TextV...

  • 浮窗广告的实现原理

    很多第三方的广告系统都是使用document.write来加载广告,如下面的一个javascript的广告...

  • 惰性单例

    定义在需要的时候创建对象的实例 惰性单例实现div浮窗

  • Android实战——系统悬浮窗踩坑记

    1.背景介绍 开启悬浮窗后,小窗悬浮在app内及桌面上,并保持悬浮窗页面所有状态 预览 路由介绍 功能概览(⚠️:...

  • Android使用WindowManger实现桌面悬浮窗

    如果想实现一个在桌面显示的悬浮窗,用Dialog、PopupWindow、Toast等已经不能实现了,他们基本都是...

  • (转)Flutter性能监控工具(2)--- Performan

    0x00 前言 PerformanceOverlay是在app上显示性能统计数据的浮窗。PerformanceOv...

  • Android 开发之锁屏弹窗

    尝试利用 WindowManager 添加浮窗的方式实现 想在锁屏上面实现弹窗,第一个想法就是利用 WindowM...

  • 微信浮窗、微信浮球功能实现demo

    微信6.6.7版本近日更新了,最大的亮点莫过于浮窗功能,主要用于将微信文章嵌入到浮窗内,方便大家看文章被其他信息打...

网友评论

      本文标题:App桌面浮窗实现

      本文链接:https://www.haomeiwen.com/subject/pqyfaktx.html