无需SYSTEM_ALERT_WINDOW权限,如何在系统UI(如SAF对话框)上方显示引导浮层?
兄弟,我懂你想在SAF对话框上加引导又不想碰那个烦人的SYSTEM_ALERT_WINDOW权限的心情——毕竟这个权限需要用户跳去设置里开启,体验太差了。先给你说清楚为啥你之前试的方法都没用:
SAF的文件选择对话框是系统进程托管的窗口,它的窗口层级比咱们普通应用的所有窗口(包括你用的TYPE_APPLICATION、TYPE_APPLICATION_ATTACHED_DIALOG,还有透明Activity)都要高。系统为了安全,普通应用的窗口默认是不能覆盖系统级UI的,除非你用SYSTEM_ALERT_WINDOW权限对应的窗口类型(比如Android 10+的TYPE_APPLICATION_OVERLAY)。
那不用这个权限的话,有没有办法实现类似的引导效果?给你两个可行的思路:
前置引导,提前告知操作步骤
在启动SAF对话框之前,先弹出一个应用内的弹窗(比如Flutter的AlertDialog或者自定义的半透明弹窗),把要引导的内容说清楚:比如“接下来请点击左上角的返回,找到WhatsApp的Status目录...”,等用户点击“知道了”之后再启动SAF。这种方式虽然不是直接在SAF窗口上加浮层,但能达到引导用户的目的,而且完全不需要额外权限。利用AccessibilityService(需用户手动开启辅助权限)
如果一定要在SAF对话框上方显示浮层,那可以用AccessibilityService。这个服务可以监听系统UI的变化,当SAF对话框出现时,在上面绘制引导浮层。不过要注意:- AccessibilityService需要用户去系统设置里开启“无障碍权限”,这个权限的申请流程比
SYSTEM_ALERT_WINDOW稍微友好一点,但还是需要用户额外操作; - 实现的时候,你需要在Service里监听
TYPE_WINDOW_STATE_CHANGED事件,判断当前窗口是否是SAF的选择器(可以通过窗口的包名或者类名判断,SAF的类名通常是com.android.documentsui.DocumentsActivity),然后在这个窗口上添加你的引导View。
- AccessibilityService需要用户去系统设置里开启“无障碍权限”,这个权限的申请流程比
另外,你提到有些App不用SYSTEM_ALERT_WINDOW就能显示覆盖系统UI的浮层,大概率它们用的就是AccessibilityService,或者是针对旧版本Android的漏洞(但现在新版本系统已经堵上了)。
如果你还是执着于直接在SAF窗口上加浮层又不想用任何特殊权限,那抱歉,目前Android系统的安全机制下是做不到的——系统就是要防止普通应用随意覆盖系统级UI,避免恶意App欺骗用户。
内容来源于stack exchange

