我们已经有一个移动应用程序(适用于iOS和Android的Xamarin.Forms),我们一直在从我们的内部部署Team Foundation Server(TFS)迁移到Visual Studio Team Services( VSTS)。在过去的几个月里,我们已经在VSTS中托管了我们的代码,但是已经通过我们的内部部署TFS对各个商店进行了构建和发布。上周晚些时候,我还将构建和发布定义迁移到了VSTS,现在我们在VSTS中完成了整个过程。
或者我认为......因为,虽然iOS构建和发布工作正常,并且Android构建和发布也是如此,但 Android应用程序现在在您尝试运行时崩溃。代码中没有发生重大(读取:否)更改,HockeyApp和我们应用程序自己的错误日志都无法记录崩溃的原因 - Google Developer Console也没有为我们提供任何见解物。经过几次尝试后,我能够从Logcat中获得以下异常:
I/MonoDroid(21970): UNHANDLED EXCEPTION:
I/MonoDroid(21970): System.ArgumentException: element is not of type Xamarin.Forms.View
I/MonoDroid(21970): Parameter name: element
I/MonoDroid(21970): at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[TElement].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x0001c] in <fa196d4afd1b4356b38d6cf3bb1e4df8>:0
I/MonoDroid(21970): at Xamarin.Forms.Platform.Android.Platform.CreateRenderer (Xamarin.Forms.VisualElement element, Android.Support.V4.App.FragmentManager fragmentManager, Android.Content.Context context) [0x00031] in <fa196d4afd1b4356b38d6cf3bb1e4df8>:0
I/MonoDroid(21970): at Xamarin.Forms.Platform.Android.AppCompat.FragmentContainer.OnCreateView (Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState) [0x0001b] in <fa196d4afd1b4356b38d6cf3bb1e4df8>:0
I/MonoDroid(21970): at Android.Support.V4.App.Fragment.n_OnCreateView_Landroid_view_LayoutInflater_Landroid_view_ViewGroup_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_inflater, System.IntPtr native_container, System.IntPtr native_savedInstanceState) [0x00020] in <20045e457c414d37bc46e447a5bb3bb5>:0
I/MonoDroid(21970): at (wrapper dynamic-method) System.Object.b09cff61-6f2e-471d-b43a-8d2949513eb7(intptr,intptr,intptr,intptr,intptr)
现在我们的代码中只有一个地方使用片段,我们使用自定义渲染器来扩展我们使用的BottomBarPage
的默认实现,而不是Xamarin的默认实现TabbedPage
。因此,我尝试关闭此功能的构建(使用默认的TabbedPage
而不是BottomBarPage
并删除ExportRenderer
- 属性),但这并没有解决问题。当然,我也在线查看我是否可以将错误消息与其他人可能遇到的任何问题进行匹配。结果似乎相当微弱,并不是特别适用于我的情况:install the latest version of Xamarin.Forms(我们目前无法做到 - 除了事情正在我们的私人构建服务器上工作)或做clean and rebuild(我实际上尝试打开我们的Xamarin.Android任务中的Clean
- 选项,但没有效果。)
因此,我继续将TFS的最后一个构建日志与VSTS中的最新构建日志进行比较,看看是否能找到任何重大差异。由于两个构建定义之间的输出明显不同,因此结果相当棘手。从表面上看,它们看起来都是一样的,执行相同的任务。然而,我注意到我们自己的Mac构建服务器使用了比VSTS Hosted Mac更新版本的MS Build和Android Build Tools(分别为15.6.0.0和15.4.0.0以及27.0.1和23.0.0),所以我决定改变构建环境,因为似乎没有办法影响构建环境的这些部分,并且当没有明确指定时,将使用最高安装版本的Android Build Tools(根据https://docs.microsoft.com/en-us/xamarin/android/deploy-test/building-apps/build-process )。在VS2017上运行现在托管至少给了我Android Build Tools版本27.0.3。顺便说一句,JDK版本在所有环境中都是相同的。
由于构建环境中的切换也无法解决问题,我接下来尝试了以下内容:
Mono.Data.Tds.dll
- 和System.Runtime.InteropServices.RuntimeInformation.dll
- 程序集) 只有后者 - 包装比较 - 我发现信息丰富,但我不知道。也就是说,人们会期望包含完全相同的代码和资源文件的包在它们之间几乎没有区别,除了Android-manifest中的版本号。事实上,这正是我所看到的资产和资源。但是,显着(至少在我看来),META-INF
,lib
,classes.dex
,assemblies
和typemap
- 文件的大小各不相同。我不清楚这意味着什么,但是......
现在大约1.5天,到目前为止唯一有希望的结果是Stack Overflow上的another post,它似乎描述了我们遇到的相同症状,但在他们的logcat中报告了不同的异常消息。但是,没有公布决议。
在比较TFS上构建的Android-manifest与VSTS上构建的Android-manifest之间时,我注意到的一件事是application
- 节点缺少以下metadata在VSTS上构建(但在本地[debug-]版本中存在):
<meta-data
android:name="android.support.VERSION"
android:value="26.1.0" />
我不确定哪个软件包添加了这个节点及其功能,但是感觉它可能很重要,并会进一步调查。
经过漫长的一天的挫折之后,尝试各种不同的库组合(其中一些似乎不想安装在.NetStandard项目上,VS2017默认为移动应用程序而不是旧PCL创建),我设法缩小了Android-manifest中上述条目的来源:显然这是版本26.1.0 Xamarin Android支持库添加的内容。事实证明,我们的应用程序使用的三个Android项目之一的CS-project-file 中提到的 Xamarin Android支持库之一仍然指向旧的26.1.0.1版本,而所有其他参考文献已更新至27.0.2。手动更改此条目可确保Android-manifest中的条目消失。然而,遗憾的是,这并没有解决我们的应用程序的Android版本的构建问题...
在托管的VS2017环境上构建现在会产生以下异常消息:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(2374):C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(2374,3): Error : error XA5101: Missing Android NDK toolchains directory '\toolchains'. Please install the Android NDK. at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainDirectories(String toolchainsPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainPath(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkTool(String androidNdkPath, AndroidTargetArch arch, String tool) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolPrefix(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.Aot.<GetAotConfigs>d__73.MoveNext() at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerable.GrabChunk_Buffered(KeyValuePair`2[] destArray, Int32 requestedChunkSize, Int32& actualNumElementsGrabbed) at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerator.GrabNextChunk(Int32 requestedChunkSize) at System.Collections.Concurrent.Partitioner.DynamicPartitionEnumerator_Abstract`2.MoveNext() at System.Threading.Tasks.Parallel.<>c__DisplayClass42_0`2.<PartitionerForEachWorker>b__1() at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask) at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(2374):C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(2374,3): Error XA3001: System.AggregateException: One or more errors occurred. ---> System.AggregateException: One or more errors occurred. ---> Java.Interop.Tools.Diagnostics.XamarinAndroidException: error XA5101: Missing Android NDK toolchains directory '\toolchains'. Please install the Android NDK. at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainDirectories(String toolchainsPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainPath(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkTool(String androidNdkPath, AndroidTargetArch arch, String tool) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolPrefix(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.Aot.<GetAotConfigs>d__73.MoveNext() at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerable.GrabChunk_Buffered(KeyValuePair`2[] destArray, Int32 requestedChunkSize, Int32& actualNumElementsGrabbed) at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerator.GrabNextChunk(Int32 requestedChunkSize) at System.Collections.Concurrent.Partitioner.DynamicPartitionEnumerator_Abstract`2.MoveNext() at System.Threading.Tasks.Parallel.<>c__DisplayClass42_0`2.<PartitionerForEachWorker>b__1() at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask) at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object ) --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.Wait() at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally) at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally) at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body) at Xamarin.Android.Tasks.Aot.RunParallelAotCompiler(List`1 nativeLibs) at Xamarin.Android.Tasks.Aot.<>c__DisplayClass71_0.<DoExecute>b__0() at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.Execute() --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task`1.get_Result() at Xamarin.Android.Tasks.Aot.DoExecute() at Xamarin.Android.Tasks.Aot.Execute() ---> (Inner Exception #0) System.AggregateException: One or more errors occurred. ---> Java.Interop.Tools.Diagnostics.XamarinAndroidException: error XA5101: Missing Android NDK toolchains directory '\toolchains'. Please install the Android NDK. at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainDirectories(String toolchainsPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainPath(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkTool(String androidNdkPath, AndroidTargetArch arch, String tool) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolPrefix(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.Aot.<GetAotConfigs>d__73.MoveNext() at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerable.GrabChunk_Buffered(KeyValuePair`2[] destArray, Int32 requestedChunkSize, Int32& actualNumElementsGrabbed) at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerator.GrabNextChunk(Int32 requestedChunkSize) at System.Collections.Concurrent.Partitioner.DynamicPartitionEnumerator_Abstract`2.MoveNext() at System.Threading.Tasks.Parallel.<>c__DisplayClass42_0`2.<PartitionerForEachWorker>b__1() at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask) at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object ) --- End of inner exception stack trace --- at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) at System.Threading.Tasks.Task.Wait() at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally) at System.Threading.Tasks.Parallel.ForEachWorker[TSource,TLocal](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally) at System.Threading.Tasks.Parallel.ForEach[TSource](IEnumerable`1 source, ParallelOptions parallelOptions, Action`1 body) at Xamarin.Android.Tasks.Aot.RunParallelAotCompiler(List`1 nativeLibs) at Xamarin.Android.Tasks.Aot.<>c__DisplayClass71_0.<DoExecute>b__0() at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.Execute() ---> (Inner Exception #0) Java.Interop.Tools.Diagnostics.XamarinAndroidException: error XA5101: Missing Android NDK toolchains directory '\toolchains'. Please install the Android NDK. at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainDirectories(String toolchainsPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolchainPath(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.NdkUtil.GetNdkTool(String androidNdkPath, AndroidTargetArch arch, String tool) at Xamarin.Android.Tasks.NdkUtil.GetNdkToolPrefix(String androidNdkPath, AndroidTargetArch arch) at Xamarin.Android.Tasks.Aot.<GetAotConfigs>d__73.MoveNext() at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerable.GrabChunk_Buffered(KeyValuePair`2[] destArray, Int32 requestedChunkSize, Int32& actualNumElementsGrabbed) at System.Collections.Concurrent.Partitioner.DynamicPartitionerForIEnumerable`1.InternalPartitionEnumerator.GrabNextChunk(Int32 requestedChunkSize) at System.Collections.Concurrent.Partitioner.DynamicPartitionEnumerator_Abstract`2.MoveNext() at System.Threading.Tasks.Parallel.<>c__DisplayClass42_0`2.<PartitionerForEachWorker>b__1() at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask) at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object )<--- <---
Process 'msbuild.exe' exited with code '1'.
我不是 - 据我所知 - 使用Android NDK,所以我不太明白为什么我现在收到此异常消息。但是,VSTS托管的Mac环境似乎还没有遇到这些问题,所以我将切换回在Mac上构建。
进行了一些搜索,显然上述异常消息是由于最近发生的版本15.6到版本15.7的Visual Studio自动更新问题(source)。总是很高兴看到这些东西被检查全球推出。
以上是自上次更新以来我尝试的其他一些事项:将Xamarin.Android使用的JDK版本明确设置为版本8 ,将JDK架构设置为 x64 (如here所述);并删除Android的所有自定义渲染器,因为原始异常似乎指向VisualElementRenderer<TElement>
,这是几乎所有(如果不是全部)默认和自定义渲染器的基类。但是,所有这些都没有用,所以我怀疑抛出的异常来自于Xamarin.Forms本身。
我们终于尝试将我们用于TFS内部构建流程的Mac作为私有构建代理添加到VSTS,这是一件非常容易的事情!我们甚至不需要更改防火墙配置,因为代理似乎与服务器建立连接(跨HTTP和HTTPS),而不是相反(我们按照here描述的步骤)。我希望所有装置都这么简单!
尽管我们配置私有构建代理很容易,但无论我们是使用Xamarin.Android构建任务还是我们之前在之后使用的自定义构建脚本构建的,我们仍然会在构建后遇到相同的崩溃。与TFS内部完全相同的机器成功)。
我们最终通过跟进here提出的建议进入了解决方案,然而,这些建议似乎有些不相关且之前并不相关。然而,正如我刚才从版本2.5.1.444934更新我们的Xamarin.Forms 的版本到前一版本的2.5.1.527436版本,我决定尝试使用此代码运行构建。结果发挥了作用!我不知道为什么......但我认为这不如能够再次建造那么重要!
答案 0 :(得分:0)
事实证明,更新Xamarin.Forms是解决方案。
虽然建议在Xamarin forums上解决与我们相同的错误,以及我之前遇到过的事情,但是帖子的年龄和旧版本的Xamarin.Forms让我忽略了这个选项与我们的问题有关。什么没有帮助的是我认为我们已经在Xamarin.Forms 2.5.1的最高版本,并且还没有准备好转移到Xamarin.Forms 3.0。然而,昨天,我发现仍然有一个版本,我们可以在2.5.1分支内升级,这就是我所做的。然后,当我尝试使用此代码进行构建时,令人惊讶的是,生成的APK结果没有任何问题!
但是,更新Xamarin.Forms的原因尚不清楚。但是,我们确实观察到这个特定版本的 Xamarin.Forms,2.5.1.527436 ,在我将构建定义从TFS迁移到VSTS之前大约一周发布。因此可能存在一些相关性。
今天使用Xamarin.Forms 2.5.1.527436遇到了一些问题,最终导致我最有可能导致我们在创建App的Android版本时遇到问题。也就是说,为了解决由Xamarin.Forms引起的崩溃,我试图将Forms恢复到我知道仍然有效的最后一个版本。然而,即使在降级之后,Xamarin.Forms的问题仍然存在。这引发了我检查项目文件,并将应用程序的工作版本与已降级的应用程序进行比较,但尽管如此,应该已经达到了相同的效果。
事实证明某些项目文件引用了两个不同版本的Xamarin.Forms :我打算使用的那个,以及我们之前使用过的那个。现在这种混合物在本地开发机器上运行时没有造成任何问题,因为这台机器将安装新旧版本的Xamarin.Forms,因此不会有任何丢失的程序集。但是,我可以想象在构建服务器上运行VSTS构建时不会出现这种情况。此外,包含不正确的程序集引用的项目文件都是Android项目 - 这解释了为什么iOS构建没有问题......!