无障碍模拟点击
-
创建无障碍服务MyAccessibilityService
public class MyAccessibilityService extends AccessibilityService { private EventObserver<SimulateClickBean> observer = new EventObserver<SimulateClickBean>() { @Override public void onObserver(SimulateClickBean clickBean) { simulateClick(clickBean.getX(), clickBean.getY()); } }; @Override protected void onServiceConnected() { super.onServiceConnected(); LtEventBus.with(EventKey.KEY_EVENT_SIMULATE_CLICK, SimulateClickBean.class) .observer(observer); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { LogUtils.d(TAG, " onAccessibilityEvent " + stringBuilder.toString()); } @Override public void onInterrupt() { // handle interrupt } }
-
AndroidManifest.xml中声明服务
<service android:name=".service.MyAccessibilityService" android:exported="true" android:label="模拟点击" 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/accessibility_config" /> </service>
- accessibility_config.xml文件
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeAllMask" android:accessibilityFeedbackType="feedbackGeneric" android:canPerformGestures="true" android:canRetrieveWindowContent="true" android:notificationTimeout="100" />
- 无障碍服务模拟屏幕点击
-
public void simulateClick(int x, int y) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { LogUtils.d(TAG, "simulateClick ", "X: " + x, "Y: " + y); Path path = new Path(); path.moveTo(x, y); path.lineTo(x, y); GestureDescription.Builder builder = new GestureDescription.Builder(); builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 100)); dispatchGesture(builder.build(), null, null); } }
- 打开无障碍服务设置
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS); startActivity(intent);
系统悬浮窗
- 申请悬浮窗权限
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + activity.getPackageName())); activity.startActivityForResult(intent, REQUEST_CODE);
private boolean canDrawOverlays(Context context) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(context)) { return false; } return true; }
- 添加悬浮窗到windows
private void addViewToWindow(Context context, View contentView, int x, int y) { WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { params.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; } else { params.type = WindowManager.LayoutParams.TYPE_PHONE; } params.x = x; params.y = y; params.alpha = 0.5F; params.dimAmount = 0.3f; params.gravity = Gravity.START | Gravity.TOP; WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); windowManager.addView(contentView, params); addStatusMap.put(String.valueOf(contentView.getId()), true); }
private void remove(Context context, View view) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if (view != null && addStatusMap.containsKey(String.valueOf(view.getId()))) { windowManager.removeView(view); addStatusMap.remove(String.valueOf(view.getId())); } }
- 更新悬浮窗位置
private void updateViewLayoutParam(Context context, View view, WindowManager.LayoutParams layoutParams) { if (System.currentTimeMillis() - updateInterval < 10) { return; } updateInterval = System.currentTimeMillis(); WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); windowManager.updateViewLayout(view, layoutParams); }
mOverlayViewBinding.getRootView().setOnTouchListener(new View.OnTouchListener() { int downX, downY; int moveX, moveY; @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: downX = (int) motionEvent.getX(); downY = (int) motionEvent.getY(); LogUtils.d(TAG, "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: moveX = (int) motionEvent.getX(); moveY = (int) motionEvent.getY(); WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) mOverlayViewBinding.getRootView().getLayoutParams(); layoutParams.x = layoutParams.x + (int) (0.8F * (moveX - downX)); layoutParams.y = layoutParams.y + (int) (0.8F * (moveY - downY)); layoutParams.gravity = Gravity.START | Gravity.TOP; updateViewLayoutParam(view.getContext(), mOverlayViewBinding.getRootView(), layoutParams); downX = moveX; downY = moveY; break; case MotionEvent.ACTION_UP: LogUtils.d(TAG, "ACTION_UP"); break; } return true; } });