Version_iOS.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. using System;
  2. using System.Json;
  3. using System.Net.Http;
  4. using Foundation;
  5. using System.Threading.Tasks;
  6. using System.Text.RegularExpressions;
  7. using System.Globalization;
  8. [assembly: Xamarin.Forms.Dependency(typeof(InABox.Mobile.iOS.Version_iOS))]
  9. namespace InABox.Mobile.iOS
  10. {
  11. internal static class iOS_VersionExtensions
  12. {
  13. public static string MakeSafeForAppStoreShortLinkUrl(this string value)
  14. {
  15. // Reference: https://developer.apple.com/library/content/qa/qa1633/_index.html
  16. var regex = new Regex(@"[©™®!¡""#$%'()*+,\\\-.\/:;<=>¿?@[\]^_`{|}~]*");
  17. var safeValue = regex.Replace(value, "")
  18. .Replace(" ", "")
  19. .Replace("&", "and")
  20. .ToLower();
  21. return safeValue;
  22. }
  23. }
  24. /// <summary>
  25. /// <see cref="ILatestVersion"/> implementation for iOS.
  26. /// </summary>
  27. public class Version_iOS : IAppVersion
  28. {
  29. string _bundleName => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleName").ToString();
  30. string _bundleIdentifier => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleIdentifier").ToString();
  31. string _bundleVersion => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleShortVersionString").ToString();
  32. JsonValue _appstoreInfo = null;
  33. /// <inheritdoc />
  34. public string InstalledVersionNumber
  35. {
  36. get => _bundleVersion;
  37. }
  38. private async Task CheckAppStoreInfo(string appName)
  39. {
  40. if (_appstoreInfo != null)
  41. return;
  42. var url = $"http://itunes.apple.com/lookup?bundleId={appName}";
  43. using (var request = new HttpRequestMessage(HttpMethod.Get, url))
  44. {
  45. using (var handler = new HttpClientHandler())
  46. {
  47. handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
  48. {
  49. //bypass
  50. return true;
  51. };
  52. using (var client = new HttpClient(handler))
  53. {
  54. using (var responseMsg = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead))
  55. {
  56. if (!responseMsg.IsSuccessStatusCode)
  57. {
  58. throw new LatestVersionException($"Error connecting to the App Store. Url={url}.");
  59. }
  60. try
  61. {
  62. var content = responseMsg.Content == null ? null : await responseMsg.Content.ReadAsStringAsync();
  63. _appstoreInfo = JsonValue.Parse(content);
  64. }
  65. catch (Exception e)
  66. {
  67. throw new LatestVersionException($"Error parsing content from the App Store. Url={url}.", e);
  68. }
  69. }
  70. }
  71. }
  72. }
  73. }
  74. /// <inheritdoc />
  75. public async Task<bool> IsUsingLatestVersion()
  76. {
  77. string latestversion = string.Empty;
  78. try
  79. {
  80. latestversion = await GetLatestVersionNumber();
  81. return Version.Parse(latestversion).CompareTo(Version.Parse(_bundleVersion)) <= 0;
  82. }
  83. catch (Exception e)
  84. {
  85. throw new LatestVersionException($"Error comparing current app version number with latest. Bundle version={_bundleVersion} and lastest version={latestversion} .", e);
  86. }
  87. }
  88. /// <inheritdoc />
  89. public async Task<string> GetLatestVersionNumber()
  90. {
  91. return await GetLatestVersionNumber(_bundleIdentifier);
  92. }
  93. /// <inheritdoc />
  94. public async Task<string> GetLatestVersionNumber(string appName)
  95. {
  96. if (string.IsNullOrWhiteSpace(appName))
  97. {
  98. throw new ArgumentNullException(nameof(appName));
  99. }
  100. await CheckAppStoreInfo(appName);
  101. var version = _appstoreInfo["results"][0]["version"];
  102. return version;
  103. }
  104. /// <inheritdoc />
  105. public Task OpenAppInStore()
  106. {
  107. return OpenAppInStore(_bundleName);
  108. }
  109. /// <inheritdoc />
  110. public Task OpenAppInStore(string appName)
  111. {
  112. if (string.IsNullOrWhiteSpace(appName))
  113. {
  114. throw new ArgumentNullException(nameof(appName));
  115. }
  116. try
  117. {
  118. var location = RegionInfo.CurrentRegion.Name.ToLower();
  119. var trackid = _appstoreInfo["results"][0]["trackId"];
  120. var url = String.Format("https://itunes.apple.com/{0}/app/{1}/id{2}?mt=8",location,appName,trackid);
  121. //appName = appName.MakeSafeForAppStoreShortLinkUrl();
  122. #if __IOS__
  123. UIKit.UIApplication.SharedApplication.OpenUrl(new NSUrl(url)); // $"http://appstore.com/{appName}"));
  124. #elif __MACOS__
  125. AppKit.NSWorkspace.SharedWorkspace.OpenUrl(new NSUrl($"http://appstore.com/mac/{appName}"));
  126. #endif
  127. return Task.FromResult(true);
  128. }
  129. catch (Exception e)
  130. {
  131. throw new LatestVersionException($"Unable to open {appName} in App Store.", e);
  132. }
  133. }
  134. }
  135. }