using System; using System.Json; using System.Net.Http; using System.Collections.Generic; using System.Linq; using System.Net; using System.IO; using Foundation; using UIKit; using Xamarin.Forms; using System.Threading.Tasks; using System.Text.RegularExpressions; using System.Globalization; [assembly: Xamarin.Forms.Dependency(typeof(InABox.Mobile.iOS.Version_iOS))] namespace InABox.Mobile.iOS { internal static class iOS_VersionExtensions { public static string MakeSafeForAppStoreShortLinkUrl(this string value) { // Reference: https://developer.apple.com/library/content/qa/qa1633/_index.html var regex = new Regex(@"[©™®!¡""#$%'()*+,\\\-.\/:;<=>¿?@[\]^_`{|}~]*"); var safeValue = regex.Replace(value, "") .Replace(" ", "") .Replace("&", "and") .ToLower(); return safeValue; } } /// /// implementation for iOS. /// public class Version_iOS : IAppVersion { string _bundleName => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleName").ToString(); string _bundleIdentifier => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleIdentifier").ToString(); string _bundleVersion => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleShortVersionString").ToString(); JsonValue _appstoreInfo = null; /// public string InstalledVersionNumber { get => _bundleVersion; } private async Task CheckAppStoreInfo(string appName) { if (_appstoreInfo != null) return; var url = $"http://itunes.apple.com/lookup?bundleId={appName}"; using (var request = new HttpRequestMessage(HttpMethod.Get, url)) { using (var handler = new HttpClientHandler()) { handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { //bypass return true; }; using (var client = new HttpClient(handler)) { using (var responseMsg = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead)) { if (!responseMsg.IsSuccessStatusCode) { throw new LatestVersionException($"Error connecting to the App Store. Url={url}."); } try { var content = responseMsg.Content == null ? null : await responseMsg.Content.ReadAsStringAsync(); _appstoreInfo = JsonValue.Parse(content); } catch (Exception e) { throw new LatestVersionException($"Error parsing content from the App Store. Url={url}.", e); } } } } } } /// public async Task IsUsingLatestVersion() { string latestversion = string.Empty; try { latestversion = await GetLatestVersionNumber(); return Version.Parse(latestversion).CompareTo(Version.Parse(_bundleVersion)) <= 0; } catch (Exception e) { throw new LatestVersionException($"Error comparing current app version number with latest. Bundle version={_bundleVersion} and lastest version={latestversion} .", e); } } /// public async Task GetLatestVersionNumber() { return await GetLatestVersionNumber(_bundleIdentifier); } /// public async Task GetLatestVersionNumber(string appName) { if (string.IsNullOrWhiteSpace(appName)) { throw new ArgumentNullException(nameof(appName)); } await CheckAppStoreInfo(appName); var version = _appstoreInfo["results"][0]["version"]; return version; } /// public Task OpenAppInStore() { return OpenAppInStore(_bundleName); } /// public Task OpenAppInStore(string appName) { if (string.IsNullOrWhiteSpace(appName)) { throw new ArgumentNullException(nameof(appName)); } try { var location = RegionInfo.CurrentRegion.Name.ToLower(); var trackid = _appstoreInfo["results"][0]["trackId"]; var url = String.Format("https://itunes.apple.com/{0}/app/{1}/id{2}?mt=8",location,appName,trackid); //appName = appName.MakeSafeForAppStoreShortLinkUrl(); #if __IOS__ UIKit.UIApplication.SharedApplication.OpenUrl(new NSUrl(url)); // $"http://appstore.com/{appName}")); #elif __MACOS__ AppKit.NSWorkspace.SharedWorkspace.OpenUrl(new NSUrl($"http://appstore.com/mac/{appName}")); #endif return Task.FromResult(true); } catch (Exception e) { throw new LatestVersionException($"Unable to open {appName} in App Store.", e); } } } }