[英]How does AccessibilityService draw on top of other apps?
SAW (system alert window) permission can be used to draw content on top of other apps. SAW(系统警报窗口)权限可用于在其他应用程序之上绘制内容。
I was told a very long time ago that accessibility service can do this too, but I never found any tutorial, sample, documentation and even an app that does it... until recently:很久以前有人告诉我无障碍服务也可以做到这一点,但我从来没有找到任何教程、示例、文档甚至是可以做到这一点的应用程序......直到最近:
https://play.google.com/store/apps/details?id=com.github.ericytsang.screenfilter.app.android https://play.google.com/store/apps/details?id=com.github.ericytsang.screenfilter.app.android
In fact, this app seems to be able to draw everywhere, as opposed to SAW permission.事实上,这个应用程序似乎可以在任何地方绘制,而不是 SAW 许可。 It draws even on top of the settings app and system dialogs, while SAW permission isn't allowed as such.
它甚至在设置应用程序和系统对话框的顶部绘制,而不允许 SAW 权限。
Sadly, as accessibility is quite a unique and rarely thing to use, just as I wrote, I couldn't find how such a thing works with drawing on top of other apps.可悲的是,由于可访问性是一种非常独特且很少使用的东西,就像我写的那样,我找不到这样的东西如何在其他应用程序之上绘图。
The only thing I know is that this app somehow does it, and this is what it shows when it asks to grant it:我唯一知道的是这个应用程序以某种方式做到了,这就是它要求授予它时显示的内容:
But that's not enough.但这还不够。 I know that for some old POC I've made of using accessibility service, it showed the same, and checking it out, I can't see what triggers it.
我知道对于我使用无障碍服务所做的一些旧 POC,它显示相同,并且检查它,我看不出是什么触发了它。 Pretty sure it's the minimal thing the users will see for any kind of accessibility service, so this won't help.
可以肯定的是,对于任何类型的可访问性服务,用户都会看到最少的东西,所以这无济于事。
How does AccessibilityService draw on top of other apps? AccessibilityService 如何利用其他应用程序?
Does it work the same as SAW permission?它与 SAW 许可的工作方式相同吗? Can you, for example, handle touch events on what it draws?
例如,你能处理它绘制的触摸事件吗?
What are the restrictions of using it, if there are any?使用它有什么限制,如果有的话?
Using TYPE_ACCESSIBILITY_OVERLAY as type
in the WindowManager.LayoutParams
when adding the view from within the accessibility service seems to do the trick.从辅助功能服务中添加视图时,使用TYPE_ACCESSIBILITY_OVERLAY作为
WindowManager.LayoutParams
中的type
似乎可以解决问题。 I did a quick test and the overlay window was shown even in the settings menu.我做了一个快速测试,甚至在设置菜单中也显示了覆盖 window。 The overlay window also received touch events.
叠加层 window 也接收到触摸事件。 This worked also without the
SYSTEM_ALERT_WINDOW
permission in the manifest and also without setting the "Display over other apps" permission interactively by the user.这在清单中没有
SYSTEM_ALERT_WINDOW
权限的情况下也有效,也没有用户以交互方式设置“在其他应用程序上显示”权限。 I did my testing using target SDK 29.我使用目标 SDK 29 进行了测试。
Sorry, I cannot answer to your third question about what specific restrictions apply.抱歉,我无法回答您关于适用哪些具体限制的第三个问题。
EDIT: By looking at the old tutorial of Google here , here's a short sample:编辑:通过查看 Google here的旧教程,这里有一个简短的示例:
GlobalActionBarService.java 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() {
}
}
manifest显现
<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 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 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>
The answer is: You must use WindowManager which puts views to a window in the service to draw it on top of other apps.答案是:您必须使用 WindowManager 将视图放入服务中的 window 以将其绘制在其他应用程序之上。
val typeApplication =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
else
WindowManager.LayoutParams.TYPE_PHONE
val layoutParams = WindowManager.LayoutParams(
windowWidth,
ViewGroup.LayoutParams.WRAP_CONTENT,
typeApplication,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
)
// inflater view with above layoutParams variable
And the application granted the Overlay permission and make sure accessibility is enabled in the device setting (Setting-> Accessibility -> Enable your app).并且应用程序授予了覆盖权限并确保在设备设置中启用了可访问性(设置-> 辅助功能-> 启用您的应用程序)。 Or use this intent to go to it
或者使用这个意图来 go 到它
Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
. . You can check the Overlay permission by the following code
您可以通过以下代码检查 Overlay 权限
// check
Settings.canDrawOverlays(applicationContext)
// Use this intent to enable permision
Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:$packageName"))
Does it work the same as SAW permission?它与 SAW 许可的工作方式相同吗? Can you, for example, handle touch events on what it draws?
例如,你能处理它绘制的触摸事件吗? I've never used SAW before so I'm not sure about this question.
我以前从未使用过 SAW,所以我不确定这个问题。
Hope can help you!希望能帮到你!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.