/// <summary> /// Tap on an x and y position of the screen. /// </summary> /// <param name="x">The x position</param> /// <param name="y">The y position</param> public void Tap(int x, int y) { if (!_interactionServer.Tap(x, y)) { DeviceLogger.Log("Failed to tap through server, trying through adb."); Device.Adb.Shell($"input tap {x} {y}"); } Device.Ui.ClearCache(); }
/// <summary> /// Kill the android process. /// </summary> private void KillAndroidProcess() { try { _terminal.ExecuteAdbCommand("shell", $"ps | grep {AndroidPackageName}"); DeviceLogger.Log("Killing testura helper process on the device."); _terminal.ExecuteAdbCommand("shell", $"pm clear {AndroidPackageName}"); } catch (Exception) { // The terminal throw an exception if we can't find anything with grep. } }
/// <summary> /// Get the current open activity /// </summary> /// <returns>Current open activity</returns> public string GetCurrent() { DeviceLogger.Log("Getting current activity"); var activity = Device.Adb.Shell("dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp'"); var regex = new Regex(@"(?<=\{)[^}]*(?=\})"); var matches = regex.Matches(activity); if (matches.Count == 0) { return("Unknown activity"); } return(matches[0].Value.Split(' ').Last()); }
/// <summary> /// Start the logcat watcher task. /// </summary> public void Start() { DeviceLogger.Log("Starting logcat watcher.."); if (_flushLogcat) { _terminal.ExecuteAdbCommand(new[] { "logcat", "-c" }); } _cancellationTokenSource = new CancellationTokenSource(); var commands = new List <string> { "shell", "logcat", "-s" }; commands.AddRange(_tags); var process = _terminal.StartAdbProcessWithoutShell(commands.ToArray()); var cancellationToken = _cancellationTokenSource.Token; _task = Task.Run( () => { process.StandardOutput.BaseStream.ReadTimeout = 500; while (true) { try { var output = process.StandardOutput.ReadLine(); if (!string.IsNullOrEmpty(output)) { NewOutput(output); } } catch (TimeoutException) { } if (_cancellationTokenSource.IsCancellationRequested) { DeviceLogger.Log("Logcat watcher cancellation requested, stopping task."); return; } } }, cancellationToken); }
private void SetScreenHeightAndWidth() { DeviceLogger.Log("Getting width and height"); var widthAndHeight = Device.Adb.Shell("wm size"); if (string.IsNullOrEmpty(widthAndHeight)) { throw new AdbException("Could not get screen width and height"); } var split = widthAndHeight.Replace(" ", string.Empty).Split(':', 'x'); DeviceLogger.Log($"Width: {split[split.Length - 2]}, Height: {split[split.Length - 1]}"); _screenBounds = new NodeBounds(int.Parse(split[split.Length - 2]), int.Parse(split[split.Length - 1])); }
/// <summary> /// Input text into the node /// </summary> /// <param name="text">The text to input into the node</param> public void InputText(string text) { if (text == null) { throw new ArgumentNullException(nameof(text)); } if (!_interactionServer.InputText(text)) { DeviceLogger.Log("Failed to input text through server, trying through adb."); Device.Adb.Shell($"input text {text.Replace(" ", "%s")}"); } Device.Ui.ClearCache(); }
/// <summary> /// Check if the ui automator server is alive on the android device. /// </summary> /// <param name="timeout">Timeout in seconds.</param> /// <returns>True if server is a alive, false otherwise.</returns> public bool Alive(int timeout) { var time = DateTime.Now; while ((DateTime.Now - time).TotalSeconds < timeout) { var result = Ping(); if (result) { return(true); } } DeviceLogger.Log("Server is not alive!"); return(false); }
/// <summary> /// Enable or disable gps /// </summary> /// <param name="state">Wanted state of gps</param> public void Gps(State state) { DeviceLogger.Log("Changing gps state"); if (state == State.Enable) { Device.Adb.Shell("settings put secure location_providers_allowed +gps"); Device.Adb.Shell("settings put secure location_providers_allowed +network"); Device.Adb.Shell("settings put secure location_providers_allowed +wifi"); } else { Device.Adb.Shell("settings put secure location_providers_allowed -gps"); Device.Adb.Shell("settings put secure location_providers_allowed -network"); Device.Adb.Shell("settings put secure location_providers_allowed -wifi"); } }
public void InstallDependenciesIfMissing(IAdbService adbService, IActivityService activityService, DeviceConfiguration configuration) { DeviceLogger.Log("Checking if helper is installed.."); if (!activityService.IsPackagedInstalled("com.testura.server")) { DeviceLogger.Log("..not installed."); InstallDependencies(adbService, configuration); } else { DeviceLogger.Log("..already installed."); var latestVersion = Version.Parse(DeviceConfiguration.ServerApkVersion); if (activityService.GetPackageVersion("com.testura.server") < latestVersion) { DeviceLogger.Log("But you don't have the current/latest version. Updating your dependencies"); InstallDependencies(adbService, configuration); } } }
/// <summary> /// Start the adb process and return the command. /// </summary> /// <param name="arguments">Arguments that should be provided to adb.</param> /// <returns>The command that contains the started process.</returns> public Command StartAdbProcess(params string[] arguments) { var allArguments = new List <string> { "/c", GetAdbExe() }; if (!string.IsNullOrEmpty(_deviceConfiguration.Serial)) { allArguments.Add("-s"); allArguments.Add(_deviceConfiguration.Serial); } allArguments.AddRange(arguments); DeviceLogger.Log($"Starting adb process with shell: {string.Join(" ", allArguments)}"); try { var command = Command.Run( "cmd.exe", allArguments.ToArray(), o => { o.StartInfo(si => { si.CreateNoWindow = false; si.UseShellExecute = true; si.RedirectStandardError = false; si.RedirectStandardInput = false; si.RedirectStandardOutput = false; }); o.DisposeOnExit(false); }); return(command); } catch (Win32Exception) { throw new AdbException(AdbNotFoundError); } }
/// <summary> /// Execute a new adb command. /// </summary> /// <param name="arguments">Arguments to send to the adb.</param> /// <returns>Output from adb.</returns> public string ExecuteAdbCommand(params string[] arguments) { var allArguments = new List <string>(); if (!string.IsNullOrEmpty(_deviceConfiguration.Serial)) { allArguments.Add("-s"); allArguments.Add(_deviceConfiguration.Serial); } allArguments.AddRange(arguments); DeviceLogger.Log($"Sending adb command: {string.Join(" ", allArguments)}"); try { using (var command = Command.Run( GetAdbExe(), allArguments, options: o => o.Timeout(TimeSpan.FromMinutes(1)))) { var output = command.StandardOutput.ReadToEnd(); var error = command.StandardError.ReadToEnd(); if (!command.Result.Success) { var message = $"Output: {output}, Error: {error}"; DeviceLogger.Log(message); throw new AdbException(message); } return(output); } } catch (Win32Exception) { throw new AdbException(AdbNotFoundError); } }
private string GetDump() { int tries = _dumpTries; while (true) { try { if (!_server.Alive(2)) { _server.Start(); } return(_server.DumpUi()); } catch (UiAutomatorServerException) { if (tries > 0) { DeviceLogger.Log($"Failed to dump UI, trying {tries} more times"); tries--; /* In some cases we get stuck and the server is alive * but we can't dump the UI. So try a reboot */ if (_server.Alive(2)) { DeviceLogger.Log("Server alive but we can't dump.. trying a reboot."); _server.Stop(); } continue; } DeviceLogger.Log("Tried everything but still can't dump the screen. Glitch in the matrix or did your device freeze?"); throw; } } }
/// <summary> /// Send interaction request to server /// </summary> /// <param name="url">Url of the request</param> /// <param name="timeout">Timeout of request</param> /// <returns>True if we managed to perform interaction, otherwise false.</returns> private bool SendInteractionRequest(string url, TimeSpan timeout) { if (!Alive(5)) { Start(); } DeviceLogger.Log($"Sending interaction request to server: {url}"); using (var client = new HttpClient { Timeout = timeout }) { try { var repsonse = client.GetAsync(url).Result; if (!repsonse.IsSuccessStatusCode) { if (repsonse.StatusCode == HttpStatusCode.NotFound) { throw new UiAutomatorServerException( "Server responded with 404, make sure that you have the latest Testura server app."); } return(false); } var result = repsonse.Content.ReadAsStringAsync().Result; return(result == "success"); } catch (AggregateException) { DeviceLogger.Log("interaction request timed out"); return(false); } } }
/// <summary> /// Forward ports to the android device. /// </summary> private void ForwardPorts() { DeviceLogger.Log("Forwarding ports"); _terminal.ExecuteAdbCommand("forward", $"tcp:{_localPort}", $"tcp:{DevicePort}"); }
public void InstallDependencies(IAdbService adbService, DeviceConfiguration configuration) { DeviceLogger.Log("Installing all dependencies.."); adbService.InstallApp(Path.Combine(configuration.DependenciesDirectory, DeviceConfiguration.ServerApkName)); adbService.InstallApp(Path.Combine(configuration.DependenciesDirectory, DeviceConfiguration.ServerUiAutomatorApkName)); }
/// <summary> /// Stop the logcat watcher task. /// </summary> public void Stop() { DeviceLogger.Log("Request to stop logcat watcher.."); _cancellationTokenSource?.Cancel(); _task?.Wait(2000); }