random click and gesture for android 7.0+!!!

This commit is contained in:
hyb1996
2017-05-16 21:40:23 +08:00
parent ec98d75d3b
commit c4ec951a10
42 changed files with 757 additions and 564 deletions

View File

@@ -0,0 +1,175 @@
package com.stardust.automator;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.content.Context;
import android.graphics.Path;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.RequiresApi;
import android.view.ViewConfiguration;
import com.stardust.concurrent.VolatileBox;
import com.stardust.util.ScreenMetrics;
/**
* Created by Stardust on 2017/5/16.
*/
public class GlobalActionAutomator {
private AccessibilityService mService;
private ScreenMetrics mScreenMetrics;
public void setService(AccessibilityService service) {
mService = service;
}
public void setScreenMetrics(ScreenMetrics screenMetrics) {
mScreenMetrics = screenMetrics;
}
public boolean back() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
}
public boolean home() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public boolean powerDialog() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG);
}
private boolean performGlobalAction(int globalAction) {
if (mService == null)
return false;
return mService.performGlobalAction(globalAction);
}
public boolean notifications() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS);
}
public boolean quickSettings() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS);
}
public boolean recents() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_RECENTS);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public boolean splitScreen() {
return performGlobalAction(AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public boolean gesture(long start, long duration, int[]... points) {
Path path = pointsToPath(points);
return gestures(new GestureDescription.StrokeDescription(path, start, duration));
}
private Path pointsToPath(int[][] points) {
Path path = new Path();
path.moveTo(scaleX(points[0][0]), scaleY(points[0][1]));
for (int i = 1; i < points.length; i++) {
int[] point = points[i];
path.lineTo(scaleX(point[0]), scaleY(point[1]));
}
return path;
}
@RequiresApi(api = Build.VERSION_CODES.N)
public void gestureAsync(long start, long duration, int[]... points) {
Path path = pointsToPath(points);
gesturesAsync(new GestureDescription.StrokeDescription(path, start, duration));
}
@RequiresApi(api = Build.VERSION_CODES.N)
public boolean gestures(GestureDescription.StrokeDescription... strokes) {
if (mService == null)
return false;
GestureDescription.Builder builder = new GestureDescription.Builder();
for (GestureDescription.StrokeDescription stroke : strokes) {
builder.addStroke(stroke);
}
prepareLooperIfNeeded();
final VolatileBox<Boolean> result = new VolatileBox<>(false);
Handler handler = new Handler(Looper.myLooper());
mService.dispatchGesture(builder.build(), new AccessibilityService.GestureResultCallback() {
@Override
public void onCompleted(GestureDescription gestureDescription) {
result.set(true);
quitLoop();
}
@Override
public void onCancelled(GestureDescription gestureDescription) {
result.set(false);
quitLoop();
}
}, handler);
Looper.loop();
return result.get();
}
@RequiresApi(api = Build.VERSION_CODES.N)
public void gesturesAsync(GestureDescription.StrokeDescription... strokes) {
if (mService == null)
return;
GestureDescription.Builder builder = new GestureDescription.Builder();
for (GestureDescription.StrokeDescription stroke : strokes) {
builder.addStroke(stroke);
}
mService.dispatchGesture(builder.build(), null, null);
}
private void quitLoop() {
Looper looper = Looper.myLooper();
if (looper != null) {
looper.quitSafely();
}
}
private void prepareLooperIfNeeded() {
if (Looper.myLooper() == null) {
Looper.prepare();
}
}
@RequiresApi(api = Build.VERSION_CODES.N)
public boolean click(int x, int y) {
return press(x, y, ViewConfiguration.getTapTimeout() + 50);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public boolean press(int x, int y, int delay) {
return gesture(0, delay, new int[]{x, y});
}
@RequiresApi(api = Build.VERSION_CODES.N)
public boolean longClick(int x, int y) {
return gesture(0, ViewConfiguration.getLongPressTimeout() + 200, new int[]{x, y});
}
private int scaleX(int x) {
if (mScreenMetrics == null)
return x;
return mScreenMetrics.scaleX(x);
}
private int scaleY(int y) {
if (mScreenMetrics == null)
return y;
return mScreenMetrics.scaleY(y);
}
@RequiresApi(api = Build.VERSION_CODES.N)
public boolean swipe(int x1, int y1, int x2, int y2, int delay) {
return gesture(0, delay, new int[]{x1, y1}, new int[]{x2, y2});
}
}

View File

@@ -14,6 +14,8 @@ import java.util.Set;
public interface AccessibilityDelegate {
Set<Integer> ALL_EVENT_TYPES = null;
boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event);
/**

View File

@@ -30,41 +30,40 @@ public class AccessibilityInfoProvider implements AccessibilityDelegate {
mPackageManager = packageManager;
}
public synchronized String getLatestPackage() {
public String getLatestPackage() {
return mLatestPackage;
}
public synchronized String getLatestActivity() {
public String getLatestActivity() {
return mLatestActivity;
}
@Override
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
AccessibilityNodeInfo root = service.getRootInActiveWindow();
if (root != null)
setLatestComponent(root.getPackageName(), event.getClassName());
else
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
setLatestComponent(event.getPackageName(), event.getClassName());
}
return false;
}
@Override
public Set<Integer> getEventTypes() {
return null;
return ALL_EVENT_TYPES;
}
private synchronized void setLatestComponent(CharSequence latestPackage, CharSequence latestClass) {
if (latestPackage == null)
private void setLatestComponent(CharSequence latestPackage, CharSequence latestClass) {
if (latestPackage == null || latestClass == null)
return;
mLatestPackage = latestPackage.toString();
if (latestClass == null)
String latestPackageStr = latestPackage.toString();
String latestClassStr = latestClass.toString();
if (latestClassStr.startsWith("android.view.") || latestClassStr.startsWith("android.widget."))
return;
try {
ComponentName componentName = new ComponentName(latestPackage.toString(), latestClass.toString());
ActivityInfo activityInfo = mPackageManager.getActivityInfo(componentName, 0);
mLatestActivity = activityInfo.name;
ComponentName componentName = new ComponentName(latestPackageStr, latestClassStr);
mLatestActivity = mPackageManager.getActivityInfo(componentName, 0).name;
} catch (PackageManager.NameNotFoundException ignored) {
return;
}
mLatestPackage = latestPackage.toString();
}
}

View File

@@ -2,13 +2,23 @@ package com.stardust.view.accessibility;
import android.view.accessibility.AccessibilityNodeInfo;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Created by Stardust on 2017/5/2.
*/
public abstract class AccessibilityService extends android.accessibilityservice.AccessibilityService {
public interface NotificationCallback {
void onNotification();
}
private CopyOnWriteArrayList<NotificationCallback> mNotificationCallbacks = new CopyOnWriteArrayList<>();
@Override
public AccessibilityNodeInfo getRootInActiveWindow() {
try {
return super.getRootInActiveWindow();
@@ -16,4 +26,5 @@ public abstract class AccessibilityService extends android.accessibilityservice.
return null;
}
}
}