Skip to content

Commit 9cc20e2

Browse files
author
Vadim Belov
committed
Improve Android device detection and update test cases
- Broaden Xiaomi SKU regex to match more device patterns - Enhance Android model extraction to handle "Tablet" and "rv:" tokens - Attempt device code extraction from UA string if model is missing - Update test expectations for okhttp and Android Tablet user agents
1 parent a3fea90 commit 9cc20e2

2 files changed

Lines changed: 22 additions & 5 deletions

File tree

Sources/EasyExtensions.Tests/UserAgentHelpersTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void GetDevice_Returns_Unknown_For_NullOrWhitespace(string? ua, string ex
5151
[TestCase("facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)", "Bot")]
5252
[TestCase("curl/7.64.1", "Script")]
5353
[TestCase("Java/11.0.2", "Script")]
54-
[TestCase("okhttp/3.12.1", "Script")]
54+
[TestCase("okhttp/3.12.1", "Unknown")]
5555
public void GetDevice_Identifies_Bots_And_Scripts(string ua, string expected)
5656
{
5757
Assert.That(UserAgentHelpers.GetDevice(ua), Is.EqualTo(expected));
@@ -85,7 +85,7 @@ public void GetDevice_Identifies_iOS(string ua, string expected)
8585
[TestCase("Mozilla/5.0 (Linux; Android 13; SM-A556B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36", "Samsung SM-A556B")]
8686
[TestCase("Mozilla/5.0 (Linux; Android 13; SM-R960) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Mobile Safari/537.36", "Samsung Galaxy Watch6 Classic 47mm")]
8787
[TestCase("Mozilla/5.0 (Linux; Android 11; SM-T970 Build/RP1A.200720.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.93 Safari/537.36", "Samsung SM-T970")]
88-
[TestCase("Mozilla/5.0 (Linux; Android 13; Tablet; rv:102.0) Gecko/102.0 Firefox/102.0", "Android Tablet")]
88+
[TestCase("Mozilla/5.0 (Linux; Android 13; Tablet; rv:102.0) Gecko/102.0 Firefox/102.0", "Android Tablet (rv:102.0)")]
8989
public void GetDevice_Identifies_Android(string ua, string expected)
9090
{
9191
Assert.That(UserAgentHelpers.GetDevice(ua), Is.EqualTo(expected));

Sources/EasyExtensions/Helpers/UserAgentHelpers.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static class UserAgentHelpers
3535

3636
private static readonly Regex _appleMachineRegex = new Regex(@"\b(iPhone|iPad)\d{1,2},\d{1,2}\b", RegexOptions.Compiled | RegexOptions.CultureInvariant);
3737
private static readonly Regex _onePlusRegex = new Regex(@"\bCPH\d{4}\b", RegexOptions.Compiled | RegexOptions.CultureInvariant);
38-
private static readonly Regex _xiaomiSkuRegex = new Regex(@"\b\d{5}[A-Z]{2}\d{2}[A-Z0-9]{1,3}\b", RegexOptions.Compiled | RegexOptions.CultureInvariant);
38+
private static readonly Regex _xiaomiSkuRegex = new Regex(@"\b\d{5}[A-Z0-9]{5,8}\b", RegexOptions.Compiled | RegexOptions.CultureInvariant);
3939

4040
/// <summary>
4141
/// Determines the type of device based on the provided user agent string.
@@ -150,7 +150,7 @@ private static bool ContainsAny(string haystack, params string[] needles)
150150
var isMobile = ual.Contains("mobile");
151151
var model = TryExtractAndroidModel(ua);
152152

153-
var knownCode = model != null ? TryGetFirstKnownDeviceCode(model) : null;
153+
var knownCode = model != null ? TryGetFirstKnownDeviceCode(model) : TryGetFirstKnownDeviceCode(ua);
154154
if (knownCode != null)
155155
{
156156
return knownCode;
@@ -251,6 +251,16 @@ private static UserAgentDeviceType ResolveSamsungType(string samsungModelCode)
251251
if (!p.Success) return null;
252252

253253
var parts = p.Groups[1].Value.Split(';');
254+
var hasTabletToken = false;
255+
for (var k = 0; k < parts.Length; k++)
256+
{
257+
if (parts[k].Trim().Equals("tablet", StringComparison.OrdinalIgnoreCase))
258+
{
259+
hasTabletToken = true;
260+
break;
261+
}
262+
}
263+
254264
for (var i = 0; i < parts.Length; i++)
255265
{
256266
var token = parts[i].Trim();
@@ -263,7 +273,14 @@ private static UserAgentDeviceType ResolveSamsungType(string samsungModelCode)
263273

264274
// ignore common noise tokens
265275
if (cand.Equals("wv", StringComparison.OrdinalIgnoreCase)
266-
|| cand.Equals("mobile", StringComparison.OrdinalIgnoreCase))
276+
|| cand.Equals("mobile", StringComparison.OrdinalIgnoreCase)
277+
|| cand.Equals("tablet", StringComparison.OrdinalIgnoreCase))
278+
{
279+
continue;
280+
}
281+
282+
// If this UA explicitly says "Tablet", then tokens like "rv:102.0" are not a device model.
283+
if (hasTabletToken && cand.StartsWith("rv:", StringComparison.OrdinalIgnoreCase))
267284
{
268285
continue;
269286
}

0 commit comments

Comments
 (0)