您的位置首页  散文杂谈

performclick(performclick不执行)没想到

会议室大屏是公司内部的一体化会议室管理系统,集成了Android平板硬件、服务与监控后台以及前台展示App。

performclick(performclick不执行)没想到

 

前言会议室大屏是公司内部的一体化会议室管理系统,集成了Android平板硬件、服务与监控后台以及前台展示App行政和IT部门联合发起了该项目,目的是为了提高会议室利用率,提升现场定会用户体验大屏主要适用场景为现场临时定会和小范围地点优先的临时会议。

上线半年以来,作为邮箱预定会议的另一种补充使用场景,逐渐被越来越多的同学所接受并使用

背景会议室App与我们平常的上架App,在开发以及发布等流程上还是存在些许差异的首先,会议室App不需要上架到应用市场,用户主要是公司内部员工,所以少了权限上的限制与掣肘其次,因为App不需要做市场投放,也少了安装包大小上的顾忌,所以背景图奢侈的使用了一个循环播放的十几MB的视频。

单一的设备没有了多屏幕适配的烦恼,炫酷的的交互动画实现起来更加得心应手当然除了单一设备,稳定性能,无需上架等等带来的开发方面的便捷,因为项目使用场景的特殊性,开发方面的难题也是不少的,比如为了防止误操作导致App退出,需要会议室App一直保持前台运行,无法退出至后台;下班后,大屏也需要定时休息减少功耗以实现节能减排等等。

随着App上线后版本的不断迭代,我们又发现了新的问题整个办公楼有近百个会议室,每次新版本发布,IT同学要楼上楼下一台一台的手动下载,安装更新App,这是一个重复且繁重的工作那么,是否能通过技术手段实现自动安装并打开,以降低App更新维护的成本呢?答案是肯定的。

本文将介绍会议室App在更新迭代上,是如何实现完全自动化的方案调研需求的目标是很明确的,那么接下来就是方案调研方案一:热更新App的热更新是插件化开发技术中的一种应用形式其核心原理是利用了DexClassLoader类可以加载动态下发的dex文件,以实现代码文件的覆盖替换,用以功能更新或bug修复。

但这里有个弊端是热更新需要下次启动才能生效,还有就是插件化的开发方式,项目的迭代维护和发布成本较高方案二:寻求设备供应商支持我们也向平板设备供应商寻求过技术支持,对方给出的解决方案是通过root平板设备,并给会议室App做签名加入到系统白名单里。

这样App可以自动安装,也可以开机自启动但这与我们的诉求还是有一点差距,我们希望安装完能自己启动,但是供应商能做到开机自启动,所以整条路径就变成了下载-安装-关机-开机-打开App虽然关机开机操作也可以通过供应商提供的底层Api来实现,但整个技术方案成本高,链条长,稳定性堪忧。

方案三:通过无障碍服务实现自动化点击回到我们的需求,一步步拆解执行路径首先第一步下载是可以自动完成的,下载完成后启动安装程序也是没有问题的,如果能自动点击一下安装程序界面的“安装”按钮,安装完成后再自动点击下“打开”按钮,问题就解决了。

而这种自动化点击的场景在设备开启无障碍服务的情况下是可以实现的具体实现经过方案的对比和分析,我们决定采用无障碍技术来实现自动安装和打开App的需求那么接下来,我们将重点介绍一下手机系统的无障碍服务以及如何使用它来实现自动化操作。

现实生活中随处可见的盲道,无障碍坡道电梯等,目的是为了保障残疾人、老年人以及其他行动不便者能安全、方便地通行,体现的是对于社会少数群体的关怀和尊重而我们的手机系统里也有这种无障碍设施和功能,它的设计初衷同样也是为了照顾到部分视力听力受损、有认知障碍或无法完成精细动作的残障人士,使他们也能够和其他正常人一样,无障碍地使用手机应用来完成日常的沟通、学习和工作。

除此以外,无障碍功能还可以弥补应用在某些使用场景上的限制,比如在开车的同时使用导航类的应用,有了无障碍功能的辅助,我们就可以使用语音指令而非手势触控来操控应用了当然无障碍功能也被用在了诸如:微信QQ自动抢红包,自动跳过各大应用的开屏启动广告,某些购物平台自动抢票等等。

理论上毫不夸张地说:只要你手动能操作完成的动作,无障碍服务均可实现自动化刚刚过去的农历新年,不知道大家在各微信群里的抢红包大战中战绩如何早年间有很多抢红包外挂,有时候不一定是你的网络差或者手速慢,而是跟你一起抢红包的是各种外挂,但现在这类外挂几乎都被封禁了。

那么这些外挂是如何实现的呢?这类程序打开的时候,服务就不停的在后台运行,不停地轮询着微信里面的消息,当发现红包时就立即打开微信红包所在的界面但是它怎么识别红包呢?Android应用所采用的界面布局,是基于View和ViewGroup对象,以树状结构来进行构建的视图层级。

Android系统也是基于此视图层级结构编写的无障碍事件,这里有一个AccessibilityService的服务,它是一个辅助类,通过它可以找到微信抢红包里面节点的view,当找到对应的view,在获取view的关键字或者id,根据关键字或者id,自动的模拟点击,拆开红包。

回到我们的主题,借鉴抢红包外挂的实现思路。当设备开启无障碍服务,检查到有新安装包下载后并启动安装,这个时候只要能够识别界面上的安装按钮,并模拟点击即可。

具体实现如下:创建无障碍服务首先我们要做的,就是创建一个扩展自AccessibilityService的类publicclassAutoInstallServiceextendsAccessibilityService。

{ } 由于无障碍服务本质上就是一个服务(Service),因此必须在AndroidManife应用清单文件中包含特定的声明在service元素的声明中,我们还必须添加一个intent过滤器,告诉系统这是一个无障碍服务。

此外,我们还需要添加 BIND_ACCESSIBILITY_SERVICE 权限,以确保只有系统才可以绑定到它

android:enabled="true"android:exported="true"android:label="会议室"android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"

android:process=":install">

/>

/>配置无障碍服务配置的目的是为了告诉系统,我们的无障碍服务运行的方式和时机、响应的事件类型、是针对特定的应用还是所有的应用以及采用的反馈类型等配置的方式有代码形式和XML文件形式两种,这里我们主要介绍后者。

首先,我们需要在res/xml目录下创建一个名为serviceconfig(命名可随意)的XML文件

xmlns:android="http://schemas.android.com/apk/res/android"android:accessibilityEventTypes="typeAllMask"

android:description="@string/app_accessibility_description"android:settingsActivity="cn.com.codeteenager.accessibilityapp.MainActivity"

android:accessibilityFeedbackType="feedbackGeneric"android:accessibilityFlags="flagDefault"android:canRetrieveWindowContent

="true"android:notificationTimeout="100"android:packageNames="com.android.packageinstaller,com.google.android.packageinstaller,com.samsung.android.packageinstaller,com.lenovo.safecenter,com.lenovo.security,com.xiaomi.gamecenter"

/>申请无障碍权限只有当系统绑定到我们定义的无障碍服务,我们的服务才能正常运行起来,为此,我们需要跳转到系统的无障碍设置界面,开启我们的无障碍服务自动安装具体实现除了常规的Service类方法外,无障碍服务还额外提供了2个必须重载的方法,分别是:。

onAccessibilityEvent():当系统检测到与我们前面的配置选项相匹配的事件时,就会回调此方法,事件将以AccessibilityEvent类对象的形式提供随后我们就可以解析该对象,并执行相应的处理。

这个方法可能会在服务的整个生命周期内被调用多次onInterrupt():当系统要中断我们的服务正在提供的反馈时(通常是在控件焦点转移时),就会回调此方法第一步,我们要做的事情就是,在接收到无障碍事件后,使用getSource()从事件中检索出AccessibilityNodeInfo对象, 通过AccessibilityNodeInfo对象,我们可以浏览当前界面的视图层级结构,找到包含“安装”或者“更新”字样文本的事件来源节点。

第二步就很简单了,直接调用performAction(ACTION_CLICK)执行点击操作即可/** * 事件监听回调 * @param event */ @Override publicvoid。

onAccessibilityEvent(AccessibilityEvent event) { if (!event.getPackageName().toString().contains(

"packageinstaller")) return; if (event.getSource() != null) { if (INSTALL.equals(

event.getPackageName().toString())) { for (String s : key) { AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();

if (nodeInfo != null) { List nodes = nodeInfo.findAccessibilityNodeInfosByText(s);

if (!nodes.isEmpty()) { AccessibilityNodeInfo node; for

(int j = 0; j < nodes.size(); j++) { node = nodes.get(j);

if (node.getClassName().equals("android.widget.Button") && node.isEnabled()) { node.performAction(AccessibilityNodeInfo.ACTION_CLICK);

break; } } } } } } } }

完成上面的步骤,我们已经完成了自动下载安装,但是还少了一步,安装完后还希望App能够自动打开开始的想法也是通过无障碍去查找“打开”按钮,然后模拟点击重新打开App但实际测下来,App在安装过程中已经被强制关闭了,所以上述代码已经终止,在执行完“安装”后已经没有机会再去执行“打开”。

问题似乎又陷入了死结,如果非要沿着当前的方案继续走下去也不是没有办法可以再开一个守护App,这个App是一个服务一直在后台默默运行,当它检测到会议室App不在前台运行了就发一个Intent,把会议室App再重新拉起来。

但这个方案的弊端就是要装两个App,维护成本比较高转念一想,会议室App里不是已经注册了一个AutoInstallService服务了吗,它是否能够担此重任呢测试过程中发现当安装新版本的时候AutoInstallService伴随着App一起被杀掉了,但因为AutoInstallService继承自AccessibilityService,注册了无障碍服务,所以在死掉后又立马被系统唤醒。

问题就变得简单了,只要在Service被唤醒的地方,重新打开App即可

自此App下载,安装,打开一气呵成设置好检查更新的时间,就可以在指定的时间(下班后)完成静默更新了,将来再更新迭代,就不需要IT同学去扫楼一台一台的输入链接,下载,安装,极大的降低了会议室屏幕的维护成本。

虽然本次我们巧妙的利用无障碍服务完成了App的自动化安装迭代工作但使用无障碍服务进行自动化操作可能会影响用户体验,甚至还有隐私泄露风险,所以在日常的手机使用过程中,请确认申请该权限的应用是可信赖的,建议大家谨慎开启。

作者介绍Star,移动研发专家作者:Star 来源:微信公众号:拍码场出处:https://mp.weixin.qq.com/s/gZTfJxObkAY-FZbculRxYQ

免责声明:本站所有信息均搜集自互联网,并不代表本站观点,本站不对其真实合法性负责。如有信息侵犯了您的权益,请告知,本站将立刻处理。联系QQ:1640731186