add sublime text plugin support
This commit is contained in:
@@ -6,18 +6,12 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.stardust.enhancedfloaty.FloatyService;
|
||||
import com.stardust.enhancedfloaty.FloatyWindow;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.autojs.api.VolatileBox;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/9.
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.external.floating_window.FloatingWindowManger;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.view.FloatingLayoutBoundsView;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.view.FloatingLayoutHierarchyView;
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
|
||||
import com.stardust.theme.ThemeColorManagerCompat;
|
||||
import com.stardust.util.MessageEvent;
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.HoverMenuService;
|
||||
import com.stardust.scriptdroid.layout_inspector.LayoutInspector;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.LayoutInspector;
|
||||
import com.stardust.util.ClipboardUtil;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
import com.stardust.util.MessageEvent;
|
||||
|
||||
@@ -15,17 +15,15 @@ import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.accessibility.AccessibilityEventHelper;
|
||||
import com.stardust.scriptdroid.autojs.AutoJs;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.HoverMenuService;
|
||||
import com.stardust.scriptdroid.record.Recorder;
|
||||
import com.stardust.scriptdroid.record.accessibility.AccessibilityActionRecorder;
|
||||
import com.stardust.scriptdroid.record.inputevent.InputEventConverter;
|
||||
import com.stardust.scriptdroid.record.inputevent.KeyObserver;
|
||||
import com.stardust.scriptdroid.record.inputevent.TouchRecorder;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.record.Recorder;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.record.accessibility.AccessibilityActionRecorder;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.record.inputevent.KeyObserver;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.record.inputevent.TouchRecorder;
|
||||
import com.stardust.scriptdroid.ui.main.MainActivity;
|
||||
import com.stardust.util.MessageEvent;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import io.mattcarroll.hover.Navigator;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.layout_inspector;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
|
||||
import com.stardust.util.UnderuseExecutors;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*
|
||||
*/
|
||||
|
||||
// TODO: 2017/5/8
|
||||
|
||||
public class LayoutInspector {
|
||||
|
||||
private volatile NodeInfo mCapture;
|
||||
private volatile boolean mDumping = false;
|
||||
private Executor mExecutor = UnderuseExecutors.getExecutor();
|
||||
|
||||
public void captureCurrentWindow() {
|
||||
AccessibilityService service = AccessibilityWatchDogService.getInstance();
|
||||
if (service == null) {
|
||||
mCapture = null;
|
||||
} else {
|
||||
final AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
if (root == null) {
|
||||
mCapture = null;
|
||||
} else {
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDumping = true;
|
||||
mCapture = NodeInfo.capture(root);
|
||||
mDumping = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDumping() {
|
||||
return mDumping;
|
||||
}
|
||||
|
||||
public void clearCapture() {
|
||||
mCapture = null;
|
||||
}
|
||||
|
||||
public NodeInfo getCapture() {
|
||||
return mCapture;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.layout_inspector;
|
||||
|
||||
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<>();
|
||||
|
||||
public String id;
|
||||
public CharSequence contentDesc, className, packageName, text;
|
||||
public int drawingOrder;
|
||||
public boolean accessibilityFocused, checked, clickable, contextClickable, dismissable, editable, enabled,
|
||||
focusable, longClickable, selected, scrollable, visibleToUser;
|
||||
public String bounds;
|
||||
|
||||
private Rect mBoundsInScreen;
|
||||
|
||||
public NodeInfo(AccessibilityNodeInfoCompat node) {
|
||||
id = simplifyId(node.getViewIdResourceName());
|
||||
contentDesc = 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();
|
||||
visibleToUser = node.isVisibleToUser();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public List<NodeInfo> getChildren() {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
import com.stardust.util.ViewUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class LayoutBoundsView extends View {
|
||||
|
||||
private NodeInfo mRootNode;
|
||||
|
||||
|
||||
private Paint mPaint;
|
||||
private int mStatusBarHeight;
|
||||
private OnNodeInfoSelectListener mOnNodeInfoSelectListener;
|
||||
|
||||
public LayoutBoundsView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public LayoutBoundsView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public LayoutBoundsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public LayoutBoundsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
public void setOnNodeInfoSelectListener(OnNodeInfoSelectListener onNodeInfoSelectListener) {
|
||||
mOnNodeInfoSelectListener = onNodeInfoSelectListener;
|
||||
}
|
||||
|
||||
public void setRootNode(NodeInfo rootNode) {
|
||||
mRootNode = rootNode;
|
||||
}
|
||||
|
||||
|
||||
private void init() {
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(Color.GREEN);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mStatusBarHeight = ViewUtil.getStatusBarHeight(getContext());
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
draw(canvas, mRootNode);
|
||||
}
|
||||
|
||||
public Paint getPaint() {
|
||||
return mPaint;
|
||||
}
|
||||
|
||||
|
||||
private void draw(Canvas canvas, NodeInfo node) {
|
||||
if (node == null)
|
||||
return;
|
||||
drawRect(canvas, node.getBoundsInScreen(), mStatusBarHeight, mPaint);
|
||||
for (NodeInfo child : node.getChildren()) {
|
||||
draw(canvas, child);
|
||||
}
|
||||
}
|
||||
|
||||
static void drawRect(Canvas canvas, Rect rect, int statusBarHeight, Paint paint) {
|
||||
Rect offsetRect = new Rect(rect);
|
||||
offsetRect.offset(0, -statusBarHeight);
|
||||
canvas.drawRect(offsetRect, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN && mRootNode != null) {
|
||||
ArrayList<NodeInfo> list = new ArrayList<>();
|
||||
findNodeAt(mRootNode, (int) event.getRawX(), (int) event.getRawY(), list);
|
||||
showNodeInfoList(list);
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
|
||||
}
|
||||
|
||||
private void showNodeInfoList(ArrayList<NodeInfo> list) {
|
||||
onNodeInfoClick(list.get(list.size() - 1));
|
||||
}
|
||||
|
||||
private void onNodeInfoClick(NodeInfo nodeInfo) {
|
||||
if (mOnNodeInfoSelectListener != null) {
|
||||
mOnNodeInfoSelectListener.onNodeSelect(nodeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private void findNodeAt(NodeInfo node, int x, int y, List<NodeInfo> list) {
|
||||
for (NodeInfo child : node.getChildren()) {
|
||||
if (child != null && child.getBoundsInScreen().contains(x, y)) {
|
||||
list.add(child);
|
||||
findNodeAt(child, x, y, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
import com.stardust.util.ViewUtil;
|
||||
import com.stardust.widget.LevelBeamView;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import pl.openrnd.multilevellistview.ItemInfo;
|
||||
import pl.openrnd.multilevellistview.MultiLevelListAdapter;
|
||||
import pl.openrnd.multilevellistview.MultiLevelListView;
|
||||
import pl.openrnd.multilevellistview.NestType;
|
||||
import pl.openrnd.multilevellistview.OnItemClickListener;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class LayoutHierarchyView extends MultiLevelListView {
|
||||
|
||||
private Adapter mAdapter;
|
||||
private OnNodeInfoSelectListener mOnNodeInfoSelectListener;
|
||||
private AdapterView.OnItemLongClickListener mOnItemLongClickListenerProxy = new AdapterView.OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (mOnNodeInfoSelectListener != null) {
|
||||
mOnNodeInfoSelectListener.onNodeSelect(((ViewHolder) view.getTag()).nodeInfo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private Paint mPaint;
|
||||
private int mStatusBarHeight;
|
||||
private NodeInfo mClickedNodeInfo;
|
||||
private View mClickedView;
|
||||
private Drawable mOriginalBackground;
|
||||
|
||||
private boolean mShowClickedNodeBounds;
|
||||
private int mClickedColor = 0x77c4c4c4;
|
||||
|
||||
public LayoutHierarchyView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public LayoutHierarchyView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public LayoutHierarchyView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public void setShowClickedNodeBounds(boolean showClickedNodeBounds) {
|
||||
mShowClickedNodeBounds = showClickedNodeBounds;
|
||||
}
|
||||
|
||||
public void setClickedColor(int clickedColor) {
|
||||
mClickedColor = clickedColor;
|
||||
}
|
||||
|
||||
|
||||
private void init() {
|
||||
mAdapter = new Adapter();
|
||||
setAdapter(mAdapter);
|
||||
setNestType(NestType.MULTIPLE);
|
||||
((ListView) getChildAt(0)).setOnItemLongClickListener(mOnItemLongClickListenerProxy);
|
||||
setWillNotDraw(false);
|
||||
initPaint();
|
||||
setOnItemClickListener(new OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClicked(MultiLevelListView parent, View view, Object item, ItemInfo itemInfo) {
|
||||
setClickedItem(view, (NodeInfo) item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGroupItemClicked(MultiLevelListView parent, View view, Object item, ItemInfo itemInfo) {
|
||||
setClickedItem(view, (NodeInfo) item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setClickedItem(View view, NodeInfo item) {
|
||||
mClickedNodeInfo = item;
|
||||
if (mClickedView == null) {
|
||||
mOriginalBackground = view.getBackground();
|
||||
} else {
|
||||
mClickedView.setBackground(mOriginalBackground);
|
||||
}
|
||||
view.setBackgroundColor(mClickedColor);
|
||||
mClickedView = view;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void initPaint() {
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(Color.DKGRAY);
|
||||
mPaint.setStyle(Paint.Style.STROKE);
|
||||
mPaint.setAntiAlias(true);
|
||||
mPaint.setStrokeWidth(3);
|
||||
mStatusBarHeight = ViewUtil.getStatusBarHeight(getContext());
|
||||
}
|
||||
|
||||
public Paint getBoundsPaint() {
|
||||
return mPaint;
|
||||
}
|
||||
|
||||
public void setRootNode(NodeInfo rootNodeInfo) {
|
||||
mAdapter.setDataItems(Collections.singletonList(rootNodeInfo));
|
||||
mClickedNodeInfo = null;
|
||||
}
|
||||
|
||||
public void setOnNodeInfoLongClickListener(final OnNodeInfoSelectListener onNodeInfoSelectListener) {
|
||||
mOnNodeInfoSelectListener = onNodeInfoSelectListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (mShowClickedNodeBounds && mClickedNodeInfo != null) {
|
||||
LayoutBoundsView.drawRect(canvas, mClickedNodeInfo.getBoundsInScreen(), mStatusBarHeight, mPaint);
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewHolder {
|
||||
TextView nameView;
|
||||
TextView infoView;
|
||||
ImageView arrowView;
|
||||
LevelBeamView levelBeamView;
|
||||
NodeInfo nodeInfo;
|
||||
|
||||
ViewHolder(View view) {
|
||||
infoView = (TextView) view.findViewById(R.id.dataItemInfo);
|
||||
nameView = (TextView) view.findViewById(R.id.dataItemName);
|
||||
arrowView = (ImageView) view.findViewById(R.id.dataItemArrow);
|
||||
levelBeamView = (LevelBeamView) view.findViewById(R.id.dataItemLevelBeam);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class Adapter extends MultiLevelListAdapter {
|
||||
|
||||
|
||||
@Override
|
||||
public List<?> getSubObjects(Object object) {
|
||||
return ((NodeInfo) object).getChildren();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpandable(Object object) {
|
||||
return !((NodeInfo) object).getChildren().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getViewForObject(Object object, View convertView, ItemInfo itemInfo) {
|
||||
NodeInfo nodeInfo = (NodeInfo) object;
|
||||
ViewHolder viewHolder;
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(getContext()).inflate(R.layout.layout_hierarchy_view_item, LayoutHierarchyView.this, false);
|
||||
viewHolder = new ViewHolder(convertView);
|
||||
convertView.setTag(viewHolder);
|
||||
} else {
|
||||
viewHolder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
viewHolder.nameView.setText(simplifyClassName(nodeInfo.className));
|
||||
viewHolder.nodeInfo = nodeInfo;
|
||||
if (viewHolder.infoView.getVisibility() == VISIBLE)
|
||||
viewHolder.infoView.setText(getItemInfoDsc(itemInfo));
|
||||
|
||||
if (itemInfo.isExpandable() && !isAlwaysExpanded()) {
|
||||
viewHolder.arrowView.setVisibility(View.VISIBLE);
|
||||
viewHolder.arrowView.setImageResource(itemInfo.isExpanded() ?
|
||||
R.drawable.arrow_up : R.drawable.arrow_down);
|
||||
} else {
|
||||
viewHolder.arrowView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
viewHolder.levelBeamView.setLevel(itemInfo.getLevel());
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private String simplifyClassName(CharSequence className) {
|
||||
if (className == null)
|
||||
return null;
|
||||
String s = className.toString();
|
||||
if (s.startsWith("android.widget.")) {
|
||||
s = s.substring(15);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
private String getItemInfoDsc(ItemInfo itemInfo) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(String.format(Locale.getDefault(), "level[%d], idx in level[%d/%d]",
|
||||
itemInfo.getLevel() + 1, /*Indexing starts from 0*/
|
||||
itemInfo.getIdxInLevel() + 1 /*Indexing starts from 0*/,
|
||||
itemInfo.getLevelSize()));
|
||||
|
||||
if (itemInfo.isExpandable()) {
|
||||
builder.append(String.format(", expanded[%b]", itemInfo.isExpanded()));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.annotation.StyleRes;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ViewSwitcher;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class LayoutInspectView extends FrameLayout {
|
||||
|
||||
private ViewSwitcher mViewSwitcher;
|
||||
private NodeInfoView mNodeInfoView;
|
||||
private LayoutHierarchyView mLayoutBoundsView;
|
||||
private View mCurrentView;
|
||||
|
||||
public LayoutInspectView(@NonNull Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public LayoutInspectView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public LayoutInspectView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public LayoutInspectView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
inflate(getContext(), R.layout.floating_window_expand, this);
|
||||
mNodeInfoView = (NodeInfoView) findViewById(R.id.node_info);
|
||||
mLayoutBoundsView = (LayoutHierarchyView) findViewById(R.id.bounds_view);
|
||||
mViewSwitcher = (ViewSwitcher) findViewById(R.id.view_switcher);
|
||||
mCurrentView = mNodeInfoView;
|
||||
mLayoutBoundsView.setOnNodeInfoLongClickListener(new OnNodeInfoSelectListener() {
|
||||
@Override
|
||||
public void onNodeSelect(NodeInfo info) {
|
||||
mNodeInfoView.setNodeInfo(info);
|
||||
showNodeInfoView();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showNodeInfoView() {
|
||||
if (mCurrentView != mNodeInfoView) {
|
||||
mViewSwitcher.showPrevious();
|
||||
mCurrentView = mNodeInfoView;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLayoutBoundsViewShowing() {
|
||||
return mCurrentView == mLayoutBoundsView;
|
||||
}
|
||||
|
||||
public boolean isNodeInfoViewShowing() {
|
||||
return mCurrentView == mNodeInfoView;
|
||||
}
|
||||
|
||||
public void backToLayoutBoundsView() {
|
||||
if (mCurrentView != mLayoutBoundsView) {
|
||||
mViewSwitcher.showNext();
|
||||
mCurrentView = mLayoutBoundsView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
import com.stardust.util.ClipboardUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import de.codecrafters.tableview.TableDataAdapter;
|
||||
import de.codecrafters.tableview.TableView;
|
||||
import de.codecrafters.tableview.model.TableColumnWeightModel;
|
||||
import de.codecrafters.tableview.toolkit.SimpleTableDataAdapter;
|
||||
import de.codecrafters.tableview.toolkit.TableDataRowBackgroundProviders;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public class NodeInfoView extends TableView {
|
||||
|
||||
private static final Field[] fields = NodeInfo.class.getFields();
|
||||
private String[][] mData = new String[fields.length][2];
|
||||
|
||||
public NodeInfoView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public NodeInfoView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public NodeInfoView(Context context, @Nullable AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public void setNodeInfo(NodeInfo nodeInfo) {
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
try {
|
||||
Object value = fields[i].get(nodeInfo);
|
||||
mData[i][1] = value == null ? "null" : value.toString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
getDataAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
initData();
|
||||
setUpTableConfig();
|
||||
setAdapter();
|
||||
setUpStyle();
|
||||
}
|
||||
|
||||
private void setAdapter() {
|
||||
setDataAdapter(new TableDataAdapter<String[]>(getContext(), mData) {
|
||||
SimpleTableDataAdapter mSimpleTableDataAdapter = new SimpleTableDataAdapter(getContext(), mData);
|
||||
|
||||
@Override
|
||||
public View getCellView(int rowIndex, int columnIndex, ViewGroup parentView) {
|
||||
final TextView textView = (TextView) mSimpleTableDataAdapter.getCellView(rowIndex, columnIndex, parentView);
|
||||
textView.setSingleLine(false);
|
||||
textView.setMaxLines(3);
|
||||
textView.setTextColor(0xcc000000);
|
||||
textView.setTextIsSelectable(true);
|
||||
textView.setOnLongClickListener(new OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
ClipboardUtil.setClip(getContext(), textView.getText());
|
||||
Toast.makeText(getContext(), R.string.text_already_copy_to_clip, Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
return textView;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setUpTableConfig() {
|
||||
setColumnCount(2);
|
||||
setColumnModel(new TableColumnWeightModel(2));
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
for (int i = 0; i < mData.length; i++) {
|
||||
mData[i][0] = fields[i].getName();
|
||||
mData[i][1] = "";
|
||||
}
|
||||
}
|
||||
|
||||
private void setUpStyle() {
|
||||
int colorEvenRows = Color.WHITE;
|
||||
int colorOddRows = 0xffe7e7e7;
|
||||
setDataRowBackgroundProvider(TableDataRowBackgroundProviders.alternatingRowColors(colorEvenRows, colorOddRows));
|
||||
getChildAt(0).setVisibility(GONE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view;
|
||||
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/10.
|
||||
*/
|
||||
|
||||
public interface OnNodeInfoSelectListener {
|
||||
void onNodeSelect(NodeInfo info);
|
||||
|
||||
}
|
||||
175
app/src/main/java/com/stardust/scriptdroid/external/floating_window/menu/record/Recorder.java
vendored
Normal file
175
app/src/main/java/com/stardust/scriptdroid/external/floating_window/menu/record/Recorder.java
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/16.
|
||||
*/
|
||||
|
||||
public interface Recorder {
|
||||
|
||||
interface OnStateChangedListener {
|
||||
|
||||
void onStart();
|
||||
|
||||
void onStop();
|
||||
|
||||
void onPause();
|
||||
|
||||
void onResume();
|
||||
|
||||
}
|
||||
|
||||
class StateChangeEvent {
|
||||
|
||||
private int mOldState;
|
||||
private int mCurrentState;
|
||||
|
||||
public StateChangeEvent(int oldState, int currentState) {
|
||||
mOldState = oldState;
|
||||
mCurrentState = currentState;
|
||||
}
|
||||
|
||||
public int getOldState() {
|
||||
return mOldState;
|
||||
}
|
||||
|
||||
public int getCurrentState() {
|
||||
return mCurrentState;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int STATE_NOT_START = 0;
|
||||
int STATE_RECORDING = 1;
|
||||
int STATE_PAUSED = 2;
|
||||
int STATE_STOPPED = 3;
|
||||
|
||||
void start();
|
||||
|
||||
void stop();
|
||||
|
||||
void pause();
|
||||
|
||||
void resume();
|
||||
|
||||
String getCode();
|
||||
|
||||
int getState();
|
||||
|
||||
void setOnStateChangedListener(OnStateChangedListener onStateChangedListener);
|
||||
|
||||
abstract class AbstractRecorder implements Recorder {
|
||||
|
||||
private static final OnStateChangedListener NO_OPERATION_LISTENER = new OnStateChangedListener() {
|
||||
@Override
|
||||
public void onStart() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private OnStateChangedListener mOnStateChangedListener = NO_OPERATION_LISTENER;
|
||||
|
||||
private final boolean mSync;
|
||||
private int mState = STATE_NOT_START;
|
||||
|
||||
public AbstractRecorder(boolean syncOfState) {
|
||||
mSync = syncOfState;
|
||||
}
|
||||
|
||||
public AbstractRecorder() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public void start() {
|
||||
ensureIsStateOf(STATE_NOT_START);
|
||||
setState(STATE_RECORDING);
|
||||
startImpl();
|
||||
mOnStateChangedListener.onStart();
|
||||
}
|
||||
|
||||
|
||||
private void ensureIsStateOf(int... expectedStates) {
|
||||
for (int expectedState : expectedStates) {
|
||||
if (mState == expectedState)
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("expected=" + Arrays.toString(expectedStates) + " state=" + mState);
|
||||
}
|
||||
|
||||
|
||||
protected abstract void startImpl();
|
||||
|
||||
public void stop() {
|
||||
ensureIsStateOf(STATE_RECORDING, STATE_PAUSED);
|
||||
setState(STATE_STOPPED);
|
||||
stopImpl();
|
||||
mOnStateChangedListener.onStop();
|
||||
}
|
||||
|
||||
protected abstract void stopImpl();
|
||||
|
||||
public void pause() {
|
||||
ensureIsStateOf(STATE_RECORDING);
|
||||
setState(STATE_PAUSED);
|
||||
pauseImpl();
|
||||
mOnStateChangedListener.onPause();
|
||||
}
|
||||
|
||||
protected synchronized void setState(int state) {
|
||||
if (mSync) {
|
||||
synchronized (this) {
|
||||
mState = state;
|
||||
}
|
||||
} else {
|
||||
mState = state;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int getState() {
|
||||
if (mSync) {
|
||||
synchronized (this) {
|
||||
return mState;
|
||||
}
|
||||
} else {
|
||||
return mState;
|
||||
}
|
||||
}
|
||||
|
||||
protected void pauseImpl() {
|
||||
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
ensureIsStateOf(STATE_PAUSED);
|
||||
setState(STATE_RECORDING);
|
||||
resumeImpl();
|
||||
mOnStateChangedListener.onResume();
|
||||
}
|
||||
|
||||
protected void resumeImpl() {
|
||||
|
||||
}
|
||||
|
||||
public void setOnStateChangedListener(OnStateChangedListener onStateChangedListener) {
|
||||
mOnStateChangedListener = onStateChangedListener == null ? NO_OPERATION_LISTENER : onStateChangedListener;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.os.Build;
|
||||
import android.util.SparseArray;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.automator.UiObject;
|
||||
import com.stardust.automator.simple_action.FilterAction;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
import com.stardust.util.SparseArrayEntries;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoHelper;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class AccessibilityActionConverter {
|
||||
|
||||
private static final SparseArray<EventToScriptConverter> CONVERTER_MAP = new SparseArrayEntries<EventToScriptConverter>()
|
||||
.entry(AccessibilityEvent.TYPE_VIEW_CLICKED, new DoUtilSucceedConverter("click"))
|
||||
.entry(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED, new DoUtilSucceedConverter("longClick"))
|
||||
.entry(AccessibilityEvent.TYPE_VIEW_SCROLLED, new DoOnceConverter("//scroll???"))
|
||||
.entry(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED, new SetTextEventConverter())
|
||||
.sparseArray();
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
CONVERTER_MAP.put(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED, new DoOnceConverter("contextClick"));
|
||||
}
|
||||
}
|
||||
|
||||
private StringBuilder mScript = new StringBuilder();
|
||||
private boolean mFirstAction = true;
|
||||
|
||||
public AccessibilityActionConverter(boolean shouldIgnoreFirstAction) {
|
||||
mShouldIgnoreFirstAction = shouldIgnoreFirstAction;
|
||||
}
|
||||
|
||||
private boolean mShouldIgnoreFirstAction = false;
|
||||
|
||||
public void record(AccessibilityService service, AccessibilityEvent event) {
|
||||
EventToScriptConverter converter = CONVERTER_MAP.get(event.getEventType());
|
||||
if (converter != null) {
|
||||
if (mFirstAction && mShouldIgnoreFirstAction) {
|
||||
mFirstAction = false;
|
||||
return;
|
||||
}
|
||||
converter.onAccessibilityEvent(service, event, mScript);
|
||||
mScript.append("\n");
|
||||
EventBus.getDefault().post(new AccessibilityActionRecorder.AccessibilityActionRecordEvent(event));
|
||||
}
|
||||
}
|
||||
|
||||
public String getScript() {
|
||||
return mScript.toString();
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
mFirstAction = true;
|
||||
}
|
||||
|
||||
interface EventToScriptConverter {
|
||||
|
||||
void onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event, StringBuilder sb);
|
||||
}
|
||||
|
||||
private static abstract class BoundsEventConverter implements EventToScriptConverter {
|
||||
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event, StringBuilder sb) {
|
||||
AccessibilityNodeInfo source = event.getSource();
|
||||
if (source == null)
|
||||
return;
|
||||
String bounds = NodeInfo.boundsToString(AccessibilityNodeInfoHelper.getBoundsInScreen(source));
|
||||
source.recycle();
|
||||
onAccessibilityEvent(event, bounds, sb);
|
||||
}
|
||||
|
||||
protected abstract void onAccessibilityEvent(AccessibilityEvent event, String bounds, StringBuilder sb);
|
||||
|
||||
}
|
||||
|
||||
private static class DoOnceConverter extends BoundsEventConverter {
|
||||
|
||||
private String mActionFunction;
|
||||
|
||||
DoOnceConverter(String actionFunction) {
|
||||
mActionFunction = actionFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAccessibilityEvent(AccessibilityEvent event, String bounds, StringBuilder sb) {
|
||||
sb.append(mActionFunction).append(bounds).append(";");
|
||||
}
|
||||
}
|
||||
|
||||
private static class DoUtilSucceedConverter extends BoundsEventConverter {
|
||||
|
||||
private String mActionFunction;
|
||||
|
||||
DoUtilSucceedConverter(String actionFunction) {
|
||||
mActionFunction = actionFunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAccessibilityEvent(AccessibilityEvent event, String bounds, StringBuilder sb) {
|
||||
sb.append("while(!").append(mActionFunction).append(bounds).append(");");
|
||||
}
|
||||
}
|
||||
|
||||
private static class SetTextEventConverter implements EventToScriptConverter {
|
||||
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event, StringBuilder sb) {
|
||||
AccessibilityNodeInfo source = event.getSource();
|
||||
if (source == null)
|
||||
return;
|
||||
UiObject uiObject = UiObject.createRoot(service.getRootInActiveWindow());
|
||||
List<UiObject> editableList = FilterAction.EditableFilter.findEditable(uiObject);
|
||||
int i = findInEditableList(editableList, source);
|
||||
sb.append("while(!input(").append(i).append(", \"").append(source.getText()).append("\"));");
|
||||
source.recycle();
|
||||
}
|
||||
|
||||
private static int findInEditableList(List<UiObject> editableList, AccessibilityNodeInfo editable) {
|
||||
int i = 0;
|
||||
for (UiObject nodeInfo : editableList) {
|
||||
if (AccessibilityNodeInfoHelper.getBoundsInScreen(nodeInfo).equals(AccessibilityNodeInfoHelper.getBoundsInScreen(editable))) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.accessibility;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.record.Recorder;
|
||||
import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class AccessibilityActionRecorder extends Recorder.AbstractRecorder implements AccessibilityDelegate {
|
||||
|
||||
public static class AccessibilityActionRecordEvent {
|
||||
|
||||
private final AccessibilityEvent mAccessibilityEvent;
|
||||
|
||||
public AccessibilityActionRecordEvent(AccessibilityEvent event) {
|
||||
mAccessibilityEvent = event;
|
||||
}
|
||||
|
||||
public AccessibilityEvent getAccessibilityEvent() {
|
||||
return mAccessibilityEvent;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Set<Integer> EVENT_TYPES = new HashSet<>(Arrays.asList(AccessibilityEvent.TYPE_VIEW_CLICKED, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED, AccessibilityEvent.TYPE_VIEW_SCROLLED, AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED));
|
||||
|
||||
private static final long RECORD_TIME_OUT = 10 * 60 * 1000;
|
||||
|
||||
private boolean mShouldIgnoreFirstAction = false;
|
||||
|
||||
|
||||
private AccessibilityActionConverter mConverter;
|
||||
private long mRecordStartMillis;
|
||||
|
||||
public AccessibilityActionRecorder() {
|
||||
super(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startImpl() {
|
||||
mConverter = new AccessibilityActionConverter(mShouldIgnoreFirstAction);
|
||||
mRecordStartMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopImpl() {
|
||||
setState(STATE_NOT_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resumeImpl() {
|
||||
mConverter.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
|
||||
if (getState() == STATE_RECORDING) {
|
||||
mConverter.record(service, event);
|
||||
checkTimeOut();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> getEventTypes() {
|
||||
return EVENT_TYPES;
|
||||
}
|
||||
|
||||
private void checkTimeOut() {
|
||||
if (System.currentTimeMillis() - mRecordStartMillis > RECORD_TIME_OUT) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return mConverter.getScript();
|
||||
}
|
||||
|
||||
public void setShouldIgnoreFirstAction(boolean shouldIgnoreFirstAction) {
|
||||
mShouldIgnoreFirstAction = shouldIgnoreFirstAction;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/7.
|
||||
*/
|
||||
|
||||
public class EventFormatException extends RuntimeException {
|
||||
|
||||
|
||||
public static EventFormatException forEventStr(String eventStr, NumberFormatException e) {
|
||||
return new EventFormatException(eventStr, e);
|
||||
}
|
||||
|
||||
public EventFormatException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public EventFormatException(String eventStr, Exception e) {
|
||||
super("eventStr=" + eventStr, e);
|
||||
}
|
||||
|
||||
public EventFormatException(String eventStr) {
|
||||
super("eventStr=" + eventStr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.flurry.android.FlurryAgent;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.record.Recorder;
|
||||
import com.stardust.util.MapEntries;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/7.
|
||||
*/
|
||||
|
||||
public abstract class InputEventConverter {
|
||||
|
||||
static class Event {
|
||||
|
||||
static final Pattern PATTERN = Pattern.compile("^\\[([^\\]]*)\\]\\s+([^:]*):\\s+([^\\s]*)\\s+([^\\s]*)\\s+([^\\s]*)\\s*$");
|
||||
|
||||
static Event parseEvent(String eventStr) {
|
||||
Matcher matcher = Event.PATTERN.matcher(eventStr);
|
||||
if (!matcher.matches()) {
|
||||
throw new EventFormatException(eventStr);
|
||||
}
|
||||
double time;
|
||||
try {
|
||||
time = Double.parseDouble(matcher.group(1));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new EventFormatException(eventStr, e);
|
||||
}
|
||||
return new Event(time, matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5));
|
||||
}
|
||||
|
||||
|
||||
double time;
|
||||
String device;
|
||||
String type;
|
||||
String code;
|
||||
String value;
|
||||
|
||||
public Event(double time, String device, String type, String code, String value) {
|
||||
this.time = time;
|
||||
this.device = device;
|
||||
this.type = type;
|
||||
this.code = code;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Event{" +
|
||||
"time=" + time +
|
||||
", device='" + device + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", code='" + code + '\'' +
|
||||
", value='" + value + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean mConverting = false;
|
||||
private int mState = Recorder.STATE_NOT_START;
|
||||
|
||||
public void convertEventIfFormatCorrect(String eventStr) {
|
||||
if (!mConverting)
|
||||
return;
|
||||
if (TextUtils.isEmpty(eventStr) || !eventStr.startsWith("["))
|
||||
return;
|
||||
Event event = parseEventOrNull(eventStr);
|
||||
if (event != null) {
|
||||
convertEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void convertEvent(@NonNull Event event);
|
||||
|
||||
public String getGetEventCommand() {
|
||||
return "getevent -t -l";
|
||||
}
|
||||
|
||||
|
||||
public void start() {
|
||||
mConverting = true;
|
||||
mState = Recorder.STATE_RECORDING;
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
mConverting = true;
|
||||
mState = Recorder.STATE_RECORDING;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
mConverting = false;
|
||||
mState = Recorder.STATE_PAUSED;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
mConverting = false;
|
||||
mState = Recorder.STATE_STOPPED;
|
||||
}
|
||||
|
||||
public abstract String getCode();
|
||||
|
||||
private boolean mFirstEventFormatError = true;
|
||||
|
||||
public Event parseEventOrNull(String eventStr) {
|
||||
try {
|
||||
return Event.parseEvent(eventStr);
|
||||
} catch (EventFormatException e) {
|
||||
e.printStackTrace();
|
||||
if (mFirstEventFormatError) {
|
||||
Toast.makeText(App.getApp(), R.string.text_record_format_error, Toast.LENGTH_SHORT).show();
|
||||
mFirstEventFormatError = false;
|
||||
FlurryAgent.logEvent("EventFormatException", new MapEntries<String, String>()
|
||||
.entry("message", e.getMessage())
|
||||
.map());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
import com.stardust.scriptdroid.autojs.api.Shell;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.record.Recorder;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/6.
|
||||
*/
|
||||
|
||||
public class InputEventRecorder extends Recorder.AbstractRecorder {
|
||||
|
||||
private static final String TAG = "InputEventRecorder";
|
||||
private String mGetEventCommand;
|
||||
private Shell mShell;
|
||||
protected InputEventConverter mInputEventConverter;
|
||||
|
||||
|
||||
protected InputEventRecorder(InputEventConverter inputEventConverter) {
|
||||
mGetEventCommand = inputEventConverter.getGetEventCommand();
|
||||
mInputEventConverter = inputEventConverter;
|
||||
}
|
||||
|
||||
public void listen() {
|
||||
mShell = new Shell(true);
|
||||
mShell.setCallback(new Shell.SimpleCallback() {
|
||||
@Override
|
||||
public void onNewLine(String str) {
|
||||
if (mShell.isInitialized()) {
|
||||
convertEvent(str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialized() {
|
||||
mShell.exec(mGetEventCommand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupted(InterruptedException e) {
|
||||
stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startImpl() {
|
||||
mInputEventConverter.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void pauseImpl() {
|
||||
mInputEventConverter.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resumeImpl() {
|
||||
mInputEventConverter.resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopImpl() {
|
||||
mShell.exit();
|
||||
mInputEventConverter.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return mInputEventConverter.getCode();
|
||||
}
|
||||
|
||||
protected void convertEvent(String eventStr) {
|
||||
mInputEventConverter.convertEventIfFormatCorrect(eventStr);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.stardust.util.MapEntries;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/7.
|
||||
*/
|
||||
|
||||
public class InputEventToJsConverter extends InputEventConverter {
|
||||
|
||||
interface EventHandler {
|
||||
void handle(Event event);
|
||||
}
|
||||
|
||||
abstract static class Router implements EventHandler {
|
||||
|
||||
private Map<String, EventHandler> mEventHandlerMap = new HashMap<>();
|
||||
|
||||
Router put(String key, EventHandler handler) {
|
||||
mEventHandlerMap.put(key, handler);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Event event) {
|
||||
EventHandler handler = mEventHandlerMap.get(getKey(event));
|
||||
if (handler != null) {
|
||||
handler.handle(event);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getKey(Event event);
|
||||
}
|
||||
|
||||
private class TypeRouter extends Router {
|
||||
|
||||
TypeRouter() {
|
||||
put("EV_ABS", new AbsHandler());
|
||||
put("EV_SYN", new SyncHandler());
|
||||
put("EV_KEY", new KeyHandler());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getKey(Event event) {
|
||||
return event.type;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Point {
|
||||
int x, y;
|
||||
}
|
||||
|
||||
private class AbsHandler implements EventHandler {
|
||||
|
||||
@Override
|
||||
public void handle(Event event) {
|
||||
if (event.code.equals("ABS_MT_POSITION_X")) {
|
||||
mTouchPoint.x = Integer.parseInt(event.value, 16);
|
||||
mTouchTime = event.time;
|
||||
} else if (event.code.equals("ABS_MT_POSITION_Y")) {
|
||||
mTouchPoint.y = Integer.parseInt(event.value, 16);
|
||||
mTouchTime = event.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SyncHandler implements EventHandler {
|
||||
|
||||
@Override
|
||||
public void handle(Event event) {
|
||||
if (mTouchDown) {
|
||||
if (mSwipe) {
|
||||
appendCodeIfNotStopped(event);
|
||||
mSwipe = false;
|
||||
} else {
|
||||
mLastTouchPoint.x = mTouchPoint.x;
|
||||
mLastTouchPoint.y = mTouchPoint.y;
|
||||
mSwipe = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendCodeIfNotStopped(Event event) {
|
||||
if (!mConverting)
|
||||
return;
|
||||
long interval = (long) (1000 * (event.time - mTouchTime));
|
||||
mCode.append("sh.Swipe(")
|
||||
.append(mLastTouchPoint.x).append(", ").append(mLastTouchPoint.y).append(", ")
|
||||
.append(mTouchPoint.x).append(", ").append(mTouchPoint.y);
|
||||
if (interval >= 1) {
|
||||
mCode.append(", ").append(interval);
|
||||
}
|
||||
mCode.append(");\n");
|
||||
}
|
||||
}
|
||||
|
||||
private class KeyHandler implements EventHandler {
|
||||
|
||||
private Map<String, String> mKeyPressCodeMap = new MapEntries<>(new HashMap<String, String>())
|
||||
.entry("KEY_HOME", "Home")
|
||||
.entry("KEY_MENU", "Menu")
|
||||
.entry("KEY_VOLUMEDOWN", "VolumeDown")
|
||||
.entry("KEY_VOLUMEUP", "VolumeUp")
|
||||
.entry("KEY_BACK", "Back")
|
||||
.entry("KEY_CAMERA", "Camera")
|
||||
.map();
|
||||
|
||||
@Override
|
||||
public void handle(Event event) {
|
||||
if (event.code.equals("BTN_TOUCH")) {
|
||||
mTouchDown = event.value.equals("DOWN");
|
||||
if (!mTouchDown && mSwipe) {
|
||||
if (mConverting)
|
||||
mCode.append("sh.Tap(").append(mLastTouchPoint.x).append(", ").append(mLastTouchPoint.y).append(");\n");
|
||||
mSwipe = false;
|
||||
}
|
||||
} else if (event.value.equals("UP")) {
|
||||
appendKeyPressCode(event);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendKeyPressCode(Event event) {
|
||||
String code = mKeyPressCodeMap.get(event.code);
|
||||
if (code != null) {
|
||||
mCode.append("sh.").append(code).append("();\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EventHandler mEventHandler = new TypeRouter();
|
||||
private StringBuilder mCode = new StringBuilder().append("var sh = new Shell(true);\n");
|
||||
private Point mTouchPoint = new Point(), mLastTouchPoint = new Point();
|
||||
private boolean mTouchDown = false, mSwipe = false;
|
||||
private double mTouchTime;
|
||||
|
||||
|
||||
@Override
|
||||
public void convertEvent(@NonNull Event event) {
|
||||
mEventHandler.handle(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
mCode.append("sh.exitAndWaitFor();");
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return mCode.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/7.
|
||||
*/
|
||||
|
||||
public class InputEventToSendEventConverter extends InputEventConverter {
|
||||
|
||||
private static final DecimalFormat DELAY_FORMAT = new DecimalFormat("#.###");
|
||||
|
||||
private double mLastEventTime;
|
||||
private StringBuilder mSendEventCommands = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void convertEvent(@NonNull Event event) {
|
||||
if (mLastEventTime == 0) {
|
||||
mLastEventTime = event.time;
|
||||
} else if (event.time - mLastEventTime > 0.1) {
|
||||
mSendEventCommands.append("sleep ").append(DELAY_FORMAT.format(event.time - mLastEventTime)).append("\n");
|
||||
mLastEventTime = event.time;
|
||||
}
|
||||
mSendEventCommands.append("sendevent ")
|
||||
.append(event.device).append(" ")
|
||||
.append(hex2dec(event.type)).append(" ")
|
||||
.append(hex2dec(event.code)).append(" ")
|
||||
.append(hex2dec(event.value)).append("\n");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGetEventCommand() {
|
||||
return "getevent -t";
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return mSendEventCommands.toString();
|
||||
}
|
||||
|
||||
private static String hex2dec(String hex) {
|
||||
try {
|
||||
return String.valueOf((int) Long.parseLong(hex, 16));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new EventFormatException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.stardust.util.ScreenMetrics.getScreenHeight;
|
||||
import static com.stardust.util.ScreenMetrics.getScreenWidth;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/3.
|
||||
*/
|
||||
|
||||
public class InputEventToSendEventJsConverter extends InputEventConverter {
|
||||
|
||||
private final static Pattern LAST_INT_PATTERN = Pattern.compile("[^0-9]+([0-9]+)$");
|
||||
private double mLastEventTime;
|
||||
private StringBuilder mCode = new StringBuilder();
|
||||
private int mTouchDevice = -1;
|
||||
private int mLastTouchX = -1;
|
||||
private int mLastTouchY = -1;
|
||||
|
||||
public InputEventToSendEventJsConverter() {
|
||||
mCode.append("var sh = new Shell(true);\n")
|
||||
.append("sh.SetScreenMetrics(").append(getScreenWidth()).append(", ")
|
||||
.append(getScreenHeight()).append(");\n");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void convertEvent(@NonNull Event event) {
|
||||
if (mLastEventTime == 0) {
|
||||
mLastEventTime = event.time;
|
||||
} else if (event.time - mLastEventTime > 0.03) {
|
||||
mCode.append("sleep(").append((long) (1000 * (event.time - mLastEventTime))).append(");\n");
|
||||
mLastEventTime = event.time;
|
||||
}
|
||||
int device = parseDeviceNumber(event.device);
|
||||
int type = (int) Long.parseLong(event.type, 16);
|
||||
int code = (int) Long.parseLong(event.code, 16);
|
||||
int value = (int) Long.parseLong(event.value, 16);
|
||||
if (type == 3) {
|
||||
if (code == 53) {
|
||||
onTouchX(device, value);
|
||||
return;
|
||||
}
|
||||
if (code == 54) {
|
||||
onTouchY(device, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
checkLastTouch();
|
||||
mCode.append("sh.SendEvent(");
|
||||
if (device != mTouchDevice) {
|
||||
mCode.append(device).append(", ");
|
||||
}
|
||||
mCode.append(type).append(", ")
|
||||
.append(code).append(", ")
|
||||
.append(value).append(");\n");
|
||||
}
|
||||
|
||||
private void checkLastTouch() {
|
||||
if (mLastTouchX >= 0) {
|
||||
mCode.append("sh.TouchX(").append(mLastTouchX).append(");\n");
|
||||
mLastTouchX = -1;
|
||||
}
|
||||
if (mLastTouchY >= 0) {
|
||||
mCode.append("sh.TouchY(").append(mLastTouchY).append(");\n");
|
||||
mLastTouchY = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int parseDeviceNumber(String device) {
|
||||
Matcher matcher = LAST_INT_PATTERN.matcher(device);
|
||||
if (matcher.find()) {
|
||||
String someNumberStr = matcher.group(1);
|
||||
return Integer.parseInt(someNumberStr);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void onTouchX(int device, int value) {
|
||||
if (mTouchDevice == -1) {
|
||||
setTouchDevice(device);
|
||||
}
|
||||
mLastTouchX = value;
|
||||
}
|
||||
|
||||
private void onTouchY(int device, int value) {
|
||||
if (mTouchDevice == -1) {
|
||||
setTouchDevice(device);
|
||||
}
|
||||
if (mLastTouchX >= 0) {
|
||||
mCode.append("sh.Touch(")
|
||||
.append(mLastTouchX).append(", ")
|
||||
.append(value).append(");\n");
|
||||
mLastTouchX = -1;
|
||||
} else {
|
||||
mLastTouchY = value;
|
||||
}
|
||||
}
|
||||
|
||||
private void setTouchDevice(int i) {
|
||||
mCode.append("sh.SetTouchDevice(").append(i).append(");\n");
|
||||
mTouchDevice = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGetEventCommand() {
|
||||
return "getevent -t";
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return mCode.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
mCode.append("sh.exitAndWaitFor();");
|
||||
}
|
||||
|
||||
private static String hex2dec(String hex) {
|
||||
try {
|
||||
return String.valueOf((int) Long.parseLong(hex, 16));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new EventFormatException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/4.
|
||||
*/
|
||||
|
||||
public class KeyObserver {
|
||||
|
||||
public interface KeyListener {
|
||||
|
||||
void onKeyDown(String keyName);
|
||||
|
||||
void onKeyUp(String keyName);
|
||||
|
||||
}
|
||||
|
||||
private InputEventRecorder mObserver;
|
||||
private KeyListener mKeyListener;
|
||||
|
||||
public KeyObserver(){
|
||||
mObserver = new InputEventRecorder(new InputEventConverter() {
|
||||
@Override
|
||||
public void convertEvent(@NonNull Event event) {
|
||||
if(event.value.equalsIgnoreCase("UP")){
|
||||
notifyKeyUp(event.code);
|
||||
}
|
||||
if(event.value.equalsIgnoreCase("DOWN")){
|
||||
notifyKeyDown(event.code);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCode() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setKeyListener(KeyListener keyListener) {
|
||||
mKeyListener = keyListener;
|
||||
}
|
||||
|
||||
public void startListening(){
|
||||
mObserver.listen();
|
||||
mObserver.start();
|
||||
}
|
||||
|
||||
public void stopListening(){
|
||||
mObserver.stopImpl();
|
||||
}
|
||||
|
||||
private void notifyKeyDown(String keyName) {
|
||||
if(mKeyListener != null){
|
||||
mKeyListener.onKeyDown(keyName);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyKeyUp(String keyName) {
|
||||
if(mKeyListener != null){
|
||||
mKeyListener.onKeyUp(keyName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.stardust.scriptdroid.external.floating_window.menu.record.inputevent;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/3/16.
|
||||
*/
|
||||
|
||||
public class TouchRecorder extends InputEventRecorder {
|
||||
|
||||
public TouchRecorder() {
|
||||
super(new InputEventToSendEventJsConverter());
|
||||
listen();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,10 +7,10 @@ import android.view.WindowManager;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.afollestad.materialdialogs.Theme;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.HoverMenuService;
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.layout_inspector.view.LayoutBoundsView;
|
||||
import com.stardust.scriptdroid.layout_inspector.view.NodeInfoView;
|
||||
import com.stardust.scriptdroid.layout_inspector.view.OnNodeInfoSelectListener;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view.LayoutBoundsView;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view.NodeInfoView;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view.OnNodeInfoSelectListener;
|
||||
import com.stardust.util.MessageEvent;
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,10 +7,10 @@ import android.view.WindowManager;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.afollestad.materialdialogs.Theme;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.HoverMenuService;
|
||||
import com.stardust.scriptdroid.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.layout_inspector.view.LayoutHierarchyView;
|
||||
import com.stardust.scriptdroid.layout_inspector.view.NodeInfoView;
|
||||
import com.stardust.scriptdroid.layout_inspector.view.OnNodeInfoSelectListener;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.NodeInfo;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view.LayoutHierarchyView;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view.NodeInfoView;
|
||||
import com.stardust.scriptdroid.external.floating_window.menu.layout_inspector.view.OnNodeInfoSelectListener;
|
||||
import com.stardust.util.MessageEvent;
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,8 +40,4 @@ public class ImportIntentActivity extends BaseActivity {
|
||||
finish();
|
||||
}
|
||||
|
||||
private void startMainActivity() {
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,11 @@ public class RunIntentActivity extends Activity {
|
||||
source = new StringScriptSource(script);
|
||||
} else if (path != null && new PathChecker(this).checkAndToastError(path)) {
|
||||
ScriptSource fileScriptSource = new FileScriptSource(path);
|
||||
source = new SequenceScriptSource(fileScriptSource.getName(), new StringScriptSource(script), fileScriptSource);
|
||||
if (script != null) {
|
||||
source = new SequenceScriptSource(fileScriptSource.getName(), new StringScriptSource(script), fileScriptSource);
|
||||
} else {
|
||||
source = fileScriptSource;
|
||||
}
|
||||
directoryPath = new File(path).getParent();
|
||||
}
|
||||
if (source != null) {
|
||||
|
||||
Reference in New Issue
Block a user