GithubHelp home page GithubHelp logo

jpobst / prototype.android.mavenbindings Goto Github PK

View Code? Open in Web Editor NEW
5.0 5.0 2.0 83 KB

Prototype of MSBuild tasks to facilitate binding of Java libraries from Maven repositories

License: MIT License

C# 100.00%

prototype.android.mavenbindings's People

Contributors

jpobst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

kfrancis jasells

prototype.android.mavenbindings's Issues

Parent POM not understood

Scenario 1

There seems to be an additional way to specify a parent POM we need to investigate:
https://repo1.maven.org/maven2/com/squareup/wire/wire-runtime/4.7.1/wire-runtime-4.7.1.pom

That is, this POM does not specify a <parent> section like our previous examples did:
https://repo1.maven.org/maven2/com/google/guava/guava/31.1-android/guava-31.1-android.pom

<parent>
  <groupId>com.google.guava</groupId>
  <artifactId>guava-parent</artifactId>
  <version>31.1-android</version>
</parent>

Instead, it specifies this which I think we need to add support for:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.squareup.okio</groupId>
      <artifactId>okio-bom</artifactId>
      <version>3.3.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

This probably allows multiple parent POMs to be specified?

https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

Scenario 2

Another possible way of specifying dependencies:
https://maven.google.com/web/index.html?q=androidx.wear.protolayout#androidx.wear.protolayout:protolayout-expression:1.0.0

POM lists:

<dependency>
  <groupId>org.jetbrains.kotlin</groupId>
  <artifactId>kotlin-stdlib</artifactId>
  <scope>runtime</scope>
</dependency>

But does not include any <type>pom</type> as specified in the above example.

Support odd version strings

Hey,

I'm trying to use this with this: https://central.sonatype.com/artifact/org.jboss/jboss-vfs/3.2.17.Final but the ".Final" is causing the following:

The "MavenDependencyVerifierTask" task failed unexpectedly.
System.ArgumentException: '3.2.17.Final' is not a valid version string.
Parameter name: value
   at NuGet.Versioning.NuGetVersion.Parse(String value)
   at MavenNet.MavenVersionRange.Satisfies(String version)
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
   at Prototype.Android.MavenBinding.Tasks.DependencyResolver.IsDependencySatisfied(Dependency dependency, MicrosoftNuGetPackageFinder packages, LogWrapper log)
   at Prototype.Android.MavenBinding.Tasks.MavenDependencyVerifierTask.Execute()
   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()	Tesseract.Binding.Droid	C:\Users\kfrancis\.nuget\packages\xamprototype.android.mavenbinding.tasks\0.0.7\build\XamPrototype.Android.MavenBinding.Tasks.targets

They seem to include that in all their versions: https://central.sonatype.com/artifact/org.jboss/jboss-vfs/3.2.17.Final/versions

Can't consume a NuGet containing multiple native libs

This tool currently assumes only 1 native library per NuGet package dependency. This does follow the 1:1 convention for Android-binding packages. However when simply trying to include native dependencies without bindings, there are times when it is much more convenient to provide a "roll-up" NuGet that provides an entire "framework" of native packages.

For example: Ktor. https://mvnrepository.com/artifact/io.ktor

You can see my roll-up here, where there are ~20 native packages I need to roll up into a singel, or maybe 2-3 packages instead of 1:1 NuGet:jar.

In this case, none of these native libs generated bindings, as they are only needed to support a 3rd-party lib I am integrating into my Maui app.

The main issue with that 3rd party lib is it provides some full-stack functionality, which is how the whole Ktor framework gets pulled in as a dependency... but that's another topic...

Back to the point:

The MavenBindings build task seemed pretty straight forward, after looking at the code a bit. I was able to mod it locally to support consuming a single roll-up .nupkg that contains multiple native libs (the Ktor roll-up package linked above) with multiple meta-data tags (1 tag per native lib).

I think this would be a valuable use-case. I can push my branch/open PR if there is interest. I'm torn what to do since this local version does exactly what I need, but I am not sure what .Net9 roadmap is and if this use-case is intentionally going to not be supported, I'm going to have to think on how to proceed.

Here's the branch that I have working locally. (some extra debugging log statements are still there, but can be removed)
https://github.com/jasells/Prototype.Android.MavenBindings/tree/support-roll-up-packages

I suppose, the only other option would be to use the MavenNet package to create some tool that looked for all the native io.ktor packages and generated a .csproj for each... and package them all individually that way for "framework" scenarios. But this is working well, and I like the roll-up package, since I can just find-replace the old version string to update and publish the v-next NuGet.

Automatically include transitive Java dependencies

First of all thanks for this project, I really like the idea of ​​slim bindings, I've been using my own slim bindings for years and it's much better than full C# binding for all Java types. Now, I'm using https://github.com/kezong/fat-aar-android to include all .aar files to a native library.

I tried to use this library to add com.walletconnect:sign:2.18.0, com.walletconnect:android-core:1.20.0 and in my opinion it is completely unusable in its current state. I have a native project written in Kotlin which uses these libs and I want to include all .aar dependencies in a .NET project to get my native project working.
I get a lot of messages on dependencies and it is almost impossible to solve them all, moreover, if they update their library, I will have to repeat all the steps again to find all the dependencies and update them. Try including these libraries and you will understand me.

My suggestions:
It would be nice to automatically resolve all dependencies and add all .aar.jar files without manually describing them in .csproj, something like this (the same way like fat aar includes them):

<AndroidMavenLibrary Include="com.walletconnect:android-core" Version="1.20.0"/><!-- automatically include all dependencies except critical like  Xamarin.AndroidX.., Xamarin.Kotlin... etc-->
<AndroidMavenLibrary Include="com.walletconnect:sign" Version="2.18.0"/>

and only show nuget package errors for critical packages like Xamarin.AndroidX.., Xamarin.Kotlin.., etc.
For example, I don't use Square.OkIO at all from C# code, but it will show me an error that I need to install the nuget package instead of just including the raw .aar file.
Perhaps you should add some kind of mode that will simply download and include all .aar files in the project, without matching them against all nuget packages, only the critical ones.

Here is the list of libs that I added and gave up because the number of errors is growing exponentially:

        <AndroidMavenLibrary Include="com.walletconnect:android-core" Version="1.20.0"/>
        <AndroidMavenLibrary Include="com.walletconnect:foundation" Version="1.10.0"/>
        <AndroidMavenLibrary Include="com.squareup.sqldelight:android-driver" Version="1.5.4"/>
        <AndroidMavenLibrary Include="com.squareup.sqldelight:coroutines-extensions-jvm" Version="1.5.4"/>
        <AndroidMavenLibrary Include="net.zetetic:android-database-sqlcipher" Version="4.5.3"/>
        <AndroidMavenLibrary Include="androidx.security:security-crypto-ktx" Version="1.1.0-alpha04" Repository="Google"/>
        <AndroidMavenLibrary Include="io.insert-koin:koin-android" Version="3.4.2"/>
        <AndroidMavenLibrary Include="com.jakewharton.timber:timber" Version="5.0.1"/>
        <AndroidMavenLibrary Include="com.github.WalletConnect.Scarlet:lifecycle-android" Version="1.0.0" Repository="https://maven.scijava.org/content/repositories/public/"/>
        <AndroidMavenLibrary Include="org.web3j:crypto" Version="4.9.5"/>
        <AndroidMavenLibrary Include="com.github.komputing.kethereum:bip39" Version="0.85.7" Repository="https://jitpack.io"/>
        <AndroidMavenLibrary Include="com.github.komputing.kethereum:bip39_wordlist_en" Version="0.85.7" Repository="https://jitpack.io"/>
        <AndroidMavenLibrary Include="com.github.komputing.kethereum:bip32" Version="0.85.7" Repository="https://jitpack.io"/>
        <AndroidMavenLibrary Include="com.github.komputing.kethereum:crypto_impl_spongycastle" Version="0.85.7" Repository="https://jitpack.io"/>
        <AndroidMavenLibrary Include="com.github.komputing.kethereum:model" Version="0.85.7" Repository="https://jitpack.io"/>
        <AndroidMavenLibrary Include="com.squareup.retrofit2:retrofit" Version="2.9.0"/>
        <AndroidMavenLibrary Include="com.squareup.retrofit2:converter-moshi" Version="2.9.0"/>
        <AndroidMavenLibrary Include="com.squareup.sqldelight:runtime-jvm" Version="1.5.4"/>
        <AndroidMavenLibrary Include="com.getkeepsafe.relinker:relinker" Version="1.4.5"/>
        
        <PackageReference Include="Xamarin.AndroidX.Sqlite" Version="2.3.1.3" />
        
        <PackageReference Include="Xamarin.Kotlin.StdLib" Version="1.9.0.1" />
        <PackageReference Include="Xamarin.Kotlin.StdLib.Common" Version="1.9.0.1" />
        <PackageReference Include="Xamarin.Kotlin.StdLib.Jdk8" Version="1.9.0.1"/>
        <PackageReference Include="Xamarin.KotlinX.Coroutines.Core" Version="1.7.3"/>

here is the list of errors:


0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.WalletConnect.Scarlet:scarlet' version '1.0.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.WalletConnect.Scarlet:websocket-okhttp' version '1.0.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.WalletConnect.Scarlet:stream-adapter-coroutines' version '1.0.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.WalletConnect.Scarlet:message-adapter-moshi' version '1.0.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Warning  : Could not determine needed version of Maven dependency 'com.squareup.okhttp3:okhttp' (possibly due to not understanding a parent POM). Validation of this dependency will be skipped, but it still needs to be fulfilled.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Warning  : Could not determine needed version of Maven dependency 'com.squareup.okhttp3:logging-interceptor' (possibly due to not understanding a parent POM). Validation of this dependency will be skipped, but it still needs to be fulfilled.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.squareup.moshi:moshi-adapters' version '1.14.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.squareup.moshi:moshi-kotlin' version '1.14.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.bouncycastle:bcprov-jdk15on' version '1.70' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.multiformats:java-multibase' version '1.1.1' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'io.insert-koin:koin-core-jvm' version '3.3.2' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'jakarta.ws.rs:jakarta.ws.rs-api' version '3.1.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.sqlite:sqlite-framework' version '2.1.0' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Sqlite.Framework' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm' version '1.5.2' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.KotlinX.Coroutines.Core.Jvm' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.security:security-crypto' version '1.1.0-alpha04' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Security.SecurityCrypto' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'io.insert-koin:koin-core' version '3.4.2' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.appcompat:appcompat' version '1.6.1' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.AppCompat' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.activity:activity-ktx' version '1.6.1' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Activity.Ktx' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.fragment:fragment-ktx' version '1.5.7' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Fragment.Ktx' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.lifecycle:lifecycle-viewmodel-ktx' version '2.6.1' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Lifecycle.ViewModel.Ktx' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.lifecycle:lifecycle-common-java8' version '2.6.1' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Lifecycle.Common.Java8' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.jetbrains:annotations' version '20.1.0' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.Jetbrains.Annotations' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.WalletConnect.Scarlet:scarlet' version '1.0.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'io.reactivex.rxjava2:rxjava' version '2.1.16' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.Android.ReactiveX.RxJava' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'io.reactivex.rxjava2:rxkotlin' version '2.2.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'androidx.appcompat:appcompat' version '1.2.0' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.AppCompat' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.jetbrains.kotlin:kotlin-stdlib-jdk7' version '1.5.30' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.Kotlin.StdLib.Jdk7' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.web3j:abi' version '4.9.5' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.web3j:rlp' version '4.9.5' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.web3j:utils' version '4.9.5' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'org.slf4j:slf4j-api' version '1.7.30' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.fasterxml.jackson.core:jackson-databind' version '2.13.3' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:extensions_kotlin' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:crypto' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:crypto_api' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing:khex' version '1.1.2' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.khash:sha256-jvm' version '1.1.1' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:crypto' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:crypto_api' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:extensions_kotlin' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing:kbip44' version '0.5' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing:kbase58' version '0.4' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.khash:sha256-jvm' version '1.1.1' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.khash:ripemd160-jvm' version '1.1.1' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.madgag.spongycastle:prov' version '1.58.0.0' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:crypto_api' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:crypto_impl_java_provider' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing:khex' version '1.1.2' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.github.komputing.kethereum:extensions_kotlin' version '0.85.7' is not satisfied.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.squareup.okhttp3:okhttp' version '3.14.9' is not satisfied. Microsoft maintains the NuGet package 'Square.OkHttp3' that could fulfill this dependency.
0>XamPrototype.Android.MavenBinding.Tasks.targets(28,5): Error  : Maven dependency 'com.squareup.moshi:moshi' version '1.8.0' is not satisfied.

Intercom

So, I've long been searching for a way to create bindings without the annoying step of interacting with maven to get the aar file, so this is AMAZING.

That being said, try creating one for intercom. The SDK Base, for example, has a very large set of runtime dependencies so it's quite tedious setting that up: https://mvnrepository.com/artifact/io.intercom.android/intercom-sdk-base/14.2.0

image

So far, the base csproj is starting to look like this and I'm curious if I'm doing this right:

<ItemGroup>
	<PackageReference Include="GoogleGson" Version="2.10.1.1" />
	<PackageReference Include="Square.OkHttp3" Version="4.10.0.1" />
	<PackageReference Include="Xamarin.AndroidX.Annotation" Version="1.6.0" />
	<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.6.1" />
	<PackageReference Include="Xamarin.AndroidX.ConstraintLayout" Version="2.1.4.3" />
	<PackageReference Include="Xamarin.AndroidX.Core.Core.Ktx" Version="1.9.0.2" />
	<PackageReference Include="Xamarin.AndroidX.DataBinding.ViewBinding" Version="7.4.2" />
	<PackageReference Include="Xamarin.AndroidX.ExifInterface" Version="1.3.6" />
	<PackageReference Include="Xamarin.AndroidX.Fragment.Ktx" Version="1.5.6" />
	<PackageReference Include="Xamarin.AndroidX.RecyclerView" Version="1.3.0" />
	<PackageReference Include="Xamarin.AndroidX.VectorDrawable" Version="1.1.0.16" />
	<PackageReference Include="Xamarin.AndroidX.VectorDrawable.Animated" Version="1.1.0.16" />
	<PackageReference Include="Xamarin.AndroidX.WebKit" Version="1.6.1" />
	<PackageReference Include="Xamarin.Google.Android.Material" Version="1.8.0" />
	<PackageReference Include="Xamarin.Kotlin.StdLib" Version="1.8.20" />
	<PackageReference Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.4.2" />
	<PackageReference Include="XamPrototype.Android.MavenBinding.Tasks" Version="0.0.7" />
</ItemGroup>
<ItemGroup>
	<AndroidMavenLibrary Include="io.intercom.android:intercom-sdk-base" Version="14.2.0" />
	<AndroidMavenLibrary Include="io.intercom.android:intercom-sdk-ui" Version="14.2.0" />
	<AndroidMavenLibrary Include="com.squareup.okhttp3:okhttp" Version="4.9.3" Bind="false" />
	<AndroidMavenLibrary Include="org.jetbrains.kotlin:kotlin-parcelize-runtime" Version="1.8.20" Bind="false" />
	<AndroidMavenLibrary Include="org.jetbrains.kotlin:kotlin-android-extensions-runtime" Version="1.5.20" Bind="false" />
</ItemGroup>
<ItemGroup>
  <ProjectReference Include="..\Intercom.Droid.Commons\Intercom.Droid.Commons.csproj" JavaArtifact="com.intercom:android-commons" JavaVersion="2.0.0" />
  <ProjectReference Include="..\Intercom.Droid.Composer.Gallery\Intercom.Droid.Composer.Gallery.csproj" JavaArtifact="com.intercom:android-composer-gallery" JavaVersion="3.3.3" />
  <ProjectReference Include="..\Intercom.Droid.Composer\Intercom.Droid.Composer.csproj" JavaArtifact="com.intercom:android-composer" JavaVersion="3.3.3" />
</ItemGroup>

For example, if I add one that it's complaining about:

Severity	Code	Description	Project	File	Line	Suppression State	Priority
Error		Maven dependency 'com.google.android.flexbox:flexbox' version '3.0.0' is not satisfied.	Intercom.Droid.SDK.Base	C:\Users\kfrancis\.nuget\packages\xamprototype.android.mavenbinding.tasks\0.0.7\build\XamPrototype.Android.MavenBinding.Tasks.targets	28		Normal

as <AndroidMavenLibrary Include="com.google.android.flexbox:flexbox" Version="3.0.0" Bind="false" /> then I get the error:

Severity	Code	Description	Project	File	Line	Suppression State	Priority
Error		Cannot download artifact 'com.google.android.flexbox:flexbox'.
- com.google.android.flexbox_flexbox.jar: Response status code does not indicate success: 404 (Not Found).
- com.google.android.flexbox_flexbox.aar: Response status code does not indicate success: 404 (Not Found).	Intercom.Droid.SDK.Base	C:\Users\kfrancis\.nuget\packages\xamprototype.android.mavenbinding.tasks\0.0.7\build\XamPrototype.Android.MavenBinding.Tasks.targets	22		Normal

AFAIK, that entry should be correct based on the maven information: https://mvnrepository.com/artifact/com.google.android.flexbox/flexbox/3.0.0

Proposal: Untyped Slim Bindings

Summary

Another potential way to implement "bind only what you need" would be to remain fully in C# and place the burden on the user to provide the metadata needed to perform JNI interop. While this can be cumbersome and tricky for lots of API, for a few small uses it might be acceptable.

Downsides:

  • User must manually provide the metadata needed by JNI
  • Only supports C# -> Java invocations, users cannot override methods or listen for events

Open questions:

  • Can we determine the method signature from the parameters the user gives us? Or would they need to provide the signature as well?

Proposed API

// Create a new "com.googleplay.services.ApiClient" type instance
var api_client = new UntypedJavaObject ("com.googleplay.services", "ApiClient");

// or with constructor parameters
var api_client = new UntypedJavaObject ("com.googleplay.services", "ApiClient", "my_api_key");

// Invoke a method with 'void' return
api_client.InvokeMethod ("setApiKey", "my_api_key");

// Invoke a method with 'int' return
var quota = api_client.InvokeMethod<int> ("getRemainingQuota");

// Get an 'int' field
var quota = api_client.GetField<int> ("API_VERSION");

// Set an 'int' field
api_client.SetField ("API_VERSION", 34);

Would also need a static version:

var api_client = new UntypedStaticJavaObject ("com.googleplay.services", "ApiClient");
var quota = api_client.GetField<int> ("API_VERSION");

Interop with Classic Java.Lang.Object

Use a JLO as an "untyped" parameter type

var view = FindViewById (Resources.layout);
var map = new UntypedJavaObject ("com.mapbox.maps", "MapView");

map.InvokeMethod ("attachToView", view);

Return a JLO from an "untyped" return type

var map = new UntypedJavaObject ("com.mapbox.maps", "MapView");
var view = map.InvokeMethod<Android.Views.View> ("getAttachedView");

Cast a JLO that was bound as Object to an "untyped" type

var view = FindViewById (Resources.layout);
var unknown_jlo = view.GetThing ();

var untyped = UntypedJavaObject.FromObject (view);

Cast an "untyped" type to a known JLO

var map = new UntypedJavaObject ("com.mapbox.maps", "MapView");
var untyped = map.InvokeMethod<UntypedJavaObject> ("getAttachedView");

var view= untyped.JavaCast<Android.Views.View> ();

Execute an unbound method on a JLO

var view = FindViewById (Resources.layout);
var untyped = UntypedJavaObject.FromObject (view);

untyped.InvokeMethod ("newUnboundMethod");

Sample

Converting the sample from https://github.com/Redth/MapboxSlimBindingDemo/tree/main:

public class MainActivity : Activity
{
    protected override void OnCreate (Bundle? savedInstanceState)
    {
        base.OnCreate (savedInstanceState);
        
        // Create new MapView ('this' is 'Android.Content.Context')
        var mapview = new UntypedJavaObject ("com.mapbox.maps", "MapView", this);

        // MapView inherits Android.Views.View
        var view = mapview.JavaCast<Android.Views.View> ();

        // Set as our view
        SetContentView (view);
    }
}

Proposal: Vaguely Typed Slim Bindings

Background

One of the key tenets of "slim bindings" is that you only bind the type(s)/method(s) that you need to use. Unfortunately this does not work for a normal binding project because your desired types likely derive from other unbound types or take unbound types as method parameters or return types.

Example:

public class MapView extends MapViewBase implements MappableComponent {
  public MapView (Activity activity, MapViewOptions options) { ... }

  public PinResult AddPin (string name, PinCoordinates coordinates) { ... }
}

Trying to bind just MapView would fail because it also needs the types: MapViewBase, MappableComponent, MapViewOptions, PinResult, and PinCoordinates. Binding each of those types may require further types, and you essentially end up needing to bind the entire library.

Slim Bindings

The way slim bindings fixes this is that you write a Java wrapper around the API you need that does not expose these custom types to C#. This may look something like:

public class MyMapView extends android.view.View {
  private MapView mv;

  public MyMapView (Activity activity, string option1, bool option2) {
    var options = new MapViewOptions (option1, option2);
    mv = new MapView (activity, options);
  }
  
  public bool AddPin (string name, long latitude, long longitude) {
    var result = mv.AddPin (name, new PinCoordinates (latitude, longitude);
    return result.Success;
  }
}

In effect, it performs "type erasure" of custom types in order to bind the class.

One potential downside to this is that users must write a Java wrapper in order to expose the correct API, and many users may not know Java or would prefer to remain in C#.

Flutter's New jingen Bindings

Either as a conscience choice or because it is very early in development, jnigen does not expose any custom types in their bindings. Every non-primitive type is exposed as jni.JObject. (Their ~equivalent of Java.Lang.Object.)

So their binding of the above class would look like this (in a C#-looking language rather than dart):

public class MyMapView : Java.Lang.Object {
  public MyMapView (Java.Lang.Object activity, Java.Lang.Object options) { ... }

  public Java.Lang.Object AddPin (string name, Java.Lang.Object coordinates) { ... }
}

Basically, they are performing the same "type erasure" that our slim bindings require.

Vaguely Typed Slim Bindings

Applying the automatic type erasure that jnigen does to our generator process would provide a nice "hybrid" approach:

  • Bindings could be generated automatically without the user needing to write and maintain a Java wrapper.
  • Binding everything as JLO would eliminate nearly all errors that prevent typed bindings from automatically working today:
    • Missing implementations of abstract base type methods
    • Missing implementations of interface methods
    • Covariant return type issues
    • Generics
    • Mismatched override signatures

The downside is that you lose all C#/compile time type checking and type checks are performed at runtime by Java. For this reason, it feels better to keep these as "slim bindings" that are used sparingly on a few types rather than binding an entire library without types.

Example:

// Works correctly:
var activity = my_activity;
var map_view = new MapView (activity, null);

// Compiles, but throws a Java exception like IncompatibleClassException or something at runtime
var context = my_activity.Context;
var map_view = new MapView (context, null);

We would need a way to specify which types to bind, perhaps in MSBuild?

<ItemGroup>
  <AndroidMavenLibrary Include="map.company:MyMaps" Version="1.0.0" />
  <AndroidBindType Include="map.company.MyMapView" />
</ItemGroup>

Theoretically this is all that should be required to create a vaguely typed binding for the MyMapView class.

Flutter also includes the ability to exclude problematic members if needed, which could be something like:

<AndroidBindExcludeMember Include="map.mycompany.PinResult map.mycompany.MyMapView.AddPin (string, map.mycompany.PinCoordinates)" />

Or it could use XPath.

Working With Vaguely Typed Slim Bindings

Inevitably you will need to work with some additional "real" types from a library. Consider the AddPin method, which requires a PinCoordinates parameter and returns a PinResult type.

Assuming they do not come from a typed binding of a dependency, we would need to additionally bind them:

<AndroidBindType Include="map.company.PinCoordinates" />
<AndroidBindType Include="map.company.PinResult" />

We can now create instances of these types, or use JavaCast<T> to convert JLO to a type:

public void DoMapStuff (MyMapView map)
{
  var coords = new PinCoordinates (0, 0);
  var result = map.AddPin ("Null Island", coords).JavaCast<PinResult> ();

  Console.WriteLine ("Adding pin was successful: " + result.Success.ToString ());
}

Build is not Respecting `Bind="false"` attribute

I know this is marked as no longer maintained due to being integrated in .Net9 build system, however, hopefully @jpobst is still monitoring and can let me know if it is fixed in .Net9, or not. (I have played with the pre-release, but not in this scenario, only a single native import/include)

The issue seems to only arise when I have multiple includes, like:

<!--<AndroidLibrary Update="Jars\ktor-http-jvm-2.3.2.jar" Bind="false" Pack="true" />-->
<AndroidMavenLibrary Include="io.ktor:ktor-http-jvm" Version="2.3.2" Repository="Central" VerifyDependencies="true" Bind="false" />
<!--<AndroidLibrary Update="Jars\ktor-utils-jvm-2.3.2.jar" Bind="false" Pack="true" />-->
<AndroidMavenLibrary Include="io.ktor:ktor-utils-jvm" Version="2.3.2" Repository="Central" VerifyDependencies="true" Bind="false" />

You can see the "standard" .Net8/7 build nodes commented, which correctly skip the binding step. When using this package, the binding step runs, giving me errors in C#-generated code, unless I use x-path in Metadata.xml to force-remove all the types in the native lib to "skip" the binding step. Ktor is a "framework" of ~12 libs, so I'd like to just make a single .nupkg in this case as a "roll-up" per version.

luckily... I already built a little xml parser/generator to read the generated Api.xml and then generate the Metadata.xml file for me since I was doing this pre-.Net7/6 and the AndroidLibrary upgrade.

Hopefully, this will at least help to get a fix in the .Net9 system?

Transitive NuGet packages not considered for Maven dependency resolution

It would appear that transitive NuGet packages are not considered when ensuring POM dependencies are met.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net7.0-android</TargetFramework>
    <SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
    <RootNamespace>emoji_picker</RootNamespace>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Xamarin.AndroidX.Emoji2" Version="1.4.0.2" />
    <PackageReference Include="XamPrototype.Android.MavenBinding.Tasks" Version="0.0.11" />
  </ItemGroup>
  <ItemGroup>
  <AndroidMavenLibrary Include="androidx.emoji2:emoji2-emojipicker" Version="1.4.0" Repository="Google" />
</ItemGroup>
</Project>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.