android - AccessibilityService 如何利用其他应用程序?

标签 android accessibilityservice system-alert-window

背景
SAW(系统警报窗口)权限可用于在其他应用程序之上绘制内容。
很久以前有人告诉我,无障碍服务也可以做到这一点,但我从未找到任何教程、示例、文档甚至是应用程序……直到最近:
https://play.google.com/store/apps/details?id=com.github.ericytsang.screenfilter.app.android
事实上,这个应用程序似乎可以在任何地方绘制,而不是 SAW 许可。它甚至在设置应用程序和系统对话框的顶部绘制,而不允许 SAW 权限。
问题
可悲的是,由于可访问性是一种非常独特且很少使用的东西,正如我所写的那样,我找不到这样的东西如何在其他应用程序之上绘图。
我发现了什么
我唯一知道的是这个应用程序以某种方式做到了,这就是它要求授予它时显示的内容:
enter image description here
但这还不够。我知道对于我使用无障碍服务所做的一些旧 POC,它显示相同,并且检查它,我看不出是什么触发了它。可以肯定的是,对于任何类型的可访问性服务,用户都会看到最少的东西,所以这无济于事。
问题

  • AccessibilityService 如何利用其他应用程序?
  • 它与 SAW 许可的工作方式相同吗?例如,你能处理它绘制的触摸事件吗?
  • 使用它有什么限制,如果有的话?
  • 最佳答案

    使用 TYPE_ACCESSIBILITY_OVERLAYtypeWindowManager.LayoutParams从辅助功能服务中添加 View 似乎可以解决问题。我做了一个快速测试,甚至在设置菜单中也显示了覆盖窗口。覆盖窗口也接收到触摸事件。这在没有 SYSTEM_ALERT_WINDOW 的情况下也有效 list 中的权限,也无需用户以交互方式设置“显示在其他应用程序上”权限。我使用目标 SDK 29 进行了测试。
    抱歉,我无法回答您关于适用哪些具体限制的第三个问题。

    编辑:通过查看 Google 的旧教程 here ,这是一个简短的示例:
    GlobalActionBarService.java

    public class GlobalActionBarService extends AccessibilityService {
        FrameLayout mLayout;
    
        @Override
        protected void onServiceConnected() {
            // Create an overlay and display the action bar
            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            mLayout = new FrameLayout(this);
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
            lp.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
            lp.format = PixelFormat.TRANSLUCENT;
            lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
            lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
            lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
            lp.gravity = Gravity.TOP;
            LayoutInflater inflater = LayoutInflater.from(this);
            inflater.inflate(R.layout.action_bar, mLayout);
            wm.addView(mLayout, lp);
        }
    
        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {
        }
    
        @Override
        public void onInterrupt() {
        }
    }
    
    list
    <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
        package="com.lb.myapplication">
    
        <application
            android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true"
            android:theme="@style/Theme.MyApplication" tools:ignore="AllowBackup">
            <activity
                android:name=".MainActivity" android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
            <service
                android:name=".GlobalActionBarService" android:exported="false"
                android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
                <intent-filter>
                    <action android:name="android.accessibilityservice.AccessibilityService" />
                </intent-filter>
                <meta-data
                    android:name="android.accessibilityservice" android:resource="@xml/global_action_bar_service" />
            </service>
        </application>
    
    </manifest>
    
    global_action_bar_service.xml
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault"
        android:canPerformGestures="true" android:canRetrieveWindowContent="true" />
    
    action_bar.xml
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
        android:layout_height="wrap_content" android:orientation="horizontal">
    
        <Button
            android:id="@+id/power" android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:text="@string/power" />
    
        <Button
            android:id="@+id/volume_up" android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:text="@string/volume" />
    
        <Button
            android:id="@+id/scroll" android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:text="@string/scroll" />
    
        <Button
            android:id="@+id/swipe" android:layout_width="wrap_content" android:layout_height="wrap_content"
            android:text="@string/swipe" />
    </LinearLayout>
    

    关于android - AccessibilityService 如何利用其他应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67063026/

    相关文章:

    android - 在Android中使用辅助服务获取 Activity 的布局名称

    java - 如何读取窗口内容(使用accessibilityService)并在Android中使用draw over other app权限唤起UI?

    java - 我可以在没有 root 的情况下使用辅助功能 API 在我自己的应用程序之外触发触摸事件吗?

    android - 如何检测 Facebook Messenger 何时打开气泡?

    java - 如何使用 appium 自动化/测试 Android 混合应用程序?

    Android - 集成 ffmpeg 和 android-ndk-r9c

    android - Horizo​​ntalScrollView与Recyclerview滑动android冲突

    android - native 应用程序登录