/** * When data is available on the socket, this method is called to run the command or throw an * error if it can't. * * @throws SocketServerException */ private void handleClientData() throws SocketServerException { try { input.setLength(0); // clear String res; int a; // (char) -1 is not equal to -1. // ready is checked to ensure the read call doesn't block. while ((a = in.read()) != -1 && in.ready()) { input.append((char) a); } String inputString = input.toString(); Logger.debug("Got data from client: " + inputString); try { AndroidCommand cmd = getCommand(inputString); Logger.debug("Got command of type " + cmd.commandType().toString()); res = runCommand(cmd); Logger.debug("Returning result: " + res); } catch (final CommandTypeException e) { res = new AndroidCommandResult(WDStatus.UNKNOWN_ERROR, e.getMessage()).toString(); } catch (final JSONException e) { res = new AndroidCommandResult(WDStatus.UNKNOWN_ERROR, "Error running and parsing command") .toString(); } out.write(res); out.flush(); } catch (final IOException e) { throw new SocketServerException( "Error processing data to/from socket (" + e.toString() + ")"); } }
/* * @param command The {@link AndroidCommand} used for this handler. * * @return {@link AndroidCommandResult} * * @throws JSONException * * @see io.appium.android.bootstrap.CommandHandler#execute(io.appium.android. * bootstrap.AndroidCommand) */ @Override public AndroidCommandResult execute(final AndroidCommand command) throws JSONException { final Hashtable<String, Object> params = command.params(); AndroidElement el; final String direction = params.get("direction").toString(); final Integer percent = (Integer) params.get("percent"); final Integer steps = (Integer) params.get("steps"); try { el = command.getElement(); if (el == null) { return getErrorResult( "Could not find an element with elementId: " + params.get("elementId")); } } catch (final Exception e) { // JSONException, NullPointerException, etc. return getErrorResult("Unknown error:" + e.getMessage()); } Logger.debug( "Pinching " + direction + " " + percent.toString() + "%" + " with steps: " + steps.toString()); boolean res; if (direction.equals("in")) { try { res = el.pinchIn(percent, steps); } catch (final UiObjectNotFoundException e) { return getErrorResult("Selector could not be matched to any UI element displayed"); } } else { try { res = el.pinchOut(percent, steps); } catch (final UiObjectNotFoundException e) { return getErrorResult("Selector could not be matched to any UI element displayed"); } } if (res) { return getSuccessResult(res); } else { return getErrorResult("Pinch did not complete successfully"); } }
/** * Gets the handler out of the map, and executes the command. * * @param command The {@link AndroidCommand} * @return {@link AndroidCommandResult} */ public AndroidCommandResult execute(final AndroidCommand command) { try { Logger.debug("Got command action: " + command.action()); if (map.containsKey(command.action())) { return map.get(command.action()).execute(command); } else { return new AndroidCommandResult( WDStatus.UNKNOWN_COMMAND, "Unknown command: " + command.action()); } } catch (final JSONException e) { Logger.error("Could not decode action/params of command"); return new AndroidCommandResult( WDStatus.JSON_DECODER_ERROR, "Could not decode action/params of command, please check format!"); } }
/** * When {@link #handleClientData()} has valid data, this method delegates the command. * * @param cmd AndroidCommand * @return Result */ private String runCommand(final AndroidCommand cmd) { AndroidCommandResult res; if (cmd.commandType() == AndroidCommandType.SHUTDOWN) { keepListening = false; res = new AndroidCommandResult(WDStatus.SUCCESS, "OK, shutting down"); } else if (cmd.commandType() == AndroidCommandType.ACTION) { try { res = executor.execute(cmd); } catch ( final Exception e) { // Here we catch all possible exceptions and return a JSON Wire Protocol // UnknownError // This prevents exceptions from halting the bootstrap app res = new AndroidCommandResult(WDStatus.UNKNOWN_ERROR, e.getMessage()); } } else { // this code should never be executed, here for future-proofing res = new AndroidCommandResult( WDStatus.UNKNOWN_ERROR, "Unknown command type, could not execute!"); } return res.toString(); }