Ejemplo n.º 1
0
        /// <summary>
        /// Send a screen dump request to the ui automator server on the android device.
        /// </summary>
        /// <returns>The screen content as a xml string.</returns>
        public string DumpUi()
        {
            using (var client = new HttpClient {
                Timeout = TimeSpan.FromSeconds(_dumpTimeout)
            })
            {
                try
                {
                    var repsonse = client.GetAsync(DumpUrl).Result;
                    var dump     = repsonse.Content.ReadAsStringAsync().Result;
                    if (string.IsNullOrEmpty(dump))
                    {
                        DeviceLogger.Log("Empty dump from server!");
                        DeviceLogger.Log($"Status code: {repsonse.StatusCode}");
                        DeviceLogger.Log($"Reason phrase: {repsonse.ReasonPhrase}");
                        throw new UiAutomatorServerException("Could connect to server but the dumped ui was empty");
                    }

                    return(dump.Replace("\\\"", "\""));
                }
                catch (AggregateException ex)
                {
                    DeviceLogger.Log("Unexpected error/timed out when trying to dump: ");
                    DeviceLogger.Log(ex.ToString());
                    throw new UiAutomatorServerException("Failed to dump screen", ex);
                }
            }
        }
        /// <summary>
        /// Start an Activity specified by package and activity name
        /// </summary>
        /// <param name="packageName">Name of the package</param>
        /// <param name="activity">Name of the activity</param>
        /// <param name="forceStopActivity">Force stop the target application before starting the activity.</param>
        /// <param name="clearTasks">Clear activity stack</param>
        /// <exception cref="AdbException">Thrown if we can't find package/activity</exception>
        public void Start(string packageName, string activity, bool forceStopActivity, bool clearTasks)
        {
            if (string.IsNullOrEmpty(packageName))
            {
                throw new ArgumentException("Argument is null or empty", nameof(packageName));
            }

            if (string.IsNullOrWhiteSpace(activity))
            {
                throw new ArgumentException("Argument is null or whitespace", nameof(activity));
            }

            DeviceLogger.Log("Starting a new activity");
            var commandBuilder = new StringBuilder($"am start -W -n {packageName}/{activity}");

            if (forceStopActivity)
            {
                commandBuilder.Append(" -S");
            }

            if (clearTasks)
            {
                commandBuilder.Append(" --activity-clear-task");
            }

            var result = Device.Adb.Shell(commandBuilder.ToString());

            if (result.Contains("Error") || result.Contains("does not exist") || result.Contains("Exception"))
            {
                throw new AdbException(result);
            }

            Device.Ui.ClearCache();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Stop the ui automator server on the android device.
        /// </summary>
        public void Stop()
        {
            lock (_serverLock)
            {
                DeviceLogger.Log("Stopping server");
                try
                {
                    using (var client = new HttpClient()
                    {
                        Timeout = TimeSpan.FromSeconds(5)
                    })
                    {
                        client.GetAsync(StopUrl);
                    }
                }
                catch (Exception ex) when(ex is AggregateException || ex is HttpRequestException || ex is WebException)
                {
                    DeviceLogger.Log($"Failed stop server, already closed? {ex.Message}");
                }

                if (_currentServerProcess != null)
                {
                    KillLocalProcess(_currentServerProcess.Process.Id);
                }

                // Kill android process just to be safe..
                KillAndroidProcess();
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Kill the local process and it's children.
        /// </summary>
        /// <param name="pid">The process id.</param>
        private void KillLocalProcess(int pid)
        {
            var processSearcher =
                new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
            var processCollection = processSearcher.Get();

            try
            {
                var proc = Process.GetProcessById(pid);
                if (!proc.HasExited)
                {
                    proc.Kill();
                }
            }
            catch (ArgumentException)
            {
                // Process already exited.
            }
            catch (Exception ex)
            {
                DeviceLogger.Log($"Something went wrong when trying to kill local process: {ex}");
            }

            if (processCollection != null)
            {
                foreach (var mo in processCollection)
                {
                    KillLocalProcess(Convert.ToInt32(mo["ProcessID"]));
                }
            }
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Enable or disable bluetooth.
 /// </summary>
 /// <param name="state">Wanted state of bluetooth.</param>
 public void Bluetooth(State state)
 {
     DeviceLogger.Log("Changing wifi state");
     Device.Adb.Shell(state == State.Enable
         ? $"am startservice -n {PackageName}/{PackageName}.services.settings.BluetoothService -e enable 1"
         : $"am startservice -n {PackageName}/{PackageName}.services.settings.BluetoothService  -e enable 0");
 }
Ejemplo n.º 6
0
        /// <summary>
        /// Start the ui automator server on the android device.
        /// </summary>
        /// <exception cref="UiAutomatorServerException">The exception thrown if we can't server.</exception>
        public void Start()
        {
            lock (_serverLock)
            {
                DeviceLogger.Log("Starting server..");
                if (_currentServerProcess == null || _currentServerProcess.Process.HasExited)
                {
                    ForwardPorts();
                    KillAndroidProcess();
                    DeviceLogger.Log("Starting instrumental");
                    _currentServerProcess = _terminal.StartAdbProcess(
                        "shell",
                        $"am instrument -w -r -e debug false -e class {AndroidPackageName}.Start {AndroidPackageName}.test/android.support.test.runner.AndroidJUnitRunner");
                }
                else
                {
                    DeviceLogger.Log("Server already started");
                }

                if (!Alive(5))
                {
                    throw new UiAutomatorServerException("Could not start server");
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Enable or disable airplane mode
        /// </summary>
        /// <param name="state">Wanted state of airplane mode</param>
        public void AirplaneMode(State state)
        {
            DeviceLogger.Log("Changing airplane mode state");
            Device.Adb.Shell(state == State.Enable
                ? "settings put global airplane_mode_on 1"
                : "settings put global airplane_mode_on 0");

            Device.Adb.Shell("am broadcast -a android.intent.action.AIRPLANE_MODE");
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Perform a swipe motion on the screen.
        /// </summary>
        /// <param name="fromX">Start x position on screen</param>
        /// <param name="fromY">Start y position on screen</param>
        /// <param name="toX">Final x position on screen</param>
        /// <param name="toY">Final y position on screen</param>
        /// <param name="duration">Duration of the swipe in milliseconds</param>
        public void Swipe(int fromX, int fromY, int toX, int toY, int duration)
        {
            if (!_interactionServer.Swipe(fromX, fromY, toX, toY, duration))
            {
                DeviceLogger.Log("Failed to swipe through server, trying through adb.");
                Device.Adb.Shell($"input swipe {fromX} {fromY} {toX} {toY} {duration}");
            }

            Device.Ui.ClearCache();
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Send a key event to the device.
        /// </summary>
        /// <param name="keyEvent">Key event to send to the device</param>
        public void InputKeyEvent(KeyEvents keyEvent)
        {
            if (!_interactionServer.InputKeyEvent(keyEvent))
            {
                DeviceLogger.Log("Failed to input key event through server, trying through adb.");
                Device.Adb.Shell($"input keyevent {(int)keyEvent}");
            }

            Device.Ui.ClearCache();
        }
Ejemplo n.º 10
0
        /// <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();
        }
Ejemplo n.º 11
0
 /// <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());
        }
Ejemplo n.º 13
0
        /// <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);
        }
Ejemplo n.º 14
0
        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]));
        }
Ejemplo n.º 15
0
        /// <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();
        }
Ejemplo n.º 16
0
        /// <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);
        }
Ejemplo n.º 17
0
 /// <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);
         }
     }
 }
Ejemplo n.º 19
0
        /// <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);
            }
        }
Ejemplo n.º 20
0
        /// <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);
            }
        }
Ejemplo n.º 21
0
        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;
                }
            }
        }
Ejemplo n.º 22
0
        /// <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);
                }
            }
        }
 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));
 }
Ejemplo n.º 24
0
 /// <summary>
 /// Forward ports to the android device.
 /// </summary>
 private void ForwardPorts()
 {
     DeviceLogger.Log("Forwarding ports");
     _terminal.ExecuteAdbCommand("forward", $"tcp:{_localPort}", $"tcp:{DevicePort}");
 }
Ejemplo n.º 25
0
 /// <summary>
 /// Stop the logcat watcher task.
 /// </summary>
 public void Stop()
 {
     DeviceLogger.Log("Request to stop logcat watcher..");
     _cancellationTokenSource?.Cancel();
     _task?.Wait(2000);
 }