dotnet / android

.NET for Android provides open-source bindings of the Android SDK for use with .NET managed languages such as C#
MIT License
1.92k stars 526 forks source link

[.NET 9.0 Preview 5] Question about <AndroidMavenLibrary> includes #9040

Closed alexeygritsenko closed 2 months ago

alexeygritsenko commented 2 months ago

Android framework version

net9.0-android

Affected platform version

VS 2022 Preview

Description

Hi, I'm still trying to test to understand the possibility of migrating my Java projects to .NET by using dotnet build

My environment: VS 2022 Preview .NET 9.0 Preview 5 .NET 9.0 MAUI Workload

build.gradle:

dependencies {
    implementation 'io.appmetrica.analytics:analytics:6.5.0'
    implementation 'com.vanniktech:emoji-ios:0.18.0'
    implementation 'com.mikepenz:fastadapter:5.7.0'
}

I have converted to the following entries in csproj

AndroidBindingTest.csproj:

<ItemGroup>
    <AndroidMavenLibrary Include="io.appmetrica.analytics:analytics" Version="6.5.0" />
    <AndroidMavenLibrary Include="com.vanniktech:emoji-ios" Version="0.18.0" />
    <AndroidMavenLibrary Include="com.mikepenz:fastadapter" Version="5.7.0" />
</ItemGroup>

Problem 1 - cannot get dependencies

AndroidBindingTest failure with errors (22):
 error XA4242: Java dependency "com.android.installreferrer:installreferrer:2.2" is not satisfied. Microsoft maintains a NuGet package "Xamarin.Google.Android.InstallReferrer" that can fulfill this dependency.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-ad-revenue:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-identifiers:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-location:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-remote-permissions:6.5.0" is not satisfied.
 error XA4242: Java dependency "org.jetbrains.kotlin:kotlin-stdlib:1.6.21" is not satisfied. Microsoft maintains a NuGet package "Xamarin.Kotlin.StdLib" that can fulfill this dependency.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-proto:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-appsetid:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-billing-interface:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-billing-v6:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-core-api:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-core-utils:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-location-api:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-logger:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-modules-api:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-ndkcrashes-api:6.5.0" is not satisfied.
 error XA4241: Java dependency "io.appmetrica.analytics:analytics-network-tasks:6.5.0" is not satisfied.
 error XA4241: Java dependency "com.vanniktech:emoji:0.18.0" is not satisfied.
 error XA4242: Java dependency "org.jetbrains.kotlin:kotlin-stdlib:1.9.21" is not satisfied. Microsoft maintains a NuGet package "Xamarin.Kotlin.StdLib" that can fulfill this dependency.
 error XA4242: Java dependency "org.jetbrains.kotlin:kotlin-stdlib:1.7.20" is not satisfied. Microsoft maintains a NuGet package "Xamarin.Kotlin.StdLib" that can fulfill this dependency.
 error XA4242: Java dependency "androidx.recyclerview:recyclerview:1.2.1" is not satisfied. Microsoft maintains a NuGet package "Xamarin.AndroidX.RecyclerView" that can fulfill this dependency.
 error XA4242: Java dependency "androidx.appcompat:appcompat:1.5.1" is not satisfied. Microsoft maintains a NuGet package "Xamarin.AndroidX.AppCompat" that can fulfill this dependency.

This behavior looks strange. See how it works in Android Studio. I don't have to care about dependencies, sometimes I'm not even familiar with them. Gradle solves this automatically without distracting the user. Why didn't you do the same?

Problem 2 - cannot allow libraries to have different versions of the same dependency In this case:

io.appmetrica.analytics:analytics require stdlib 1.6.21
com.vanniktech:emoji-ios require stdlib 1.9.21
com.mikepenz:fastadapter require stdlib 1.7.20

The Android Studio does not see any conflicts here. But in Visual Studio I have to do something to resolve them, which is impossible, correct me if I'm wrong.

Problem 3 - com.vanniktech:emoji-ios does not create a wrapper Okay, let's say I put up with some of the problems and decided to leave only one Java library that is most important to me. I manually specified all its dependencies

AndroidBindingTest.csproj:

<ItemGroup>
    <PackageReference Include="Xamarin.Kotlin.StdLib" Version="1.9.21.1" />
</ItemGroup>

<ItemGroup>
    <AndroidMavenLibrary Include="com.vanniktech:emoji" Version="0.18.0" />
    <AndroidMavenLibrary Include="com.vanniktech:emoji-ios" Version="0.18.0" />
</ItemGroup>

but it gives an error BINDINGSGENERATOR : warning BG8601: Elements "<package>" not found.

Conclusion: I currently don’t see the possibility of using the new inclusion in a real situation. Looks like I'll have to leave my project in Java.

Steps to Reproduce

see above

Did you find any workaround?

No response

Relevant log output

No response

jpobst commented 2 months ago

I don't have to care about dependencies, sometimes I'm not even familiar with them. Gradle solves this automatically without distracting the user. Why didn't you do the same?

This feature is designed around helping users create correct bindings libraries. If we automatically pick between 2 versions of a library behind the user's back it is likely it will not match the bindings library, and you will get errors at runtime. For now, this feature requires the user to be explicit about which dependencies they want to use to ensure the app doesn't crash.

But in Visual Studio I have to do something to resolve them, which is impossible, correct me if I'm wrong.

Each version is a "greater than or equal too" dependency. Adding the latest NuGet package like https://www.nuget.org/packages/Xamarin.Kotlin.StdLib/1.9.23.3 will satisfy both dependencies.

but it gives an error: BINDINGSGENERATOR : warning BG8601: Elements "<package>" not found.

This is a warning, not an error. If you have a feature like warnaserror on you will need to suppress this warning.

Looking at your referenced Java libraries:

Neither of them contain any Java code in their .jar, so nothing can be found to bind. If you do not want to create C# bindings for them, you can add Bind='false' like this:

<AndroidMavenLibrary Include="com.vanniktech:emoji" Version="0.18.0" Bind="false" />
<AndroidMavenLibrary Include="com.vanniktech:emoji-ios" Version="0.18.0" Bind="false" />
alexeygritsenko commented 2 months ago

@jpobst, thank you very much for your answer

This feature is designed around helping users create correct bindings libraries. If we automatically pick between 2 versions of a library behind the user's back it is likely it will not match the bindings library, and you will get errors at runtime...

Okay, it's a pity that this doesn't work out of the box. Usually choosing a suitable intersection between versions does not seem difficult, at least Gradle manages to do it

Each version is a "greater than or equal too" dependency. Adding the latest NuGet package like https://www.nuget.org/packages/Xamarin.Kotlin.StdLib/1.9.23.3 will satisfy both dependencies

Okay, that's good news

Neither of them contain any Java code in their .jar, so nothing can be found to bind. If you do not want to create C# bindings for them, you can add Bind='false' like this...

Okay, but where is the code then? Whether I have a warning or not, I cannot call any initialization code for this library from C# the way it works for me in Java: EmojiManager.install(new IosEmojiProvider());

image

Shouldn't I get the mapping of these imports as namespaces, and the classes into the same classes on C#?

jpobst commented 2 months ago

Okay, but where is the code then?

The code appears to be in https://mvnrepository.com/artifact/com.vanniktech/emoji-android/0.20.0.

alexeygritsenko commented 2 months ago

The code appears to be in https://mvnrepository.com/artifact/com.vanniktech/emoji-android/0.20.0

Xm, maybe, but so far I haven't been able to complete the build(

<ItemGroup>
    <PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.6.1.10" />
    <PackageReference Include="Xamarin.AndroidX.CardView" Version="1.0.0.28" />
    <PackageReference Include="Xamarin.AndroidX.DataBinding.ViewBinding" Version="8.4.0.2" />
    <PackageReference Include="Xamarin.AndroidX.RecyclerView" Version="1.3.2.5" />
    <PackageReference Include="Xamarin.AndroidX.SwipeRefreshLayout" Version="1.1.0.21" />
    <PackageReference Include="Xamarin.AndroidX.WebKit" Version="1.11.0.2" />
    <PackageReference Include="Xamarin.Google.Android.Material" Version="1.11.0" />
    <PackageReference Include="Xamarin.Kotlin.StdLib" Version="1.9.23.3" />
    <PackageReference Include="Xamarin.Kotlin.StdLib.Common" Version="1.9.23.3" />
    <PackageReference Include="Xamarin.Kotlin.StdLib.Jdk8" Version="1.9.23.3" />
</ItemGroup>

<ItemGroup>
    <AndroidMavenLibrary Include="com.vanniktech:emoji" Version="0.18.0" />
    <AndroidMavenLibrary Include="com.vanniktech:emoji-ios" Version="0.18.0" />
    <AndroidMavenLibrary Include="com.vanniktech:emoji-android" Version="0.18.0" />
    <AndroidMavenLibrary Include="com.vanniktech:ui-android" Version="0.8.0" />
</ItemGroup>

output:

AndroidBindingTest fails with errors (4)
  error XA4241: Java Dependency "org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.21" not satisfied.
  error XA4241: Java Dependency "com.google.android.flexbox:flexbox:3.0.0" not satisfied.
  error XA4241: Java Dependency "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.4.1" not satisfied.
  error XA4241: Java Dependency "org.jetbrains.kotlin:kotlin-parcelize-runtime:1.7.21" not satisfied.

It looks like these libraries are not available on Nuget. Then I tried to add them manually like Java

<AndroidMavenLibrary Include="org.jetbrains.kotlin:kotlin-parcelize-runtime" Version="1.9.21" />
<AndroidMavenLibrary Include="org.jetbrains.kotlinx:kotlinx-serialization-json-jvm" Version="1.4.1" />
<AndroidMavenLibrary Include="org.jetbrains.kotlinx:kotlinx-serialization-core-jvm" Version="1.4.1" />
<AndroidMavenLibrary Include="org.jetbrains.kotlin:kotlin-android-extensions-runtime" Version="1.9.21" />
<AndroidMavenLibrary Include="com.google.android.flexbox:flexbox" Version="3.0.0" />

and these are the errors I got

AndroidBindingTest fails with errors (1)
 error XA4236:
 Unable to download Maven artifact "com.google.android.flexbox:flexbox".
 - flexbox-3.0.0.jar: Response status code does not indicate success: 404 (Not Found).
 - flexbox-3.0.0.aar: Response status code does not indicate success: 404 (Not Found).
jpobst commented 2 months ago

It looks like flexbox comes from Google's Maven, not Maven Central: https://maven.google.com/web/index.html?q=flexbox#com.google.android.flexbox:flexbox:3.0.0

You will need to specify that:

<AndroidMavenLibrary Include="com.google.android.flexbox:flexbox" Version="3.0.0" Repository="Google" />

(Documentation)

alexeygritsenko commented 2 months ago

It looks like flexbox comes from Google's Maven, not Maven Central...

Thanks, yes it looks like it is. Now I get even crazier results

AndroidBindingTest fails with 96 errors and 247 warnings
  error CS0535: "JsonArray" does not implement the interface member "ICollection.ContainsAll(ICollection)".
  error CS0738: "JsonObject" does not implement the interface member "IMap.EntrySet()". 'JsonObject.EntrySet()' cannot implement 'IMap.EntrySet()' because it does not have a corresponding 'ICollection' return type.
  error CS0506: "StringJsonLexer.Source": The inherited member "AbstractJsonLexer.Source" cannot be overridden because it is not marked virtual, abstract, or override.
  error CS0534: "StreamingJsonEncoder" does not implement the inherited abstract member "AbstractEncoder.SerializersModule.get".
  error CS0111: The type "AbstractCollectionSerializer" already defines a member "GetGetDescriptorHandler" with the same parameter types.
  and etc.

This is normal?

jpobst commented 2 months ago

Unfortunately, yes. Now you're past the new <AndroidMavenLibrary> stuff and into the regular bindings library work: https://github.com/dotnet/java-interop/wiki/Troubleshooting-Android-Bindings-Issues

If you do not actually need managed bindings of most of these libraries, I would highly suggest using Bind="false" on the ones you don't need managed bindings of so that you don't need to fix these issues.

alexeygritsenko commented 2 months ago

I would highly suggest using Bind="false" on the ones you don't need managed bindings of so that you don't need to fix these issues...

Aaa, so that's why this attribute is) This reduced the number of errors to 6 (keep only com.vanniktech:*).

Thank you for your answers, I'm closing the topic. But in my heart I am still not satisfied with the high entry threshold. While in Android Studio this is done simply. If it were also possible to connect libraries to .NET I think many would be able to transfer projects from Java.

vyacheslav-volkov commented 2 months ago

Hi @jpobst,

I'm sorry for raising this topic again, but it wouldn't be bad to have a mode that downloads all the dependencies on its own. I think a lot of developers will encounter this problem, and for some libraries, tracking all dependencies manually is an almost impossible task. This is my issue from the previous repository https://github.com/jpobst/Prototype.Android.MavenBindings/issues/10.