Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[monodroid]
AndroidEnablePreloadAssemblies
causes runtime crash. (#…
…5883) Context: #5838 Setting `$(AndroidEnablePreloadAssemblies)`=False, which disables assembly preloading (see af02a65), could result in a crash when: 1. The launched `Activity` isn't located within the "main App assembly", the assembly built as part of the `App.apk` build, and 2. The launched `Activity` uses Android Resource IDs, and 3. Those Android Resource IDs differ between the Library project build and the Application project build (usually the case). This setup is exemplified by the `DebuggingTest.ClassLibraryMainLauncherRuns()` unit test. Our current Resource architecture assumes/ensures that there is Only One™ `Resource` type mentioned by an assembly-level `ResourceDesignerAttribute` custom attribute, with `ResourceDesignerAttribute.IsApplication`=true: [assembly: global::Android.Runtime.ResourceDesignerAttribute("My.Resource", IsApplication=true)] The `ResourceIdManager.UpdateIdValues()` method looks for this attribute in all loaded assemblies, and when (if) found, will invoke the `UpdateIdValues()` static method on the specified type. The problem is that only the *App assembly* `Resource.UpdateIdValues()` method does anything, and if the App assembly isn't loaded -- which may be the case when the `Activity` loaded isn't from the App assembly and assembly preload is disabled -- then: 1. `ResourceIdManager.UpdateIdValues()` never finds the `ResourceDesignerAttribute`, and 2. `Resource.UpdateIdValues()` is never invoked, and 3. Android Resource IDs in non-App assemblies are never updated to contain their correct values. Thus, attempting to use an Android resource may result in unexpected failures: var button = FindViewById<Button> (Resource.Id.myButton); // `button` is null, because `Resource.Id.myButton` has the wrong value. This can result in `NullReferenceException`s: android.runtime.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object at MyLibrary.MainActivity.OnCreate(Bundle bundle) at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_(IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) at com.xamarin.classlibrarymainlauncherruns.MainActivity.n_onCreate(Native Method) at com.xamarin.classlibrarymainlauncherruns.MainActivity.onCreate(MainActivity.java:29) Fix this by *always* loading the App assembly during process startup, which also happens to be the *first* assembly listed within the generated `mono.MonoPackageManager_Resources.Assemblies` array, which is provided to `Runtime.initInternal()`.
- Loading branch information