聊一聊安卓WallpaperService壁纸窗口触摸事件接收原理-第一篇

Android14 系统Wallpaper详解 壁纸服务分析 安卓的动态壁纸可以归属到SystemUI中,是SystemUI管理的一部分,安卓支持静态壁纸,同时也支持动态壁纸(level 7后加入)可以从设备的内部或者是外部存储中选择一个图片资源来作为静态壁纸,此外也可以设置壁纸跟随时间的变化进行一些变化(例如切换不同的图片资源),这也是安卓的特色功能之一。需要说明的是当某个应用通过系统的接口设置为壁纸应用后,会启动一个壁纸服务,该服务的优先级很高,从某种程度上来说是不会被系统主动杀死的(但是可以被手动停止)。 阅读详情
AI摘要

本文围绕安卓动态壁纸触摸事件接收原理展开。静态壁纸触摸交互需求少,动态壁纸则需求大增。剖析了动态壁纸接收触摸事件的代码设置,如重写 onCreate 并调用 setTouchEventsEnabled(true)。还阐述了接收原理,包括 mWindowFlags 设置、InputChannel 创建等,事件最终到 WallpaperService 内部类 Engine 的 onTouchEvent 方法。

背景:

在使用android手机时候,大家壁纸可能一般都是使用的静态壁纸,静态壁纸一般就是设置一张静态,这种静态壁纸因为是固定的一张图片,所以对壁纸触摸交互这块需求比较少,但是如果设置的是一个动态壁纸,那么这个触摸交互需求就会大大增加。具体可以看下面的一个整体旋转的动态壁纸触摸场景:
在这里插入图片描述
明显可以看到这里的有一个正方体一直在旋转着,在鼠标触摸桌面时候,不仅仅桌面有响应事件,也发现Wallpaper也会绘制一个触摸点为圆心的圆,那么下面就来剖析一下Wallpaper壁纸窗口为啥可以实现触摸事件的接收原理,下面是桌面和壁纸窗口图层的位置,桌面肯定是位于壁纸上面的。
在这里插入图片描述

学习了马哥input课程就知道,正常逻辑的话上面有图层覆盖而且可以接受事件的话,那么底部的窗口肯定无法接受事件,但是上面看到动态壁纸情况下,明显可以看到桌面响应了触摸事件,壁纸也有响应,这个事件透传我们下一篇来分析input汇总原理,本节先来剖析上层WallpaperService的事件接受。

剖析动态壁纸事件接收代码

动态壁纸要接收触摸事件,还是需要一些额外设置的,具体的设置方法如下:

     @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
            super.onCreate(surfaceHolder);

            // By default we don't get touch events, so enable them.
            setTouchEventsEnabled(true);
        }

一般动态壁纸要继承WallpaperService时候会重写onCreate,在onCreate中需要调用 setTouchEventsEnabled(true)让壁纸服务可以接受对应的触摸事件,如果设置为true,默认是不可以收到触摸事件。
上面设置完成后就可以让系统把触摸事件传递到WallpaperSerivce了,具体哪个方法接收呢?
这里其实WallpaperSericce的内部类Engine也有个onTouchEvent方法,它可以实现对触摸事件的接受
在这里插入图片描述
一般会重写这个方法进行相关的事件处理,比如上面正方体动态壁纸的处理如下:

       /*
         * Store the position of the touch event so we can use it for drawing later
         */
        @Override
        public void onTouchEvent(MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_MOVE) {
                mTouchX = event.getX();
                mTouchY = event.getY();
            } else {
                mTouchX = -1;
                mTouchY = -1;
            }
            super.onTouchEvent(event);
        }

这里的处理只是记录了一下坐标,记录坐标目的是为了在正方体绘制时候用这个坐标来绘制一个圆:

        /*
         * Draw one frame of the animation. This method gets called repeatedly
         * by posting a delayed Runnable. You can do any drawing you want in
         * here. This example draws a wireframe cube.
         */
        void drawFrame() {
            final SurfaceHolder holder = getSurfaceHolder();

            Canvas c = null;
            try {
                c = holder.lockCanvas();
                if (c != null) {
                    // draw something
                    drawCube(c);
                    drawTouchPoint(c);//绘制触摸点的圆
                }
            } finally {
                if (c != null) holder.unlockCanvasAndPost(c);
            }

            // Reschedule the next redraw
            mHandler.removeCallbacks(mDrawCube);
            if (mVisible) {
                mHandler.postDelayed(mDrawCube, 1000 / 25);
            }
        }

上面就是靠drawTouchPoint方法来绘制触摸点的圆:

     /*
         * Draw a circle around the current touch point, if any.
         */
        void drawTouchPoint(Canvas c) {
            if (mTouchX >=0 && mTouchY >= 0) {
                c.drawCircle(mTouchX, mTouchY, 80, mPaint);
            }
        }

整体使用也是非常简单,那么下面来看看这块WallpaperSerice可以接受触摸事件的一个初步原理。

WallpaperService触摸事件接收原理

先从 setTouchEventsEnabled(true)作为切入点开始剖析

      /**
         * Control whether this wallpaper will receive raw touch events
         * from the window manager as the user interacts with the window
         * that is currently displaying the wallpaper.  By default they
         * are turned off.  If enabled, the events will be received in
         * {@link #onTouchEvent(MotionEvent)}.
         */
        public void setTouchEventsEnabled(boolean enabled) {
            mWindowFlags = enabled
                    ? (mWindowFlags&~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
                    : (mWindowFlags|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
            if (mCreated) {
                updateSurface(false, false, false);
            }
        }

可以看到这里主要是对mWindowFlags进行了设置,如果enable就是不进行设置FLAG_NOT_TOUCHABLE,可以通过dump确认。

dumpsys  window windows

默认的静态壁纸,不可以触摸
在这里插入图片描述

自定义动态壁纸,可以触摸,就没有flag为NOT_TOUCHABLE
在这里插入图片描述
那么setTouchEventsEnabled(true)后,事件又是怎么到传递到WallpaperService的呢?
可以看看updateSurface方法,在窗口添加时候创建好对应的InputChannel
在这里插入图片描述
所以上面就可以看得出来无论是否WallpaperService是否enable Touch,都会创建好对应的InputChannel即在InputDispatcher中都会有对应的InputWindow,只不过这个时候窗口InputWindow因为设置了NOT_TOUCHABLE导致不会进行派发到这个窗口。
可以通过dumpsys input来看看静态壁纸情况:

dumpsys input

在这里插入图片描述再看看事件的怎么到的WallpaperSerice的onTouchEvent
先看看WallpaperInputEventReceiver接收
frameworks/base/core/java/android/service/wallpaper/WallpaperService.java

       final class WallpaperInputEventReceiver extends InputEventReceiver {
            public WallpaperInputEventReceiver(InputChannel inputChannel, Looper looper) {
                super(inputChannel, looper);
            }

            @Override
            public void onInputEvent(InputEvent event) {
                boolean handled = false;
                try {
                    if (event instanceof MotionEvent
                            && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                        MotionEvent dup = MotionEvent.obtainNoHistory((MotionEvent)event);
                        dispatchPointer(dup);//这里会调用dispatchPointer派发
                        handled = true;
                    }
                } finally {
                    finishInputEvent(event, handled);
                }
            }
        }

再看看dispatchPointer

 private void dispatchPointer(MotionEvent event) {
            if (event.isTouchEvent()) {
                synchronized (mLock) {
                    if (event.getAction() == MotionEvent.ACTION_MOVE) {
                        mPendingMove = event;
                    } else {
                        mPendingMove = null;
                    }
                }
                Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);//主要是发送了msg
                mCaller.sendMessage(msg);
            } else {
                event.recycle();
            }
        }

再看看MSG_TOUCH_EVENT的消息处理:

  case MSG_TOUCH_EVENT: {
                    boolean skip = false;
                    MotionEvent ev = (MotionEvent)message.obj;
                    if (ev.getAction() == MotionEvent.ACTION_MOVE) {
                        synchronized (mEngine.mLock) {
                            if (mEngine.mPendingMove == ev) {
                                mEngine.mPendingMove = null;
                            } else {
                                // this is not the motion event we are looking for....
                                skip = true;
                            }
                        }
                    }
                    if (!skip) {
                        if (DEBUG) Log.v(TAG, "Delivering touch event: " + ev);
                        mEngine.onTouchEvent(ev);//调用到mEngine的onTouchEvent
                    }
                    ev.recycle();

上面就展示了,最后事件到了WallpaperSerice内部类Engine的onTouchEvent方法。

具体事件是如何可以穿透壁纸上面窗口图层Launcher的,下一篇文章再给大家分析。

壁纸触摸事件总结:

1、壁纸窗口本身在创建时候就已经有创建好对应的InputChannel,而且也会和正常窗口一样会有InputWindow在InputDispatcher,而且位置一般处于最底层

2、要让壁纸可以接收事件,需要调用 setTouchEventsEnabled(true),主要是把Window不进行设置NOT_TOUCHABLE的flag。

3、事件在InputDispatcher派发时候,可以透过Launcher传递到Wallpaper的窗口,但如果有NOT_TOUCHABLE的flag那么就不会传递,具体如何可以透传下一篇分析。

更多framework实战开发干货,请关注下面“千里马学框架”

Unity开发Android动态壁纸:从原理到部署的完整指南 动态壁纸作为Android系统的一项特色功能,允许开发者在设备桌面上创建可交互的视觉体验。其核心原理在于通过WallpaperService在系统Surface上托管图形渲染进程,这为游戏引擎的集成提供了技术基础。Unity引擎凭借其强大的实时3D渲染能力和跨平台特性,成为实现高性能、高表现力动态壁纸的理想选择。通过将Unity运行时嵌入到Android动态壁纸服务中,开发者能够将复杂的粒子系统、3D场景和交互逻辑引入桌面环境,极大地拓展了动态壁纸的应用场景和创意空间。本文聚焦于Unity与Android动 阅读详情

相关推荐

Unity引擎打造Android动态壁纸:原理、实现与性能优化全解析

动态壁纸作为Android系统的特色功能,通过WallpaperService在系统层级提供动态视觉体验。其核心原理是利用Surface进行帧绘制,传统方案受限于Canvas或OpenGL ES的图形处理能力。Unity引擎凭借其强大的实时渲染与跨平台特性,为动态壁纸开发带来了突破。通过JNI与AndroidJavaObject实现的双向通信机制,Unity运行时得以嵌入WallpaperService,将游戏级的粒子效果与物理模拟应用于系统组件。这种技术方案尤其适用于需要复杂视觉效果与交互逻辑的场景,例如

weixin_33946605的博客 380

Android T wallpaper相关流程

什么是壁纸? 壁纸即是一个壁纸服务,每换一张壁纸 ,就是将该图片写入壁纸文件,再启动一个壁纸服务读取该壁纸文件显示出来的过程。

yimelancholy的博客 2748

Android动态壁纸实现与WallPaPerService教程

本文还有配套的精品资源,点击获取 简介:Android动态壁纸是提供动画或交互效果的个性化壁纸类型,通过WallPaPerService组件实现。该组件是Android服务的一个子类,允许开发者创建自定义的动态壁纸应用程序。本文将探讨WallPaPerService的详细使用方法,并提供创建、实现动态壁纸服务的步骤。动态壁纸的动画效果通过Canvas和Handler实现,并...

weixin_42348783的博客 4190

WallpaperService壁纸实现

1.使用Bitmap作为壁纸WallpaperManager wallpaperManager = WallpaperManager.getInstance(this); try { Bitmap wallpaperBitmap = BitmapFactory.decodeResource(getResources(), R.raw.girl); wallp...

xd0123456789的博客 4425

深入解析Android动态壁纸源码

Android动态壁纸为用户提供了一种全新的交互式桌面体验,不同于静态的背景图像,动态壁纸能够响应用户的操作,如触摸、滑动等,并以动画的形式展示不同的视觉效果。动态壁纸不仅增加了美观性,也提升了用户的个性化需求。为了深入了解如何创建动态壁纸,本章将对Android动态壁纸的基础概念和主要特性进行简要介绍,为后续章节深入探讨Android动态壁纸开发技术打下坚实基础。在动态壁纸的实现中,绘制机制是构建视觉效果的核心。Android 提供了强大的绘图 API,其中Canvas类是所有绘图操作的基础。

weixin_29940495的博客 1154

Android动态壁纸开发实战教程

float x, y;// 当前坐标// 速度向量// 半径int color;// 颜色int life;// 生命值// 是否激活x += vx;y += vy;life--;// 逐渐缩小今天我们从零开始,搭建了一个完整的动态壁纸工程框架,涵盖了:✅ 服务创建✅ 清单配置✅ 生命周期管理✅ 高效绘图✅ 交互响应✅ 资源优化但这只是起点。未来的动态壁纸完全可以做到:🧠结合传感器:根据手机朝向调整星空视角;🌤️。

weixin_33773084的博客 1223

android 12 WallpaperService

我整理的一些关于【XML】的项目学习资料(附讲解~~)和大家一起分享、学习一下:https://d.51cto.com/Hpqqk2深入理解 Android 12 的 WallpaperService 随着移动设备的快速发展,Android操作系统在不断引入新的功能和改进。在Android 12中,WallpaperSe...

weixin_42088076的博客 398

Android樱花动态壁纸完整实现项目.zip

此方法是创建子类的实例的地方。这个 Engine 实例负责处理壁纸的绘制和用户交互。开发者可以在这个子类中重写绘制和处理输入的方法,例如和。: 当壁纸需要为一个新窗口创建视图时,该方法会被调用。开发者可以在这里初始化与窗口相关的视图或逻辑。和onBind(): 这些方法来自 Service 类,处理客户端请求绑定或启动服务的逻辑。对于动态壁纸而言,通常不需要客户端的绑定操作,因此onBind()通常返回 null。而则用于处理启动服务时的操作。作为Service。

weixin_32252929的博客 738

安卓动态壁纸开发

一般的壁纸设定,只需要在获取壁纸权限后,只需要getWallPagerManager对象来设定壁纸(静态) 与安卓应用的开发不同,动态壁纸的开发不需要传统的布局文件,也不要活动(activity)来管理,也是一种服务(WallPagerService)来维护着,里面自带有一个SurfaceHolder来进行图形的实时渲染,来达到壁纸动态的效果。 动态壁纸的设定可分为如下三步:  ...

ahuotai8429的博客 696

Android壁纸功能源码解析与实战

Android壁纸服务是操作系统中负责管理壁纸显示逻辑和功能的核心组件。它的主要任务是为用户提供美观的视觉效果,同时确保壁纸应用的资源消耗保持在合理范围内。壁纸服务需要处理静态与动态壁纸的渲染,响应用户交互,以及与系统资源的高效管理。

weixin_42350014的博客 937

Android多媒体开发实战:屏保程序设计与实现详解

构建一个功能完整的动态壁纸引擎,首要任务是继承并正确实现类。该类作为抽象基类,提供了与系统底层绘图环境交互的桥梁。开发者需遵循特定的设计模式与安全边界,以确保服务运行时的稳定性与资源可控性。

weixin_42577243的博客 535

Android实现自定义动态壁纸(附带源码)

Android实现自定义动态壁纸(附带源码)

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 1231

Android屏幕保护程序开发详解与实战

除了使用系统动画类,开发者还可以通过控制绘制参数实现自定义动画。例如,实现一个简单的旋转动画:代码逻辑分析:使用进行旋转操作,参数为角度与旋转中心。save()和restore()用于保存和恢复画布状态,避免影响后续绘制。每次绘制后更新旋转角度,形成持续旋转效果。通常配合一个绘制线程或Choreographer进行循环绘制。除了使用系统库,开发者也可以自定义手势识别逻辑。例如识别“双击”动作。

weixin_35728286的博客 592

ffmpeg实战教程(十)ffmpeg/camera实现最近很火的视频壁纸,相机壁纸

本篇实现一个有意思的玩意儿,视频壁纸,相机壁纸 这玩意好像现在还都是国外版本,哈哈 先上图:视频壁纸 相机壁纸 1.动态壁纸制作的知识: 每一个动态壁纸都继承自WallpaperService,其中必须实现的抽象方法onCreateEngine,返回一个Engine对象,实际上所有的绘图与刷新都是由engine完成。如下 public class VideoLiveWallpaper extends WallpaperService { // 实现WallpaperService必须

withoutfear的博客 998

matlab 三维绘图 抛光,瓷砖抛光过程建模与仿真

:瓷砖抛 光过程 建模与仿真朱 成 就(广 东工业大学 机 电工程 学院, 广东广州 )摘要 :瓷砖的抛磨影响 因素众 多 ,实际磨削加工时容易出现漏抛 、返抛现象 。对陶瓷抛光机磨头进行运动学分析 ,并基于不 同粒度号 的磨 粒在一定压力下的加工深度模型 ,探讨抛光机磨 头转 速 、横梁摆动频率 、传送速度对瓷砖抛光加工表 面均匀性 的影响,然 后结合 磨削机理使 用 对陶瓷抛光过程进行仿真 ...

weixin_36331058的博客 747

MC1496乘法器AM调制电路搭建全流程(附Multisim 14.0仿真文件)

本文提供了基于MC1496乘法器搭建AM调制电路的完整实战指南。针对仿真模型缺失的痛点,详细讲解了从晶体管级手动构建MC1496等效模型,到外围电路设计、调制度参数计算与调节,并在Multisim 14.0中进行仿真验证的全流程。通过深度剖析MC1496内部原理与AM信号调制机制,帮助读者获得从仿真到实践的可控设计与排错能力。

weixin_29190169的博客 593

Android源码之动态壁纸引擎

动态壁纸蛮好玩的,也没接触过,看官方有就拿了学习下,是第一次接触引擎Engine,激动兴奋...效果做出来了,记录笔记,吼吼,跟大家交流学习, 废话不多说了,先看效果,再看源码,供大家交流学习,今天的效果如下图所示,因为手机开机后就要加载图片,所以就直接从开机启动完成后讲了,看图...  未开锁时立方体形式一: 开锁时立方体形式一与二: 简单的绘制效果,因为立方体都是下面这些图(由...

weixin_33973609的博客 380

电力抄表协议DL/T645和698.45到底有啥区别?一张图帮你选对协议

本文深入对比了电力抄表协议DL/T645和DL/T698.45的技术差异,从协议架构、报文结构、功能覆盖到实施成本进行全面分析。通过实际案例和数据,揭示698.45协议在通信效率、业务扩展性和长期成本上的优势,并提供清晰的选型决策流程图,帮助工程师根据具体需求选择最适合的电力抄表协议。

weixin_38168696的博客 401

Android 12壁纸透看机制:从原理到实践,深度解析锁屏与桌面切换

在Android系统开发中,壁纸渲染与管理是影响系统视觉流畅性与性能的关键模块。其核心原理在于WallpaperService通过Engine组件响应系统状态指令,动态调整绘制行为。这一机制的技术价值在于,它能在不增加额外资源开销的前提下,确保前景内容(如锁屏时钟、桌面图标)在任何背景下都清晰可读,从而提升用户体验。典型的应用场景包括系统解锁、应用切换等涉及界面层级变化的时刻。本文聚焦于Android 12引入的“透看”(Peek-through)模式,深入剖析了WallpaperManagerServic

weixin_29279047的博客 354

Hypermesh二次开发实战:Tcl命令分类与常用函数详解(附避坑指南)

本文深入解析Hypermesh二次开发中Tcl命令的三大核心类别:界面命令、查询命令与修改命令。重点剖析了*createmark集合管理与hm_getvalue信息查询等关键函数的实战用法,并提供了避免Mark覆盖、生命周期管理等常见陷阱的实用指南,旨在帮助CAE工程师构建高效可靠的自动化前处理流程。

weixin_29233333的博客 240

从零到一:手把手教你用HFSS仿真60GHz圆极化磁电偶极子天线(附参数调优心得)

本文详细介绍了在HFSS中设计60GHz圆极化磁电偶极子天线的全流程,包括仿真环境搭建、参数化建模、收敛性优化和性能验证。通过系统化的参数扫描和优化策略,显著提升了天线的轴比带宽和增益性能,为毫米波通信应用提供了高效的天线设计解决方案。

weixin_42614269的博客 311

Android Launcher开发之动态壁纸(LiveWallPaper)气泡流动效果

最近在研究Laucher应用,今天写了一下四组件中的壁纸(WallPaper),关于静态壁纸的实现,比较简单,在此就不再描述. 参考了系统源代码之后,我自己做了一个简单的动态壁纸:气泡流动效果. 图案比较简单,但基本原理可在此例子上加以扩展,比如3D动画效果,复杂的触摸改变动画事件,有兴趣的朋友可以试一试. 大概效果如下,最开始得时候,会从四个角落的方向浮出四个气泡,然后以一定的路线移动,当...

mmdev 638

Authentication Assertion Tickets,SAP 系统到系统单点登录里的短命凭证

SAP 系统间的身份传递机制存在 Authentication Assertion Ticket 和 SAP Logon Ticket 两种易混淆的凭证。前者用于系统间短时身份委托(有效期2分钟,通过HTTP头传输),后者用于浏览器SSO(可配置有效期,通过Cookie传输)。Assertion Ticket依赖签发系统的数字签名和严格的时间同步,适用于ABAP/Java系统间的后台作业调用。现代SAP架构已转向OAuth 2.0等标准协议,但老系统中仍需注意两种票据的关键差异:传输方式、有效期、接收方限制

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 602
上一篇: wms窗口/多窗口/自由窗口systemui侧边栏手势退出实战-学员作业
下一篇: 你知道桌面和壁纸Wallpaper都接收触摸事件原理吗?--第二篇
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值