add events module, including EventEmiiter, KeyEvent, TouchEvent

This commit is contained in:
hyb1996
2017-07-20 15:39:17 +08:00
parent 1d23640362
commit 52cc5214f1
47 changed files with 755 additions and 82 deletions

View File

@@ -1,5 +1,7 @@
package com.stardust.automator.simple_action;
import android.graphics.BitmapFactory;
import com.stardust.automator.UiObject;
import java.util.List;

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}