Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing: Type XYZ is defined multiple times || packages generated by more than one managed type #764

Closed
moljac opened this issue Jul 19, 2023 · 6 comments

Comments

@moljac
Copy link
Member

moljac commented Jul 19, 2023

TL:DR - Fixes

If you are seeing a Java compilation error of the form:

Type androidx.lifecycle.DispatchQueue is defined multiple times: ...
Type kotlin.internal.jdk7.JDK7PlatformImplementations is defined multiple times: ...
Type androidx.collection.ArrayMapKt is defined multiple times: ...

Solution 1

This may be fixable by simply updating your NuGet packages to the latest. This is the preferred solution.

Solution 2

This solution adds an explicit <PackageReference> to the needed transitive package version.

Note: You will need to use versions that match the version of the primary package that is referenced.

If the problematic type starts with androidx.lifecycle, add this to your csproj:

<!-- Should match version of the referenced 'Xamarin.AndroidX.Activity' package -->
<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.7.2.1" />

If the problematic type starts with kotlin.internal.jdk7 or kotlin.internal.jdk8, add this to your csproj:

<!-- Should match version of the referenced 'Xamarin.Kotlin.StdLib' package -->
<PackageReference Include="Xamarin.Kotlin.StdLib.Jdk8" Version="1.9.0.1" />

If the problematic type starts with androidx.collection, add this to your csproj:

<!-- Should match version of the referenced 'Xamarin.AndroidX.Collection' package -->
<PackageReference Include="Xamarin.AndroidX.Collection.Jvm" Version="1.4.0.1" />
<PackageReference Include="Xamarin.AndroidX.Collection.Ktx" Version="1.4.0.1" />

How did we get here?

Let's take androidx.lifecycle.DispatchQueue as an example.

The type has always existed in the Java package androidx.lifecycle.lifecycle-runtime-ktx. However, with the 2.6.0 release, Android moved this type to the androidx.lifecycle.lifecycle-common Java package. This is fine if you reference matching versions of the NuGet packages:

  • <PackageReference Include="Xamarin.AndroidX.Lifecycle.Common" Version="2.6.1.3" />
  • <PackageReference Include="Xamarin.AndroidX.Lifecycle.Runtime.Ktx" Version="2.6.1.3" />

However, because these dependencies are referenced by other packages, and NuGet resolves transitive dependencies to the lowest version that satisfies the requirement, you can end up with mismatched references like:

  • <PackageReference Include="Xamarin.AndroidX.Lifecycle.Common" Version="2.6.1.3" />
  • <PackageReference Include="Xamarin.AndroidX.Lifecycle.Runtime.Ktx" Version="2.5.1.1" />

This is not fine, as both packages contain the androidx.lifecycle.DispatchQueue type, resulting in the type being duplicated:

java.exe error JAVA0000: Type androidx.lifecycle.DispatchQueue is defined multiple times: 
  C:\.tools\.nuget\packages\xamarin.androidx.lifecycle.common\2.6.1.3\buildTransitive\net6.0-android31.0\..\..\jar\androidx.lifecycle.lifecycle-common.jar:androidx/lifecycle/DispatchQueue.class, 
  obj\Release\net7.0-android\lp\139\jl\classes.jar:androidx/lifecycle/DispatchQueue.class

Specifically, in MAUI, this occurs because MAUI references Xamarin.AndroidX.Navigation.Common 2.5.2.1, which references Xamarin.AndroidX.Lifecycle.Runtime.Ktx 2.5.1.1:

<PackageReference Include="Xamarin.AndroidX.Navigation.Common" Version="2.5.2.1" />
  -> Xamarin.AndroidX.Lifecycle.Runtime.Ktx (>= 2.5.1.1)  

And the user adds a package like Xamarin.AndroidX.Activity 1.7.2.1 which eventually references Xamarin.AndroidX.Lifecycle.Common 2.6.1.3:

<PackageReference Include="Xamarin.AndroidX.Activity" Version="1.7.2.1" />
  -> Xamarin.AndroidX.Lifecycle.Runtime (>= 2.6.1.3)
     -> Xamarin.AndroidX.Lifecycle.Common (>= 2.6.1.3)

How does Java/Maven handle this?

Java/Maven avoids this issue by requiring an exact version match between androidx.lifecycle.lifecycle-runtime-ktx and androidx.lifecycle.lifecycle-common. That is, the POM file for androidx.lifecycle.lifecycle-runtime-ktx lists its dependency as:

<!-- lifecycle-runtime-ktx-2.6.1.pom -->
<dependency>
  <groupId>androidx.lifecycle</groupId>
  <artifactId>lifecycle-runtime</artifactId>
  <version>[2.6.1]</version>
  <scope>compile</scope>
  <type>aar</type>
</dependency>

The square brackets ([]) denote an exact match, rather than a greater than or equal match.

Our NuGet packages allow greater than or equal match, which allows the version to incorrectly differ from each other.

Long-term fix

In order to handle this long-term and help prevent this issue from recurring when other types move in the future, we need to duplicate Java/Maven's "exact match".

Unfortunately, publishing fixed packages will not make this error go away yet, because the fixed package needs to be referenced by MAUI. After fixed packages are published, MAUI will need to reference them and make a new release.

Thus, we will be living with the issue for a while.

Caveats

Using "exact match" versions will fix the androidx.lifecycle case (and potential future cases), but it will not fix the kotlin.internal case, as the Kotlin POM does not specify an "exact match" for this case:

<!-- kotlin-stdlib-jdk8-1.9.0.pom -->
<dependency>
  <groupId>org.jetbrains.kotlin</groupId>
  <artifactId>kotlin-stdlib</artifactId>
  <version>1.9.0</version>
  <scope>compile</scope>
</dependency>

Original Details

Certain PackageReference constellations can cause 2 errors:

  • type XYZ is defined multiples times
    or
  • packages generated by more than one managed type

Basically, the problem is that maven package authors (Google, JetBrains) move types from version to version, from Maven artifact to another Maven artifact. So, in rare cases even trivial transitive dependencies cause such errors if nugets transitively reference nugets with bindings where the same type rasides, but under different version.

Team does publish "alingment bumps" to put transitive dependencies "in order", but probability for hitting these issues is still high on real world projects, especially with 3rd party libraries that depend on older AndroidX and GooglePlayServices-Firebase-MLKit (not regularly updated).

Workaround steps:

  1. update AndroidX and GooglePlayServices-Firebase-MLKit to the latest
    sometimes updating AndroidX 1st could help, but recommendation is to update all PackageReferences
  2. some users report that they had to close Visual Studio (IDE) and delete bin/ and obj folders, restore and then build

If you still encounter these issues open issue in AndroidX and/or GooglePlayServices-Firebase-MLKit repos and please add list of PackageRererences.

Related/Duplicates:

This issue is project specific (PackagesReferences dependent), so finding workaround is based on experience.

Finding newer issues - search for;

Error JAVA0000 java.exe: Error in Type androidx.collection.ArrayMapKt is defined multiple times

Thus list of the similar issues:

AX (AndroidX)

#861

#805

#797

#752

#749

#747

#742

#717

#634

#525

#509

#505

#756 (comment)

GPD-FB-MLKit (GooglePlayServices, Firebase, ML Kit)

xamarin/GooglePlayServicesComponents#852

xamarin/GooglePlayServicesComponents#475

xamarin/GooglePlayServicesComponents#379

MAUI

dotnet/maui#20561

dotnet/maui#18665

dotnet/maui#18118

dotnet/maui#17935

dotnet/maui#16448

dotnet/maui#14954

dotnet/maui#11353 (comment)

Steps to Reproduce

N/A

Did you find any workaround?

Workaround steps:

  1. update AndroidX and GooglePlayServices-Firebase-MLKit to the latest
    sometimes updating AndroidX 1st could help, but recommendation is to update all PackageReferences
  2. some users report that they had to close Visual Studio (IDE) and delete bin/ and obj folders, restore and then build

Relevant log output

see related issues
@moljac moljac pinned this issue Jul 19, 2023
@moljac moljac changed the title Error: Type XYZ is defined multiples times || packages generated by more than one managed type Error: Type XYZ is defined multiple times || packages generated by more than one managed type Jul 19, 2023
@jpobst jpobst changed the title Error: Type XYZ is defined multiple times || packages generated by more than one managed type Fixing: Type XYZ is defined multiple times || packages generated by more than one managed type Jul 27, 2023
@fedemkr
Copy link

fedemkr commented Jul 28, 2023

We have a Xamarin.Forms app and given that we're having several issues upgrading to MAUI we decided to give a try upgrading the platforms (Android & iOS) to .NET 7 and check how it goes. However, I'm having this issue on the Android project on .NET 7 and tried all the proposed solutions/workarounds but still getting the error on MediaSessionCompat:

/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.68/tools/Xamarin.Android.Common.targets(1476,3): error XA4215: The Java type `mono.android.support.v4.media.session.MediaSessionCompat_OnActiveChangeListenerImplementor` is generated by more than one managed type. Please change the [Register] attribute so that the same Java type is not emitted. [/Users/user/Projects/MyProject/Mobile/src/Android/Android.csproj::TargetFramework=net7.0-android]
/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.68/tools/Xamarin.Android.Common.targets(1476,3): error XA4215:   `mono.android.support.v4.media.session.MediaSessionCompat_OnActiveChangeListenerImplementor` generated by: Android.Support.V4.Media.Session.MediaSessionCompat+IOnActiveChangeListenerImplementor, Xamarin.Android.Support.Media.Compat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null [/Users/user/Projects/MyProject/Mobile/src/Android/Android.csproj::TargetFramework=net7.0-android]
/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.68/tools/Xamarin.Android.Common.targets(1476,3): error XA4215:   `mono.android.support.v4.media.session.MediaSessionCompat_OnActiveChangeListenerImplementor` generated by: Android.Support.V4.Media.Session.MediaSessionCompat+IOnActiveChangeListenerImplementor, Xamarin.AndroidX.Media, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null [/Users/user/Projects/MyProject/Mobile/src/Android/Android.csproj::TargetFramework=net7.0-android]

Installed packages:

<PackageReference Include="Plugin.CurrentActivity" Version="2.1.0.4" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.18" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.10.1.2" />
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.6.1.3" />

Is there anything else we could try?

Edit: Tried also on .Net 8 preview 6 and getting the same issue. And tried the previous version of the AndroidX libraries ending on the same result.

@moljac
Copy link
Member Author

moljac commented Jul 28, 2023

@fedemkr I will create minimal repro sample on Sunday.

Looking good:

https://www.nuget.org/packages/Xamarin.AndroidX.AutoFill/1.1.0.18
https://www.nuget.org/packages/Xamarin.AndroidX.Core/1.10.1.2
https://www.nuget.org/packages/Xamarin.AndroidX.AppCompat/1.6.1.3

Cannot repro with net8.0. I will try net7.0 next week

@jpobst
Copy link
Contributor

jpobst commented Jul 28, 2023

@fedemkr It looks like you are using both Android Support Libraries and AndroidX:

  • Xamarin.Android.Support.Media.Compat
  • Xamarin.AndroidX.Media

It is highly recommended to migrate away from Android Support Libraries, as Google deprecated and stopped developing them many years ago.

In .NET 6+, we no longer run the Android Support -> AndroidX migration automatically for you. To make it run, add a reference to the Xamarin.AndroidX.Migration NuGet package. This will hopefully fix the duplication.

@moljac
Copy link
Member Author

moljac commented Jul 29, 2023

Looks like it was really late and I missed details in this error:

/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.68/tools/Xamarin.Android.Common.targets(1476,3): error XA4215: The Java type `mono.android.support.v4.media.session.MediaSessionCompat_OnActiveChangeListenerImplementor` is generated by more than one managed type. Please change the [Register] attribute so that the same Java type is not emitted. [/Users/user/Projects/MyProject/Mobile/src/Android/Android.csproj::TargetFramework=net7.0-android]
/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.68/tools/Xamarin.Android.Common.targets(1476,3): error XA4215:   `mono.android.support.v4.media.session.MediaSessionCompat_OnActiveChangeListenerImplementor` generated by: Android.Support.V4.Media.Session.MediaSessionCompat+IOnActiveChangeListenerImplementor, Xamarin.Android.Support.Media.Compat, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null [/Users/user/Projects/MyProject/Mobile/src/Android/Android.csproj::TargetFramework=net7.0-android]
/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/33.0.68/tools/Xamarin.Android.Common.targets(1476,3): error XA4215:   `mono.android.support.v4.media.session.MediaSessionCompat_OnActiveChangeListenerImplementor` generated by: Android.Support.V4.Media.Session.MediaSessionCompat+IOnActiveChangeListenerImplementor, Xamarin.AndroidX.Media, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null [/Users/user/Projects/MyProject/Mobile/src/Android/Android.csproj::TargetFramework=net7.0-android]

I will use stronger words - one MUST get rid of Android.Support - for own sanity. It is old and unsupported and probably tons of security and other issues.

@jamesmontemagno
Copy link

jamesmontemagno commented Aug 4, 2023

Don't use:

<PackageReference Include="Plugin.CurrentActivity" Version="2.1.0.4" />

It is built into .NET MAUI: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/platform-helpers?tabs=android

@moljac
Copy link
Member Author

moljac commented Aug 5, 2023

It is built into .NET MAUI: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/platform-helpers?tabs=android

Didn't know that. I just checked date of the latest release and it is 2018-05. I didn't dive into dependencies and it does not have any, so it should be OK, because it does not pull in transitive dependencies.

I think in this case the problem is with mixing Android.Support and AndroidX as jpobst stated. But to be sure I would need to dive in deeper into dependency graph/tree/forest.

ThreeSevenths added a commit to santedb/santedb-dc-android that referenced this issue Oct 5, 2023
@jpobst jpobst removed the packages label Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants