Xamarin Forms中Xam.Plugin.LatestVersion插件异常求助
问题概述
在Xamarin Forms应用中使用Xam.Plugin.LatestVersion插件时,仅Android平台出现版本对比异常;更新至2.1.0版本后问题未解决,尝试2.1.1-beta.107版本后出现Play Store内容解析异常。
初始异常信息
Plugin.LatestVersion.LatestVersionException: Error comparing current app version number with latest.
更新版本后的异常信息
Plugin.LatestVersion.LatestVersionException: Error parsing content from the Play Store. Url=play store url&hl=en. ---> Jurassic.JavaScriptException: TypeError: undefined cannot be converted to an object
at Jurassic.TypeConverter.ToObject (Jurassic.ScriptEngine engine, System.Object value, System.Int32 lineNumber, System.String sourcePath, System.String functionName) [0x00037] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at (wrapper dynamic-method) Jurassic.Compiler.MethodGenerator.anonymous(Jurassic.Compiler.ExecutionContext,object[])
at Jurassic.Library.UserDefinedFunction.CallLateBound (System.Object thisObject, System.Object[] argumentValues) [0x00014] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at Jurassic.Library.FunctionInstance.CallWithStackTrace (System.String path, System.String function, System.Int32 line, System.Object thisObject, System.Object[] argumentValues) [0x0000f] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at (wrapper dynamic-method) Jurassic.Compiler.MethodGenerator.anonymous(Jurassic.Compiler.ExecutionContext,object[])
at Jurassic.Library.UserDefinedFunction.CallLateBound (System.Object thisObject, System.Object[] argumentValues) [0x00014] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at Jurassic.Library.FunctionInstance.CallWithStackTrace (System.String path, System.String function, System.Int32 line, System.Object thisObject, System.Object[] argumentValues) [0x0000f] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at (wrapper dynamic-method) Jurassic.Compiler.MethodGenerator.eval(Jurassic.Compiler.ExecutionContext)
at Jurassic.Compiler.GlobalOrEvalMethodGenerator.Execute (Jurassic.ScriptEngine engine, Jurassic.Compiler.RuntimeScope parentScope, System.Object thisObject) [0x00030] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at Jurassic.ScriptEngine.Evaluate (Jurassic.ScriptSource source) [0x000a7] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at Jurassic.ScriptEngine.Evaluate (System.String code) [0x00007] in <018e8bf6db3d46cd85eb0a9bc95f4b3f>:0
at Plugin.LatestVersion.LatestVersionImplementation.GetLatestVersionNumber () [0x001ff] in <7361502664264164a28b556feec777a7>:0
--- End of inner exception stack trace ---
at Plugin.LatestVersion.LatestVersionImplementation.GetLatestVersionNumber () [0x0023d] in <7361502664264164a28b556feec777a7>:0
解决方案
方案1:自定义版本解析与对比逻辑
跳过插件内部的版本对比,手动获取并解析Play Store版本号:
try { // 尝试使用插件获取版本号 var latestVersion = await CrossLatestVersion.Current.GetLatestVersionNumber(); var currentVersion = CrossLatestVersion.Current.InstalledVersionNumber; // 自定义版本对比逻辑,适配非标准版本号格式 if (CompareVersions(currentVersion, latestVersion) < 0) { // 提示用户更新应用 await CrossLatestVersion.Current.ShowAppInStore(); } } catch (LatestVersionException) { // 插件失败时,手动请求Play Store页面提取版本号 using (var httpClient = new HttpClient()) { string appPackageName = "com.your.app.package"; // 替换为你的应用包名 string playStoreUrl = $"https://play.google.com/store/apps/details?id={appPackageName}&hl=en"; string htmlContent = await httpClient.GetStringAsync(playStoreUrl); // 正则表达式提取版本号 var versionMatch = System.Text.RegularExpressions.Regex.Match(htmlContent, @"softwareVersion"":""([\d\.]+)"""); if (versionMatch.Success) { string latestVersion = versionMatch.Groups[1].Value; string currentVersion = CrossLatestVersion.Current.InstalledVersionNumber; if (CompareVersions(currentVersion, latestVersion) < 0) { await CrossLatestVersion.Current.ShowAppInStore(); } } } } // 自定义版本对比方法,支持多段版本号 private int CompareVersions(string current, string latest) { var currentParts = current.Split('.').Select(int.Parse).ToList(); var latestParts = latest.Split('.').Select(int.Parse).ToList(); int maxLength = Math.Max(currentParts.Count, latestParts.Count); for (int i = 0; i < maxLength; i++) { int currentVal = i < currentParts.Count ? currentParts[i] : 0; int latestVal = i < latestParts.Count ? latestParts[i] : 0; if (currentVal != latestVal) { return currentVal.CompareTo(latestVal); } } return 0; }
方案2:使用Google Play Developer API(稳定方案)
依赖官方API获取版本号,避免网页解析的不稳定:
- 在Google Cloud Console创建项目,启用Google Play Developer API,生成服务账号密钥(JSON格式)。
- 在Xamarin Android项目中安装
Google.Apis.AndroidPublisher.v3和Google.Apis.AuthNuGet包。 - 编写代码获取最新版本:
using Google.Apis.AndroidPublisher.v3; using Google.Apis.Auth.OAuth2; using Google.Apis.Services; // 初始化服务 var credential = GoogleCredential.FromFile("service-account-key.json") .CreateScoped(AndroidPublisherService.Scope.Androidpublisher); var service = new AndroidPublisherService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = "Your App Name" }); // 获取生产渠道的最新版本 string packageName = "com.your.app.package"; var trackRequest = service.Edits.Tracks.Get(packageName, "production", "production"); var track = await trackRequest.ExecuteAsync(); var latestVersionCode = track.Releases?.FirstOrDefault()?.VersionCodes?.Max(); if (latestVersionCode != null) { // 对比本地版本号(需将本地版本号转为int) int currentVersionCode = int.Parse(CrossLatestVersion.Current.InstalledVersionNumber.Replace(".", "")); if (latestVersionCode > currentVersionCode) { await CrossLatestVersion.Current.ShowAppInStore(); } }
方案3:降级插件版本并规范版本号格式
如果坚持使用插件,尝试降级到1.2.0版本(该版本的版本对比逻辑更简洁),同时确保:
- 应用版本号为标准的
x.y.z格式,不含预发布标签(如beta、alpha)。 - 本地版本号与Play Store上的版本号格式完全一致。
内容的提问来源于stack exchange,提问作者Sreejith Sree

