add events module, including EventEmiiter, KeyEvent, TouchEvent
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
package com.stardust.automator.simple_action;
|
||||
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import com.stardust.automator.UiObject;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
package com.stardust.view.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.stardust.util.ScreenMetrics;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
@@ -22,6 +15,9 @@ import java.util.SortedMap;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -39,11 +35,14 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
||||
private static final ReentrantLock LOCK = new ReentrantLock();
|
||||
private static final Condition ENABLED = LOCK.newCondition();
|
||||
private static AccessibilityService instance;
|
||||
private static final OnKeyListener.Observer stickOnKeyObserver = new OnKeyListener.Observer();
|
||||
private static boolean containsAllEventTypes = false;
|
||||
private static final Set<Integer> eventTypes = new HashSet<>();
|
||||
private OnKeyListener.Observer mOnKeyObserver = new OnKeyListener.Observer();
|
||||
private volatile AccessibilityNodeInfo mRootInActiveWindow;
|
||||
private Timer mTimer;
|
||||
private Handler mHandler;
|
||||
private ExecutorService mKeyEventExecutor;
|
||||
|
||||
public static void addDelegate(int uniquePriority, AccessibilityDelegate delegate) {
|
||||
mDelegates.put(uniquePriority, delegate);
|
||||
@@ -85,6 +84,25 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onKeyEvent(final KeyEvent event) {
|
||||
if (mKeyEventExecutor == null) {
|
||||
mKeyEventExecutor = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
mKeyEventExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
stickOnKeyObserver.onKeyEvent(event.getKeyCode(), event);
|
||||
mOnKeyObserver.onKeyEvent(event.getKeyCode(), event);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
public OnKeyListener.Observer getOnKeyObserver() {
|
||||
return mOnKeyObserver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeInfo getRootInActiveWindow() {
|
||||
return mRootInActiveWindow;
|
||||
@@ -93,7 +111,10 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
instance = null;
|
||||
mTimer.cancel();
|
||||
if (mTimer != null)
|
||||
mTimer.cancel();
|
||||
if (mKeyEventExecutor != null)
|
||||
mKeyEventExecutor.shutdownNow();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@@ -155,5 +176,7 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static OnKeyListener.Observer getStickOnKeyObserver() {
|
||||
return stickOnKeyObserver;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.stardust.view.accessibility;
|
||||
|
||||
import android.os.Build;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.view.accessibility.AccessibilityService;
|
||||
import com.stardust.util.UnderuseExecutors;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class LayoutInspector {
|
||||
|
||||
private static final String LOG_TAG = LayoutInspector.class.getSimpleName();
|
||||
private volatile NodeInfo mCapture;
|
||||
private volatile boolean mDumping = false;
|
||||
private Executor mExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
public void captureCurrentWindow() {
|
||||
AccessibilityService service = AccessibilityService.getInstance();
|
||||
if (service == null) {
|
||||
Log.d(LOG_TAG, "captureCurrentWindow: service = null");
|
||||
mCapture = null;
|
||||
} else {
|
||||
final AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
if (root == null) {
|
||||
Log.d(LOG_TAG, "captureCurrentWindow: root = null");
|
||||
mCapture = null;
|
||||
} else {
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDumping = true;
|
||||
mCapture = NodeInfo.capture(root);
|
||||
mDumping = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
|
||||
private void refreshChildList(AccessibilityNodeInfo root) {
|
||||
if (root == null)
|
||||
return;
|
||||
root.refresh();
|
||||
int childCount = root.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
refreshChildList(root.getChild(i));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDumping() {
|
||||
return mDumping;
|
||||
}
|
||||
|
||||
public void clearCapture() {
|
||||
mCapture = null;
|
||||
}
|
||||
|
||||
public NodeInfo getCapture() {
|
||||
return mCapture;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.stardust.view.accessibility;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.Keep;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.automator.UiObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
@Keep
|
||||
public class NodeInfo {
|
||||
|
||||
private List<NodeInfo> children = new ArrayList<>();
|
||||
private Rect mBoundsInScreen;
|
||||
|
||||
public String id;
|
||||
public CharSequence desc;
|
||||
public CharSequence className;
|
||||
public CharSequence packageName;
|
||||
public CharSequence text;
|
||||
public int drawingOrder;
|
||||
public boolean accessibilityFocused;
|
||||
public boolean checked;
|
||||
public boolean clickable;
|
||||
public boolean contextClickable;
|
||||
public boolean dismissable;
|
||||
public boolean editable;
|
||||
public boolean enabled;
|
||||
public boolean focusable;
|
||||
public boolean longClickable;
|
||||
public boolean selected;
|
||||
public boolean scrollable;
|
||||
public String bounds;
|
||||
|
||||
|
||||
public NodeInfo(AccessibilityNodeInfoCompat node) {
|
||||
id = simplifyId(node.getViewIdResourceName());
|
||||
desc = node.getContentDescription();
|
||||
className = node.getClassName();
|
||||
packageName = node.getPackageName();
|
||||
text = node.getText();
|
||||
|
||||
drawingOrder = node.getDrawingOrder();
|
||||
|
||||
accessibilityFocused = node.isAccessibilityFocused();
|
||||
checked = node.isChecked();
|
||||
clickable = node.isClickable();
|
||||
contextClickable = node.isContextClickable();
|
||||
dismissable = node.isDismissable();
|
||||
enabled = node.isEnabled();
|
||||
editable = node.isEditable();
|
||||
focusable = node.isFocusable();
|
||||
longClickable = node.isLongClickable();
|
||||
selected = node.isSelected();
|
||||
scrollable = node.isScrollable();
|
||||
mBoundsInScreen = new Rect();
|
||||
node.getBoundsInScreen(mBoundsInScreen);
|
||||
bounds = boundsToString(mBoundsInScreen);
|
||||
}
|
||||
|
||||
private String simplifyId(String idResourceName) {
|
||||
if (idResourceName == null)
|
||||
return null;
|
||||
int i = idResourceName.indexOf('/');
|
||||
return idResourceName.substring(i + 1);
|
||||
}
|
||||
|
||||
public Rect getBoundsInScreen() {
|
||||
return mBoundsInScreen;
|
||||
}
|
||||
|
||||
public static String boundsToString(Rect rect) {
|
||||
return rect.toString().replace('-', ',').replace(" ", "").substring(4);
|
||||
}
|
||||
|
||||
public NodeInfo(AccessibilityNodeInfo node) {
|
||||
this(new AccessibilityNodeInfoCompat(node));
|
||||
}
|
||||
|
||||
|
||||
public static NodeInfo capture(@NonNull UiObject root) {
|
||||
NodeInfo nodeInfo = new NodeInfo(root);
|
||||
int childCount = root.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
UiObject child = root.child(i);
|
||||
if (child != null) {
|
||||
nodeInfo.children.add(capture(child));
|
||||
}
|
||||
}
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
public static NodeInfo capture(@NonNull AccessibilityNodeInfo root) {
|
||||
UiObject r = UiObject.createRoot(root);
|
||||
return capture(r);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<NodeInfo> getChildren() {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.stardust.view.accessibility;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/7/18.
|
||||
*/
|
||||
|
||||
public interface OnKeyListener {
|
||||
|
||||
void onKeyEvent(int keyCode, KeyEvent event);
|
||||
|
||||
class Observer implements OnKeyListener {
|
||||
|
||||
private static final String TAG = "OnKeyListenerObserver";
|
||||
|
||||
private CopyOnWriteArrayList<OnKeyListener> mOnKeyListeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(int keyCode, KeyEvent event) {
|
||||
for (OnKeyListener listener : mOnKeyListeners) {
|
||||
try {
|
||||
listener.onKeyEvent(keyCode, event);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error OnKeyEvent: " + event + " Listener: " + listener, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener(OnKeyListener listener) {
|
||||
mOnKeyListeners.add(listener);
|
||||
}
|
||||
|
||||
public boolean removeListener(OnKeyListener listener) {
|
||||
return mOnKeyListeners.remove(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user