//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public async Task <int> OnDebuggerLogcatEvent(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, Guid riidEvent, uint dwAttrib) { LoggingUtils.PrintFunction(); try { DebugEngineEvent.DebuggerLogcatEvent debuggerLogcatEvent = pEvent as DebugEngineEvent.DebuggerLogcatEvent; using (SyncRedirectProcess command = AndroidAdb.AdbCommand(debuggerLogcatEvent.HostDevice, "logcat", "-c")) { command.StartAndWaitForExit(); } m_adbLogcatProcess = AndroidAdb.AdbCommandAsync(debuggerLogcatEvent.HostDevice, "logcat", ""); m_adbLogcatListener = new DeviceLogcatListener(); m_adbLogcatProcess.Start(m_adbLogcatListener); return(VSConstants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(VSConstants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int OnDebuggerLogcatEvent(IDebugEngine2 pEngine, IDebugProcess2 pProcess, IDebugProgram2 pProgram, IDebugThread2 pThread, IDebugEvent2 pEvent, ref Guid riidEvent, uint dwAttrib) { LoggingUtils.PrintFunction(); try { DebugEngineEvent.DebuggerLogcatEvent debuggerLogcatEvent = pEvent as DebugEngineEvent.DebuggerLogcatEvent; using (SyncRedirectProcess command = AndroidAdb.AdbCommand(debuggerLogcatEvent.HostDevice, "logcat", "-c")) { command.StartAndWaitForExit(); } m_adbLogcatProcess = AndroidAdb.AdbCommandAsync(debuggerLogcatEvent.HostDevice, "logcat", ""); m_adbLogcatListener = new DeviceLogcatListener(); if (m_adbLogcatProcess == null) { throw new InvalidOperationException("Failed to launch logcat application."); } if (m_adbLogcatListener == null) { throw new InvalidOperationException("Failed to launch logcat listener."); } m_adbLogcatProcess.Start(m_adbLogcatListener); return(VSConstants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(VSConstants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public LaunchConfiguration GetLaunchConfigurationFromProjectProperties(IDictionary <string, string> projectProperties) { LoggingUtils.PrintFunction(); // // Retrieve standard project macro values, and determine the preferred debugger configuration. // string projectTargetName = EvaluateProjectProperty(projectProperties, "ConfigurationGeneral", "TargetName"); string projectProjectDir = EvaluateProjectProperty(projectProperties, "ConfigurationGeneral", "ProjectDir"); string debuggerMode = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigMode"); string debuggerTargetApk = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigTargetApk"); string debuggerUpToDateCheck = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigUpToDateCheck"); string debuggerLaunchActivity = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigLaunchActivity"); string debuggerDebugMode = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigDebugMode"); string debuggerOpenGlTrace = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigOpenGlTrace"); string debuggerKeepAppData = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigKeepAppData"); string debuggerInstallerPackage = EvaluateProjectProperty(projectProperties, "AndroidPlusPlusDebugger", "DebuggerConfigInstallerPackage"); if (string.IsNullOrEmpty(debuggerMode)) { debuggerMode = "Custom"; } else if (debuggerMode.Equals("vs-android")) { // // Support for vs-android. // string antBuildPath = EvaluateProjectProperty(projectProperties, "AntBuild", "AntBuildPath"); string antBuildType = EvaluateProjectProperty(projectProperties, "AntBuild", "AntBuildType"); string antBuildXml = Path.Combine(antBuildPath, "build.xml"); XmlDocument buildXmlDocument = new XmlDocument(); buildXmlDocument.Load(antBuildXml); string antBuildXmlProjectName = buildXmlDocument.DocumentElement.GetAttribute("name"); debuggerTargetApk = Path.Combine(antBuildPath, "bin", string.Format(CultureInfo.InvariantCulture, "{0}-{1}.apk", antBuildXmlProjectName, antBuildType)); } // // Ensure the provided target APK is found and absolute. // if (string.IsNullOrEmpty(debuggerTargetApk)) { throw new FileNotFoundException("Could not locate target application. Empty path provided."); } else if (!Path.IsPathRooted(debuggerTargetApk) && !string.IsNullOrWhiteSpace(projectProjectDir)) { debuggerTargetApk = Path.Combine(projectProjectDir, debuggerTargetApk); } if (!Path.IsPathRooted(debuggerTargetApk)) { throw new InvalidOperationException("Could not evaluate an absolute path to the target application. Tried: " + debuggerTargetApk); } debuggerTargetApk = Path.GetFullPath(debuggerTargetApk); // normalises relative paths. if (!File.Exists(debuggerTargetApk)) { throw new FileNotFoundException("Could not find required target application. Expected: " + debuggerTargetApk); } // // Find the selected Android SDK (and associated build-tools) deployment. // string androidSdkRoot = EvaluateProjectProperty(projectProperties, "ConfigurationGeneral", "AndroidSdkRoot"); if (string.IsNullOrWhiteSpace(androidSdkRoot)) { throw new DirectoryNotFoundException("Could not locate Android SDK. \"AndroidSdkRoot\" property is empty."); } else if (!Directory.Exists(androidSdkRoot)) { throw new DirectoryNotFoundException("Could not locate Android SDK. \"AndroidSdkRoot\" property references a directory which does not exist. Expected: " + androidSdkRoot); } string androidSdkBuildToolsVersion = EvaluateProjectProperty(projectProperties, "ConfigurationGeneral", "AndroidSdkBuildToolsVersion"); string androidSdkBuildToolsPath = Path.Combine(androidSdkRoot, "build-tools", androidSdkBuildToolsVersion); if (!Directory.Exists(androidSdkBuildToolsPath)) { throw new DirectoryNotFoundException(string.Format(CultureInfo.CurrentCulture, "Could not locate Android SDK build-tools (v{0}). Expected: {1}", androidSdkBuildToolsVersion, androidSdkBuildToolsPath)); } // // Spawn a AAPT.exe instance to gain some extra information about the APK we are trying to load. // string applicationPackageName = string.Empty; string applicationLaunchActivity = string.Empty; string aaptToolPath = Path.Combine(androidSdkBuildToolsPath, "aapt.exe"); if (!File.Exists(aaptToolPath)) { throw new FileNotFoundException("Could not locate AAPT tool (under Android SDK build-tools).", aaptToolPath); } using (SyncRedirectProcess getApkDetails = new SyncRedirectProcess(aaptToolPath, "dump --values badging " + PathUtils.SantiseWindowsPath(debuggerTargetApk))) { int exitCode = getApkDetails.StartAndWaitForExit(); if (exitCode != 0) { throw new InvalidOperationException("AAPT failed to dump required application badging information. Exit-code: " + exitCode); } var apkDetails = getApkDetails.StandardOutput.Replace("\r", "").Split(new char [] { '\n' }); foreach (string singleLine in apkDetails) { if (singleLine.StartsWith("package: ", StringComparison.OrdinalIgnoreCase)) { // // Retrieve package name from format: "package: name='com.example.hellogdbserver' versionCode='1' versionName='1.0'" // var packageData = singleLine.Substring("package: ".Length).Split(' '); foreach (string data in packageData) { if (data.StartsWith("name=", StringComparison.OrdinalIgnoreCase)) { applicationPackageName = data.Substring("name=".Length).Trim('\''); } } } else if (singleLine.StartsWith("launchable-activity: ", StringComparison.OrdinalIgnoreCase)) { var launchActivityData = singleLine.Substring("launchable-activity: ".Length).Split(' '); foreach (string data in launchActivityData) { if (data.StartsWith("name=", StringComparison.OrdinalIgnoreCase)) { applicationLaunchActivity = data.Substring("name=".Length).Trim('\''); } } } } } // // If a specific launch activity was not requested, ensure that the default one is referenced. // if (string.IsNullOrEmpty(debuggerLaunchActivity)) { debuggerLaunchActivity = applicationLaunchActivity; } LaunchConfiguration launchConfig = new LaunchConfiguration { ["TargetApk"] = debuggerTargetApk, ["UpToDateCheck"] = debuggerUpToDateCheck, ["PackageName"] = applicationPackageName, ["LaunchActivity"] = debuggerLaunchActivity, ["DebugMode"] = debuggerDebugMode, ["OpenGlTrace"] = debuggerOpenGlTrace, ["KeepAppData"] = debuggerKeepAppData, ["InstallerPackage"] = debuggerInstallerPackage }; return(launchConfig); }