From ee1f3c316bf1d03b86c6712ecf9e94f0c003edb9 Mon Sep 17 00:00:00 2001 From: jiangwei Date: Sat, 25 Jul 2020 23:54:12 +0800 Subject: [PATCH 1/8] =?UTF-8?q?feature:android=E7=88=AC=E8=99=AB=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Android/app/build.gradle | 1 + Android/app/src/main/AndroidManifest.xml | 32 ++- .../Accessibility/AbstractNode.java | 75 +++++ .../RobotHelper/Accessibility/HttpServer.java | 128 +++++++++ .../RobotHelper/Accessibility/INode.java | 14 + .../RobotHelper/Accessibility/Node.java | 264 ++++++++++++++++++ .../NodeHasBeenRemovedException.java | 11 + .../UnableToSetAttributeException.java | 15 + .../xjiangwei/RobotHelper/MainActivity.java | 54 ++-- .../RobotHelper/Service/Accessibility.java | 47 ++++ .../RobotHelper/Service/RunTime.java | 33 +++ .../cn/xjiangwei/RobotHelper/Tools/Robot.java | 17 ++ .../app/src/main/res/layout/activity_main.xml | 31 +- .../app/src/main/res/layout/notification.xml | 50 +++- .../res/xml/accessibility_service_config.xml | 6 + 15 files changed, 720 insertions(+), 58 deletions(-) create mode 100644 Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/AbstractNode.java create mode 100644 Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/HttpServer.java create mode 100644 Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/INode.java create mode 100644 Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/Node.java create mode 100644 Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/NodeHasBeenRemovedException.java create mode 100644 Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/UnableToSetAttributeException.java create mode 100644 Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/Accessibility.java create mode 100644 Android/app/src/main/res/xml/accessibility_service_config.xml diff --git a/Android/app/build.gradle b/Android/app/build.gradle index 41860d6..23884a6 100644 --- a/Android/app/build.gradle +++ b/Android/app/build.gradle @@ -35,5 +35,6 @@ dependencies { implementation 'com.lahm.library:easy-protector-release:1.1.0' implementation project(path: ':tesseract4android-2.0.0') implementation project(path: ':opencv-android341') + implementation 'com.nanohttpd:nanohttpd-webserver:2.2.0' } diff --git a/Android/app/src/main/AndroidManifest.xml b/Android/app/src/main/AndroidManifest.xml index 069f1fc..90c2dea 100644 --- a/Android/app/src/main/AndroidManifest.xml +++ b/Android/app/src/main/AndroidManifest.xml @@ -1,29 +1,40 @@ - - - + + + + android:theme="@style/AppTheme" + android:usesCleartextTraffic="true"> + + + + + + - + android:exported="false" /> @@ -33,7 +44,8 @@ - + + diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/AbstractNode.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/AbstractNode.java new file mode 100644 index 0000000..6c05184 --- /dev/null +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/AbstractNode.java @@ -0,0 +1,75 @@ +package cn.xjiangwei.RobotHelper.Accessibility; + + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import cn.xjiangwei.RobotHelper.Accessibility.exceptions.UnableToSetAttributeException; + +/** + * Created by adolli on 2017/7/19. + */ + +public abstract class AbstractNode implements INode { + // tree node interface + public AbstractNode getParent() { + return null; + } + + public abstract Iterable getChildren(); + + // node interface + public void setAttr(String attrName, Object attrVal) { + throw new UnableToSetAttributeException(String.format("%s=%s", attrName, attrVal), null, "Method not implemented."); + } + + public Object getAttr(String attrName) { + Map defaultAttrs = new HashMap<>(); + defaultAttrs.put("name", ""); + defaultAttrs.put("type", "Root"); + defaultAttrs.put("visible", true); + defaultAttrs.put("pos", new float[] {0, 0}); + defaultAttrs.put("size", new float[] {0, 0}); + defaultAttrs.put("scale", new float[] {0, 0}); + defaultAttrs.put("anchorPoint", new float[] {0.5f, 0.5f}); + Map zOrders = new HashMap<>(); + zOrders.put("global", 0); + zOrders.put("local", 0); + defaultAttrs.put("zOrders", zOrders); + + if (defaultAttrs.containsKey(attrName)) { + return defaultAttrs.get(attrName); + } else { + return null; + } + } + + public List getAvailableAttributeNames() { + List ret = new LinkedList<>(); + String[] a = new String[] { + "name", + "type", + "visible", + "pos", + "size", + "scale", + "anchorPoint", + "zOrders", + }; + for (String n : a) { + ret.add(n); + } + return ret; + } + + // method for dumper only + public Map enumerateAttrs() { + Map ret = new HashMap<>(); + for (String attrName : getAvailableAttributeNames()) { + ret.put(attrName, getAttr(attrName)); + } + return ret; + } +} diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/HttpServer.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/HttpServer.java new file mode 100644 index 0000000..63a40f7 --- /dev/null +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/HttpServer.java @@ -0,0 +1,128 @@ +package cn.xjiangwei.RobotHelper.Accessibility; + +import android.view.accessibility.AccessibilityNodeInfo; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import cn.xjiangwei.RobotHelper.MainApplication; +import cn.xjiangwei.RobotHelper.Service.Accessibility; +import cn.xjiangwei.RobotHelper.Tools.Robot; +import fi.iki.elonen.NanoHTTPD; + +public class HttpServer extends NanoHTTPD { + + + public boolean runing; + + public HttpServer() { + super("0.0.0.0", 1082); + try { + start(5000, true); + runing = true; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void stop() { + super.stop(); + runing = false; + } + + + public void start() { + try { + start(5000, true); + } catch (IOException e) { + e.printStackTrace(); + } + runing = true; + } + + @Override + public Response serve(IHTTPSession session) { + String path = session.getUri(); + Map parms = session.getParms(); + String ret = "[]"; + String mimeType = "application/json; charset=utf-8"; + switch (path) { + case "/dom": + if (Accessibility.DOM == null) { + ret = "{\"tip\":\"无障碍服务未开启!\"}"; + } else if (parms.containsKey("id")) { + ret = dumpHierarchyImpl(Accessibility.DOM.findAccessibilityNodeInfosByViewId(parms.get("id")), false).toString(); + } else { + ret = dumpHierarchyImpl(new Node(Accessibility.DOM, 1440, 3120), false).toString(); + } + break; + case "/sceenSize": + ret = "{\"w\": " + MainApplication.sceenWidth + " , \"h\":" + MainApplication.sceenHeight + " }"; + break; + case "/swipe": + Robot.swiper(700, 2000, 800, 1900); + break; + } + + + return newFixedLengthResponse(Response.Status.OK, mimeType, ret); + } + + + public JSONArray dumpHierarchyImpl(List nodes, boolean onlyVisibleNode) { + JSONArray jsonArray = new JSONArray(); + for (AccessibilityNodeInfo node : nodes) { + jsonArray.put(dumpHierarchyImpl(new Node(node, 3120, 1440), onlyVisibleNode)); + } + + return jsonArray; + } + + + public JSONObject dumpHierarchyImpl(AbstractNode node, boolean onlyVisibleNode) { + if (node == null) { + // return if still null + return null; + } + + JSONObject payload = new JSONObject(); + for (Map.Entry attr : node.enumerateAttrs().entrySet()) { + try { + payload.put(attr.getKey(), attr.getValue()); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + JSONObject result = new JSONObject(); + JSONArray children = new JSONArray(); + + for (AbstractNode child : node.getChildren()) { + if (!onlyVisibleNode || (boolean) child.getAttr("visible")) { + children.put(this.dumpHierarchyImpl(child, onlyVisibleNode)); + } + } + if (children.length() > 0) { + try { + result.put("children", children); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + try { + result.put("name", node.getAttr("name")); + result.put("payload", payload); + } catch (JSONException e) { + e.printStackTrace(); + } + + return result; + } + +} diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/INode.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/INode.java new file mode 100644 index 0000000..c4efc1c --- /dev/null +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/INode.java @@ -0,0 +1,14 @@ +package cn.xjiangwei.RobotHelper.Accessibility; + + +import cn.xjiangwei.RobotHelper.Accessibility.exceptions.NodeHasBeenRemovedException; +import cn.xjiangwei.RobotHelper.Accessibility.exceptions.UnableToSetAttributeException; + +/** + * Created by adolli on 2017/7/19. + */ + +public interface INode { + Object getAttr(String attrName) throws NodeHasBeenRemovedException; + void setAttr(String attrName, Object value) throws UnableToSetAttributeException, NodeHasBeenRemovedException; +} diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/Node.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/Node.java new file mode 100644 index 0000000..b36a1c4 --- /dev/null +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/Node.java @@ -0,0 +1,264 @@ +package cn.xjiangwei.RobotHelper.Accessibility; + +import android.annotation.SuppressLint; +import android.graphics.Rect; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.accessibility.AccessibilityNodeInfo; + + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.LinkedList; +import java.util.List; + +import cn.xjiangwei.RobotHelper.Accessibility.exceptions.NodeHasBeenRemovedException; +import cn.xjiangwei.RobotHelper.Accessibility.exceptions.UnableToSetAttributeException; + +/** + * Created by adolli on 2017/7/19. + */ + +public class Node extends AbstractNode { + + public AccessibilityNodeInfo node; + protected int screenWidth_ = 0; + protected int screenHeight_ = 0; + + public Node(AccessibilityNodeInfo node, int screenW, int screenH) { + super(); + this.node = node; + this.screenWidth_ = screenW; + this.screenHeight_ = screenH; + } + + @Override + @Nullable + public AbstractNode getParent() { + AccessibilityNodeInfo parent = this.node.getParent(); + if (parent == null) { + return null; + } + return new Node(this.node.getParent(), this.screenWidth_, this.screenHeight_); + } + + @Override + public Iterable getChildren() { + List ret = new LinkedList<>(); + int childCount = this.node.getChildCount(); + for (int i = 0; i < childCount; i++) { + ret.add(new Node(node.getChild(i), this.screenWidth_, this.screenHeight_)); + } + return ret; + } + + @Override + public void setAttr(String attrName, Object attrVal) throws UnableToSetAttributeException, NodeHasBeenRemovedException { + if (this.node == null) { + throw new NodeHasBeenRemovedException(attrName, null); + } + + switch (attrName) { + case "text": + if (!this.node.isEditable()) { + throw new UnableToSetAttributeException(attrName, this.node, "this node is not editable"); + } + Bundle args = new Bundle(); + args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, attrVal.toString()); + this.node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args); + break; + default: + throw new UnableToSetAttributeException(attrName, this.node); + } + } + + @Override + public Object getAttr(String attrName) throws NodeHasBeenRemovedException { + if (this.node == null) { + throw new NodeHasBeenRemovedException(attrName, null); + } + + Object ret = null; + switch (attrName) { + case "name": + ret = node.getViewIdResourceName(); + if (ret == null || ret.equals("")) { + ret = node.getContentDescription(); + } + if (ret == null || ret.toString().equals("")) { + ret = node.getClassName(); + } + if (ret != null) { + ret = ret.toString(); + } else { + ret = ""; + } + break; + case "type": + ret = node.getClassName().toString(); + break; + case "visible": + boolean visible = node.isVisibleToUser(); + if (!visible) { + ret = false; + } else { + ret = true; + AccessibilityNodeInfo parent = node.getParent(); + while (parent != null) { + boolean parentVisible = parent.isVisibleToUser(); + if (!parentVisible) { + ret = false; + break; + } + parent = parent.getParent(); + } + } + break; + case "pos": + Rect bound = new Rect(); + node.getBoundsInScreen(bound); + JSONArray pos = new JSONArray(); + try { + pos.put(1.0 * bound.centerX() / this.screenWidth_); + pos.put(1.0 * bound.centerY() / this.screenHeight_); + } catch (JSONException e) {} + ret = pos; + break; + case "size": + Rect bound1 = new Rect(); + node.getBoundsInScreen(bound1); + JSONArray size = new JSONArray(); + try { + size.put(1.0 * bound1.width() / this.screenWidth_); + size.put(1.0 * bound1.height() / this.screenHeight_); + } catch (JSONException e) {} + ret = size; + break; + case "boundsInParent": + Rect boundP = new Rect(); + node.getBoundsInParent(boundP); + JSONArray sizeP = new JSONArray(); + try { + sizeP.put(1.0 * boundP.width() / this.screenWidth_); + sizeP.put(1.0 * boundP.height() / this.screenHeight_); + } catch (JSONException e) {} + ret = sizeP; + break; + case "scale": + JSONArray scale = new JSONArray(); + scale.put(1); + scale.put(1); + ret = scale; + break; + case "anchorPoint": + JSONArray anchor = new JSONArray(); + try { + anchor.put(0.5); + anchor.put(0.5); + } catch (JSONException e) {} + ret = anchor; + break; + case "zOrders": + JSONObject zOrders = new JSONObject(); + int localOrder = 0; + try { + localOrder = node.getDrawingOrder(); + } catch (NoSuchMethodError e) { } + try { + zOrders.put("global", 0); + zOrders.put("local", localOrder); + } catch (JSONException e) {} + ret = zOrders; + break; + case "resourceId": + CharSequence resid = node.getViewIdResourceName(); + if (resid != null) { + ret = resid.toString(); + } + break; + case "package": + CharSequence pkgName = node.getPackageName(); + if (pkgName != null) { + ret = pkgName.toString(); + } + break; + case "desc": + CharSequence desc = node.getContentDescription(); + if (desc != null) { + ret = desc.toString(); + } + break; + case "text": + CharSequence text = node.getText(); + if (text != null) { + ret = text.toString(); + } + break; + case "enabled": + ret = node.isEnabled(); + break; + case "checkable": + ret = node.isCheckable(); + break; + case "checked": + ret = node.isChecked(); + break; + case "focusable": + ret = node.isFocusable(); + break; + case "focused": + ret = node.isFocused(); + break; + case "editalbe": + ret = node.isEditable(); + break; + case "selected": + ret = node.isSelected(); + break; + case "touchable": + ret = node.isClickable(); + break; + case "longClickable": + ret = node.isLongClickable(); + break; + case "scrollable": + ret = node.isScrollable(); + break; + case "dismissable": + ret = node.isDismissable(); + break; + default: + ret = super.getAttr(attrName); + } + return ret; + } + + public List getAvailableAttributeNames() { + List ret = super.getAvailableAttributeNames(); + String[] a = new String[] { + "resourceId", + "package", + "desc", + "text", + "enabled", + "checkable", + "checked", + "focusable", + "focused", + "editalbe", + "selected", + "touchable", + "longClickable", + "boundsInParent", + "scrollable", + "dismissable", + }; + + for (String n : a) { + ret.add(n); + } + return ret; + } +} diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/NodeHasBeenRemovedException.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/NodeHasBeenRemovedException.java new file mode 100644 index 0000000..ebd8eac --- /dev/null +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/NodeHasBeenRemovedException.java @@ -0,0 +1,11 @@ +package cn.xjiangwei.RobotHelper.Accessibility.exceptions; + +/** + * Created by adolli on 2017/7/30. + */ + +public class NodeHasBeenRemovedException extends RuntimeException { + public NodeHasBeenRemovedException(String attrName, Object node) { + super(String.format("Node was no longer alive when query attribute \"%s\". Please re-select.", attrName)); + } +} diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/UnableToSetAttributeException.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/UnableToSetAttributeException.java new file mode 100644 index 0000000..5483243 --- /dev/null +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Accessibility/exceptions/UnableToSetAttributeException.java @@ -0,0 +1,15 @@ +package cn.xjiangwei.RobotHelper.Accessibility.exceptions; + +/** + * Created by adolli on 2017/7/13. + */ + +public class UnableToSetAttributeException extends RuntimeException { + public UnableToSetAttributeException(String attrName, Object node) { + super(String.format("Unable to set attribute \"%s\" of node \"%s\"", attrName, node.toString())); + } + + public UnableToSetAttributeException(String attrName, Object node, String reason) { + super(String.format("Unable to set attribute \"%s\" of node \"%s\", because of \"%s\"", attrName, node.toString(), reason)); + } +} diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/MainActivity.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/MainActivity.java index a9404b5..24c951c 100644 --- a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/MainActivity.java +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/MainActivity.java @@ -16,6 +16,7 @@ import android.util.DisplayMetrics; import android.view.View; import android.widget.EditText; +import android.widget.TextView; import com.github.dfqin.grantor.PermissionListener; import com.github.dfqin.grantor.PermissionsUtil; @@ -36,6 +37,8 @@ import java.io.IOException; import java.io.InputStream; +import cn.xjiangwei.RobotHelper.Accessibility.HttpServer; +import cn.xjiangwei.RobotHelper.Service.Accessibility; import cn.xjiangwei.RobotHelper.Service.RunTime; import cn.xjiangwei.RobotHelper.Tools.MLog; import cn.xjiangwei.RobotHelper.Tools.Robot; @@ -51,7 +54,6 @@ public class MainActivity extends AppCompatActivity { private MainApplication mainApplication; private int mResultCode; private Intent mResultData; - private MediaProjection mMediaProjection; @@ -113,33 +115,29 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { public void start(View view) { - if (checkXposedHook()) { - if (!TessactOcr.checkInit()) { - Toast.show("初始化中,Please Wait!"); - return; - } - EditText editText = findViewById(R.id.serverUrl); - String serverUrl = editText.getText().toString(); - MainApplication.setServerUrl(serverUrl); - // 启动屏幕监控 - ScreenCaptureUtilByMediaPro.init(); - Intent intent = new Intent(this, RunTime.class); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(intent); - } else { - startService(intent); - } - finish(); + if (!TessactOcr.checkInit()) { + Toast.show("初始化中,Please Wait!"); + return; + } + // 启动屏幕监控 + ScreenCaptureUtilByMediaPro.init(); + Intent intent = new Intent(this, RunTime.class); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(intent); } else { - Toast.show("xp 框架加载失败!"); + startService(intent); } + finish(); + } - public void test(View view) { - - } + @Override + protected void onResume() { + super.onResume(); + updateStatus(); + } private boolean checkXposedHook() { return false; @@ -178,4 +176,16 @@ public void onManagerConnected(int status) { } } }; + + + private void updateStatus() { + TextView xpStatus = (TextView) findViewById(R.id.xposed_status); + TextView asStatus = (TextView) findViewById(R.id.accessibility_status); + TextView hsStatus = (TextView) findViewById(R.id.httpserver_status); + + xpStatus.setText(checkXposedHook() ? "Xposed状态:已加载" : "Xposed状态:未加载"); + asStatus.setText(Accessibility.DOM == null ? "Accessibility状态:未加载" : "Accessibility状态:已加载"); + hsStatus.setText((RunTime.httpServer != null && RunTime.httpServer.runing) ? "HttpServer状态:已开启" : "HttpServer状态:未开启"); + } + } diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/Accessibility.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/Accessibility.java new file mode 100644 index 0000000..c8b7790 --- /dev/null +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/Accessibility.java @@ -0,0 +1,47 @@ +package cn.xjiangwei.RobotHelper.Service; + +import android.accessibilityservice.AccessibilityService; +import android.util.Log; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; + +import java.util.List; + + +public class Accessibility extends AccessibilityService { + + + public static AccessibilityNodeInfo DOM; + + + + @Override + public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) { + DOM = getRootInActiveWindow(); + } + + public static void logViewHierarchy(AccessibilityNodeInfo nodeInfo, final int depth) { + + if (nodeInfo == null) return; + + String spacerString = ""; + + for (int i = 0; i < depth; ++i) { + spacerString += '-'; + } + //Log the info you care about here... I choce classname and view resource name, because they are simple, but interesting. + Log.d("TAG", spacerString + nodeInfo.getClassName() + " " + nodeInfo.getViewIdResourceName()); + + for (int i = 0; i < nodeInfo.getChildCount(); ++i) { + logViewHierarchy(nodeInfo.getChild(i), depth + 1); + } + } + + + @Override + public void onInterrupt() { + + } + + +} diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/RunTime.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/RunTime.java index 3d87e8b..a89eefd 100644 --- a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/RunTime.java +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Service/RunTime.java @@ -19,6 +19,7 @@ import java.lang.reflect.Method; +import cn.xjiangwei.RobotHelper.Accessibility.HttpServer; import cn.xjiangwei.RobotHelper.GamePackage.Main; import cn.xjiangwei.RobotHelper.R; import cn.xjiangwei.RobotHelper.Tools.MLog; @@ -31,9 +32,13 @@ public class RunTime extends Service { public final static String INTENT_BUTTONID_TAG = "ButtonId"; public final static int START = 1; public final static int END = 2; + public final static int START_HTTPSERVER = 3; + public final static int END_HTTPSERVER = 4; private static final String CHANNEL_ID = "cn.xjiangwei.RobotHelper.channel"; public final static String ACTION_BUTTON = "com.notification.intent.action.ButtonClick"; + public static HttpServer httpServer; + public RunTime() { } @@ -93,6 +98,19 @@ public void onCreate() { remoteViews.setOnClickPendingIntent(R.id.btn2, end); + //设置点击的事件 + Intent startHttpserverIntent = new Intent(ACTION_BUTTON); + startHttpserverIntent.putExtra(INTENT_BUTTONID_TAG, START_HTTPSERVER); + PendingIntent startHttpserver = PendingIntent.getBroadcast(this, START_HTTPSERVER, startHttpserverIntent, PendingIntent.FLAG_UPDATE_CURRENT); + remoteViews.setOnClickPendingIntent(R.id.start_http, startHttpserver); + + + Intent endHttpServerIntent = new Intent(ACTION_BUTTON); + endHttpServerIntent.putExtra(INTENT_BUTTONID_TAG, END_HTTPSERVER); + PendingIntent endHttpServer = PendingIntent.getBroadcast(this, END_HTTPSERVER, endHttpServerIntent, PendingIntent.FLAG_CANCEL_CURRENT); + remoteViews.setOnClickPendingIntent(R.id.end_http, endHttpServer); + + startForeground(101, notification); } @@ -126,6 +144,7 @@ public void onReceive(Context context, Intent intent) { if (action.equals(ACTION_BUTTON)) { //通过传递过来的ID判断按钮点击属性或者通过getResultCode()获得相应点击事件 int buttonId = intent.getIntExtra(INTENT_BUTTONID_TAG, 0); + System.out.println(buttonId); switch (buttonId) { case START: collapseStatusBar(context); @@ -157,6 +176,20 @@ public void run() { }); + break; + case START_HTTPSERVER: + if (httpServer == null) { + httpServer = new HttpServer(); + } else { + httpServer.start(); + } + cn.xjiangwei.RobotHelper.Tools.Toast.show("HttpServer Start!"); + + break; + case END_HTTPSERVER: + httpServer.stop(); + cn.xjiangwei.RobotHelper.Tools.Toast.show("HttpServer Stop!"); + break; default: break; diff --git a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Tools/Robot.java b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Tools/Robot.java index 64f628a..c223621 100644 --- a/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Tools/Robot.java +++ b/Android/app/src/main/java/cn/xjiangwei/RobotHelper/Tools/Robot.java @@ -4,6 +4,9 @@ import android.os.SystemClock; import android.view.MotionEvent; +import static android.os.SystemClock.sleep; +import static android.view.InputDevice.SOURCE_CLASS_POINTER; + public class Robot { private static Instrumentation mInst = null; @@ -72,4 +75,18 @@ public static void tap(Point p, long delay) { } + public static void swiper(final int start_x, final int start_y, final int end_x, final int end_y) { + if (Robot.mInst == null) { + mInst = new Instrumentation(); + } + //key down + mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, start_x, start_y, 0)); + //move + mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, start_x, start_y, 0)); + mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, end_x, end_y, 0)); + //key up + mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, end_x, end_y, 0)); + + } + } diff --git a/Android/app/src/main/res/layout/activity_main.xml b/Android/app/src/main/res/layout/activity_main.xml index f2be922..fbc2df4 100644 --- a/Android/app/src/main/res/layout/activity_main.xml +++ b/Android/app/src/main/res/layout/activity_main.xml @@ -4,15 +4,6 @@ android:layout_height="match_parent" android:orientation="vertical"> - - - - -