diff --git a/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs b/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs
index 12e862c7..0cc4d7ab 100644
--- a/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs
+++ b/AdvancedSharpAdbClient.Tests/AdbClientTests.Async.cs
@@ -990,6 +990,7 @@ public async void DumpScreenStringAsyncTest()
};
string dump = File.ReadAllText(@"Assets/dumpscreen.txt");
+ string cleanDump = File.ReadAllText(@"Assets/dumpscreen_clean.txt");
byte[] streamData = Encoding.UTF8.GetBytes(dump);
await using MemoryStream shellStream = new(streamData);
@@ -1006,7 +1007,117 @@ await RunTestAsync(
shellStream,
async () => xml = await TestClient.DumpScreenStringAsync(device));
- Assert.Equal(dump.Replace("Events injected: 1\r\n", "").Replace("UI hierchary dumped to: /dev/tty", "").Trim(), xml);
+ Assert.Equal(cleanDump, xml);
+ }
+
+ ///
+ /// Tests the method.
+ ///
+ [Fact]
+ public async void DumpScreenStringAsyncMIUITest()
+ {
+ DeviceData device = new()
+ {
+ Serial = "009d1cd696d5194a",
+ State = DeviceState.Online
+ };
+
+ string[] requests = new string[]
+ {
+ "host:transport:009d1cd696d5194a",
+ "shell:uiautomator dump /dev/tty"
+ };
+
+ string miuiDump = File.ReadAllText(@"Assets/dumpscreen_miui.txt");
+ string cleanMIUIDump = File.ReadAllText(@"Assets/dumpscreen_miui_clean.txt");
+ byte[] miuiStreamData = Encoding.UTF8.GetBytes(miuiDump);
+ await using MemoryStream miuiStream = new(miuiStreamData);
+
+ string miuiXml = string.Empty;
+
+ await RunTestAsync(
+ new AdbResponse[]
+ {
+ AdbResponse.OK,
+ AdbResponse.OK,
+ },
+ NoResponseMessages,
+ requests,
+ miuiStream,
+ async () => miuiXml = await TestClient.DumpScreenStringAsync(device));
+
+ Assert.Equal(cleanMIUIDump, miuiXml);
+ }
+
+ ///
+ /// Tests the method.
+ ///
+ [Fact]
+ public async void DumpScreenStringAsyncEmptyTest()
+ {
+ DeviceData device = new()
+ {
+ Serial = "009d1cd696d5194a",
+ State = DeviceState.Online
+ };
+
+ string[] requests = new string[]
+ {
+ "host:transport:009d1cd696d5194a",
+ "shell:uiautomator dump /dev/tty"
+ };
+
+ byte[] emptyStreamData = Encoding.UTF8.GetBytes(string.Empty);
+ await using MemoryStream emptyStream = new(emptyStreamData);
+ string emptyXml = string.Empty;
+
+ await RunTestAsync(
+ new AdbResponse[]
+ {
+ AdbResponse.OK,
+ AdbResponse.OK,
+ },
+ NoResponseMessages,
+ requests,
+ emptyStream,
+ async () => emptyXml = await TestClient.DumpScreenStringAsync(device));
+
+ Assert.True(string.IsNullOrEmpty(emptyXml));
+ }
+
+ ///
+ /// Tests the method.
+ ///
+ [Fact]
+ public async void DumpScreenStringAsyncErrorTest()
+ {
+ DeviceData device = new()
+ {
+ Serial = "009d1cd696d5194a",
+ State = DeviceState.Online
+ };
+
+ string[] requests = new string[]
+ {
+ "host:transport:009d1cd696d5194a",
+ "shell:uiautomator dump /dev/tty"
+ };
+
+ string errorXml = File.ReadAllText(@"Assets/dumpscreen_error.txt");
+ byte[] errorStreamData = Encoding.UTF8.GetBytes(errorXml);
+ await using MemoryStream errorStream = new(errorStreamData);
+
+ await Assert.ThrowsAsync(() =>
+ RunTestAsync(
+ new AdbResponse[]
+ {
+ AdbResponse.OK,
+ AdbResponse.OK,
+ },
+ NoResponseMessages,
+ requests,
+ errorStream,
+ () => TestClient.DumpScreenStringAsync(device)));
}
///
@@ -1044,8 +1155,9 @@ await RunTestAsync(
shellStream,
async () => xml = await TestClient.DumpScreenAsync(device));
+ string cleanDump = File.ReadAllText(@"Assets/dumpscreen_clean.txt");
XmlDocument doc = new();
- doc.LoadXml(dump.Replace("Events injected: 1\r\n", "").Replace("UI hierchary dumped to: /dev/tty", "").Trim());
+ doc.LoadXml(cleanDump);
Assert.Equal(doc, xml);
}
diff --git a/AdvancedSharpAdbClient.Tests/AdbClientTests.cs b/AdvancedSharpAdbClient.Tests/AdbClientTests.cs
index b11ddbb5..2329e388 100644
--- a/AdvancedSharpAdbClient.Tests/AdbClientTests.cs
+++ b/AdvancedSharpAdbClient.Tests/AdbClientTests.cs
@@ -12,7 +12,7 @@
using System.Text;
using System.Xml;
using Xunit;
-using System.Data.Common;
+using System.Text.RegularExpressions;
namespace AdvancedSharpAdbClient.Tests
{
@@ -1112,6 +1112,7 @@ public void DumpScreenStringTest()
};
string dump = File.ReadAllText(@"Assets/dumpscreen.txt");
+ string cleanDump = File.ReadAllText(@"Assets/dumpscreen_clean.txt");
byte[] streamData = Encoding.UTF8.GetBytes(dump);
using MemoryStream shellStream = new(streamData);
@@ -1128,7 +1129,117 @@ public void DumpScreenStringTest()
shellStream,
() => xml = TestClient.DumpScreenString(device));
- Assert.Equal(dump.Replace("Events injected: 1\r\n", "").Replace("UI hierchary dumped to: /dev/tty", "").Trim(), xml);
+ Assert.Equal(cleanDump, xml);
+ }
+
+ ///
+ /// Tests the method.
+ ///
+ [Fact]
+ public void DumpScreenStringMIUITest()
+ {
+ DeviceData device = new()
+ {
+ Serial = "009d1cd696d5194a",
+ State = DeviceState.Online
+ };
+
+ string[] requests = new string[]
+ {
+ "host:transport:009d1cd696d5194a",
+ "shell:uiautomator dump /dev/tty"
+ };
+
+ string miuidump = File.ReadAllText(@"Assets/dumpscreen_miui.txt");
+ string cleanMIUIDump = File.ReadAllText(@"Assets/dumpscreen_miui_clean.txt");
+ byte[] miuiStreamData = Encoding.UTF8.GetBytes(miuidump);
+ using MemoryStream miuiStream = new(miuiStreamData);
+
+ string miuiXml = string.Empty;
+
+ RunTest(
+ new AdbResponse[]
+ {
+ AdbResponse.OK,
+ AdbResponse.OK,
+ },
+ NoResponseMessages,
+ requests,
+ miuiStream,
+ () => miuiXml = TestClient.DumpScreenString(device));
+
+ Assert.Equal(cleanMIUIDump, miuiXml);
+ }
+
+ ///
+ /// Tests the method.
+ ///
+ [Fact]
+ public void DumpScreenStringEmptyTest()
+ {
+ DeviceData device = new()
+ {
+ Serial = "009d1cd696d5194a",
+ State = DeviceState.Online
+ };
+
+ string[] requests = new string[]
+ {
+ "host:transport:009d1cd696d5194a",
+ "shell:uiautomator dump /dev/tty"
+ };
+
+ byte[] emptyStreamData = Encoding.UTF8.GetBytes(string.Empty);
+ using MemoryStream emptyStream = new(emptyStreamData);
+ string emptyXml = string.Empty;
+
+ RunTest(
+ new AdbResponse[]
+ {
+ AdbResponse.OK,
+ AdbResponse.OK,
+ },
+ NoResponseMessages,
+ requests,
+ emptyStream,
+ () => emptyXml = TestClient.DumpScreenString(device));
+
+ Assert.True(string.IsNullOrEmpty(emptyXml));
+ }
+
+ ///
+ /// Tests the method.
+ ///
+ [Fact]
+ public void DumpScreenStringErrorTest()
+ {
+ DeviceData device = new()
+ {
+ Serial = "009d1cd696d5194a",
+ State = DeviceState.Online
+ };
+
+ string[] requests = new string[]
+ {
+ "host:transport:009d1cd696d5194a",
+ "shell:uiautomator dump /dev/tty"
+ };
+
+ string errorXml = File.ReadAllText(@"Assets/dumpscreen_error.txt");
+ byte[] errorStreamData = Encoding.UTF8.GetBytes(errorXml);
+ using MemoryStream errorStream = new(errorStreamData);
+
+ Assert.Throws(() =>
+ RunTest(
+ new AdbResponse[]
+ {
+ AdbResponse.OK,
+ AdbResponse.OK,
+ },
+ NoResponseMessages,
+ requests,
+ errorStream,
+ () => TestClient.DumpScreenString(device)));
}
///
@@ -1166,8 +1277,9 @@ public void DumpScreenTest()
shellStream,
() => xml = TestClient.DumpScreen(device));
+ string cleanDump = File.ReadAllText(@"Assets/dumpscreen_clean.txt");
XmlDocument doc = new();
- doc.LoadXml(dump.Replace("Events injected: 1\r\n", "").Replace("UI hierchary dumped to: /dev/tty", "").Trim());
+ doc.LoadXml(cleanDump);
Assert.Equal(doc, xml);
}
diff --git a/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj b/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj
index 804c34c8..57b10ad1 100644
--- a/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj
+++ b/AdvancedSharpAdbClient.Tests/AdvancedSharpAdbClient.Tests.csproj
@@ -26,6 +26,18 @@
PreserveNewest
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
PreserveNewest
diff --git a/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_clean.txt b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_clean.txt
new file mode 100644
index 00000000..508a3f03
--- /dev/null
+++ b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_clean.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_error.txt b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_error.txt
new file mode 100644
index 00000000..097b3a94
--- /dev/null
+++ b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_error.txt
@@ -0,0 +1,30 @@
+java.io.FileNotFoundException: /data/system/theme_config/theme_compatibility.xml: open failed: ENOENT (No such file or directory)
+ at libcore.io.IoBridge.open(IoBridge.java:574)
+ at java.io.FileInputStream.(FileInputStream.java:160)
+ at java.io.FileInputStream.(FileInputStream.java:115)
+ at java.io.FileReader.(FileReader.java:60)
+ at miui.content.res.ThemeCompatibilityLoader.getVersion(ThemeCompatibilityLoader.java:108)
+ at miui.content.res.ThemeCompatibilityLoader.getConfigDocumentTree(ThemeCompatibilityLoader.java:126)
+ at miui.content.res.ThemeCompatibilityLoader.loadConfig(ThemeCompatibilityLoader.java:59)
+ at miui.content.res.ThemeCompatibility.(ThemeCompatibility.java:31)
+ at miui.content.res.ThemeCompatibility.isThemeEnabled(ThemeCompatibility.java:111)
+ at android.content.res.MiuiResourcesImpl.(MiuiResourcesImpl.java:41)
+ at android.content.res.MiuiResources.(MiuiResources.java:58)
+ at android.content.res.IMiuiResourceImpl.createResources(IMiuiResourceImpl.java:13)
+ at android.content.res.ThemeManagerStub.createMiuiResources(ThemeManagerStub.java:56)
+ at android.content.res.Resources.getSystem(Resources.java:235)
+ at android.util.MiuiMultiWindowAdapter.(MiuiMultiWindowAdapter.java:81)
+ at android.util.MiuiMultiWindowAdapter.getSize(MiuiMultiWindowAdapter.java:305)
+ at com.xiaomi.freeform.MiuiFreeformImpl.getSize(MiuiFreeformImpl.java:53)
+ at android.util.MiuiFreeformUtils.getSize(MiuiFreeformUtils.java:49)
+ at android.view.Display.getSize(Display.java:796)
+ at com.android.commands.uiautomator.DumpCommand.run(DumpCommand.java:110)
+ at com.android.commands.uiautomator.Launcher.main(Launcher.java:83)
+ at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
+ at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:363)
+Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
+ at libcore.io.Linux.open(Native Method)
+ at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
+ at libcore.io.BlockGuardOs.open(BlockGuardOs.java:274)
+ at libcore.io.IoBridge.open(IoBridge.java:560)
+ ... 22 more
\ No newline at end of file
diff --git a/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_miui.txt b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_miui.txt
new file mode 100644
index 00000000..0f34f37a
--- /dev/null
+++ b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_miui.txt
@@ -0,0 +1,31 @@
+java.io.FileNotFoundException: /data/system/theme_config/theme_compatibility.xml: open failed: ENOENT (No such file or directory)
+ at libcore.io.IoBridge.open(IoBridge.java:574)
+ at java.io.FileInputStream.(FileInputStream.java:160)
+ at java.io.FileInputStream.(FileInputStream.java:115)
+ at java.io.FileReader.(FileReader.java:60)
+ at miui.content.res.ThemeCompatibilityLoader.getVersion(ThemeCompatibilityLoader.java:108)
+ at miui.content.res.ThemeCompatibilityLoader.getConfigDocumentTree(ThemeCompatibilityLoader.java:126)
+ at miui.content.res.ThemeCompatibilityLoader.loadConfig(ThemeCompatibilityLoader.java:59)
+ at miui.content.res.ThemeCompatibility.(ThemeCompatibility.java:31)
+ at miui.content.res.ThemeCompatibility.isThemeEnabled(ThemeCompatibility.java:111)
+ at android.content.res.MiuiResourcesImpl.(MiuiResourcesImpl.java:41)
+ at android.content.res.MiuiResources.(MiuiResources.java:58)
+ at android.content.res.IMiuiResourceImpl.createResources(IMiuiResourceImpl.java:13)
+ at android.content.res.ThemeManagerStub.createMiuiResources(ThemeManagerStub.java:56)
+ at android.content.res.Resources.getSystem(Resources.java:235)
+ at android.util.MiuiMultiWindowAdapter.(MiuiMultiWindowAdapter.java:81)
+ at android.util.MiuiMultiWindowAdapter.getSize(MiuiMultiWindowAdapter.java:305)
+ at com.xiaomi.freeform.MiuiFreeformImpl.getSize(MiuiFreeformImpl.java:53)
+ at android.util.MiuiFreeformUtils.getSize(MiuiFreeformUtils.java:49)
+ at android.view.Display.getSize(Display.java:796)
+ at com.android.commands.uiautomator.DumpCommand.run(DumpCommand.java:110)
+ at com.android.commands.uiautomator.Launcher.main(Launcher.java:83)
+ at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
+ at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:363)
+Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
+ at libcore.io.Linux.open(Native Method)
+ at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
+ at libcore.io.BlockGuardOs.open(BlockGuardOs.java:274)
+ at libcore.io.IoBridge.open(IoBridge.java:560)
+ ... 22 more
+UI hierchary dumped to: /dev/tty
\ No newline at end of file
diff --git a/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_miui_clean.txt b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_miui_clean.txt
new file mode 100644
index 00000000..2c583156
--- /dev/null
+++ b/AdvancedSharpAdbClient.Tests/Assets/dumpscreen_miui_clean.txt
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/AdvancedSharpAdbClient/AdbClient.Async.cs b/AdvancedSharpAdbClient/AdbClient.Async.cs
index f192516d..c3c6bbe9 100644
--- a/AdvancedSharpAdbClient/AdbClient.Async.cs
+++ b/AdvancedSharpAdbClient/AdbClient.Async.cs
@@ -14,6 +14,7 @@
using System.Net;
using System.Runtime.CompilerServices;
using System.Text;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Xml;
@@ -661,9 +662,20 @@ public async Task DumpScreenStringAsync(DeviceData device, CancellationT
await socket.SendAdbRequestAsync("shell:uiautomator dump /dev/tty", cancellationToken);
AdbResponse response = await socket.ReadAdbResponseAsync(cancellationToken);
using StreamReader reader = new(socket.GetShellStream(), Encoding);
- string xmlString = await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
- xmlString = xmlString.Replace("Events injected: 1\r\n", "").Replace("UI hierchary dumped to: /dev/tty", "").Trim();
- return xmlString;
+ string xmlString = reader.ReadToEnd()
+ .Replace("Events injected: 1\r\n", string.Empty)
+ .Replace("UI hierchary dumped to: /dev/tty", string.Empty)
+ .Trim();
+ if (string.IsNullOrEmpty(xmlString) || xmlString.StartsWith("
@@ -671,9 +683,7 @@ public async Task DumpScreenAsync(DeviceData device, CancellationTo
{
XmlDocument doc = new();
string xmlString = await DumpScreenStringAsync(device, cancellationToken);
- if (!string.IsNullOrEmpty(xmlString)
- && !xmlString.StartsWith("ERROR", StringComparison.OrdinalIgnoreCase)
- && !xmlString.StartsWith("java.lang."))
+ if (!string.IsNullOrEmpty(xmlString))
{
doc.LoadXml(xmlString);
return doc;
@@ -687,9 +697,7 @@ public async Task DumpScreenAsync(DeviceData device, CancellationTo
{
Windows.Data.Xml.Dom.XmlDocument doc = new();
string xmlString = await DumpScreenStringAsync(device, cancellationToken);
- if (!string.IsNullOrEmpty(xmlString)
- && !xmlString.StartsWith("ERROR", StringComparison.OrdinalIgnoreCase)
- && !xmlString.StartsWith("java.lang."))
+ if (!string.IsNullOrEmpty(xmlString))
{
doc.LoadXml(xmlString);
return doc;
diff --git a/AdvancedSharpAdbClient/AdbClient.cs b/AdvancedSharpAdbClient/AdbClient.cs
index ee47b37e..60b18d81 100644
--- a/AdvancedSharpAdbClient/AdbClient.cs
+++ b/AdvancedSharpAdbClient/AdbClient.cs
@@ -14,6 +14,7 @@
using System.Text;
using System.Threading;
using System.Xml;
+using System.Text.RegularExpressions;
namespace AdvancedSharpAdbClient
{
@@ -767,8 +768,20 @@ public string DumpScreenString(DeviceData device)
socket.SendAdbRequest("shell:uiautomator dump /dev/tty");
AdbResponse response = socket.ReadAdbResponse();
using StreamReader reader = new(socket.GetShellStream(), Encoding);
- string xmlString = reader.ReadToEnd().Replace("Events injected: 1\r\n", "").Replace("UI hierchary dumped to: /dev/tty", "").Trim();
- return xmlString;
+ string xmlString = reader.ReadToEnd()
+ .Replace("Events injected: 1\r\n", string.Empty)
+ .Replace("UI hierchary dumped to: /dev/tty", string.Empty)
+ .Trim();
+ if (string.IsNullOrEmpty(xmlString) || xmlString.StartsWith("
@@ -776,9 +789,7 @@ public XmlDocument DumpScreen(DeviceData device)
{
XmlDocument doc = new();
string xmlString = DumpScreenString(device);
- if (!string.IsNullOrEmpty(xmlString)
- && !xmlString.StartsWith("ERROR", StringComparison.OrdinalIgnoreCase)
- && !xmlString.StartsWith("java.lang.Exception"))
+ if (!string.IsNullOrEmpty(xmlString))
{
doc.LoadXml(xmlString);
return doc;
@@ -792,9 +803,7 @@ public Windows.Data.Xml.Dom.XmlDocument DumpScreenWinRT(DeviceData device)
{
Windows.Data.Xml.Dom.XmlDocument doc = new();
string xmlString = DumpScreenString(device);
- if (!string.IsNullOrEmpty(xmlString)
- && !xmlString.StartsWith("ERROR", StringComparison.OrdinalIgnoreCase)
- && !xmlString.StartsWith("java.lang.Exception"))
+ if (!string.IsNullOrEmpty(xmlString))
{
doc.LoadXml(xmlString);
return doc;
@@ -1073,6 +1082,13 @@ protected static void EnsureDevice(DeviceData device)
throw new ArgumentOutOfRangeException(nameof(device), "You must specific a serial number for the device");
}
}
+
+#if NET7_0_OR_GREATER
+ [GeneratedRegex("<\\?xml(.?)*")]
+ private static partial Regex GetXMLRegex();
+#else
+ private static Regex GetXMLRegex() => new("<\\?xml(.?)*");
+#endif
}
///