First pass
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<config>
|
||||
<add key="globalPackagesFolder" value=".\packages" />
|
||||
</config>
|
||||
<packageSources>
|
||||
<!-- Add this repository to the list of available repositories -->
|
||||
<add key="XamarinBindingHelpers" value=".\output" />
|
||||
</packageSources>
|
||||
</configuration>
|
|
@ -0,0 +1,6 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<RestoreNoCache>true</RestoreNoCache>
|
||||
<RestorePackagesPath>..\packages</RestorePackagesPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,19 @@
|
|||
Any raw assets you want to be deployed with your application can be placed in
|
||||
this directory (and child directories) and given a Build Action of "AndroidAsset".
|
||||
|
||||
These files will be deployed with your package and will be accessible using Android's
|
||||
AssetManager, like this:
|
||||
|
||||
public class ReadAsset : Activity
|
||||
{
|
||||
protected override void OnCreate (Bundle bundle)
|
||||
{
|
||||
base.OnCreate (bundle);
|
||||
|
||||
InputStream input = Assets.Open ("my_asset.txt");
|
||||
}
|
||||
}
|
||||
|
||||
Additionally, some Android functions will automatically load asset files:
|
||||
|
||||
Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
|
|
@ -0,0 +1,21 @@
|
|||
using Android.App;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Widget;
|
||||
using AndroidX.AppCompat.App;
|
||||
|
||||
namespace SampleAndroidApp
|
||||
{
|
||||
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
|
||||
public class MainActivity : AppCompatActivity
|
||||
{
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
// Set our view from the "main" layout resource
|
||||
SetContentView(Resource.Layout.activity_main);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
package="com.companyname.sampleandroidapp">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
|
||||
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
</manifest>
|
|
@ -0,0 +1,26 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Android.App;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SampleAndroidApp")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SampleAndroidApp")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,44 @@
|
|||
Images, layout descriptions, binary blobs and string dictionaries can be included
|
||||
in your application as resource files. Various Android APIs are designed to
|
||||
operate on the resource IDs instead of dealing with images, strings or binary blobs
|
||||
directly.
|
||||
|
||||
For example, a sample Android app that contains a user interface layout (main.xml),
|
||||
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
|
||||
would keep its resources in the "Resources" directory of the application:
|
||||
|
||||
Resources/
|
||||
drawable/
|
||||
icon.png
|
||||
|
||||
layout/
|
||||
main.xml
|
||||
|
||||
values/
|
||||
strings.xml
|
||||
|
||||
In order to get the build system to recognize Android resources, set the build action to
|
||||
"AndroidResource". The native Android APIs do not operate directly with filenames, but
|
||||
instead operate on resource IDs. When you compile an Android application that uses resources,
|
||||
the build system will package the resources for distribution and generate a class called "R"
|
||||
(this is an Android convention) that contains the tokens for each one of the resources
|
||||
included. For example, for the above Resources layout, this is what the R class would expose:
|
||||
|
||||
public class R {
|
||||
public class drawable {
|
||||
public const int icon = 0x123;
|
||||
}
|
||||
|
||||
public class layout {
|
||||
public const int main = 0x456;
|
||||
}
|
||||
|
||||
public class strings {
|
||||
public const int first_string = 0xabc;
|
||||
public const int second_string = 0xbcd;
|
||||
}
|
||||
}
|
||||
|
||||
You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
|
||||
to reference the layout/main.xml file, or R.strings.first_string to reference the first
|
||||
string in the dictionary file values/strings.xml.
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
</RelativeLayout>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
После Ширина: | Высота: | Размер: 1.6 KiB |
Двоичные данные
Samples/SampleAndroidApp/Resources/mipmap-hdpi/ic_launcher_foreground.png
Normal file
После Ширина: | Высота: | Размер: 1.4 KiB |
После Ширина: | Высота: | Размер: 3.5 KiB |
После Ширина: | Высота: | Размер: 1.3 KiB |
Двоичные данные
Samples/SampleAndroidApp/Resources/mipmap-mdpi/ic_launcher_foreground.png
Normal file
После Ширина: | Высота: | Размер: 958 B |
После Ширина: | Высота: | Размер: 2.4 KiB |
После Ширина: | Высота: | Размер: 2.3 KiB |
Двоичные данные
Samples/SampleAndroidApp/Resources/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
После Ширина: | Высота: | Размер: 2.0 KiB |
После Ширина: | Высота: | Размер: 4.7 KiB |
После Ширина: | Высота: | Размер: 3.8 KiB |
Двоичные данные
Samples/SampleAndroidApp/Resources/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
После Ширина: | Высота: | Размер: 3.3 KiB |
После Ширина: | Высота: | Размер: 7.8 KiB |
После Ширина: | Высота: | Размер: 4.9 KiB |
Двоичные данные
Samples/SampleAndroidApp/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png
Normal file
После Ширина: | Высота: | Размер: 4.8 KiB |
После Ширина: | Высота: | Размер: 11 KiB |
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#2c3e50</color>
|
||||
<color name="colorPrimaryDark">#1B3147</color>
|
||||
<color name="colorAccent">#3498db</color>
|
||||
</resources>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#2C3E50</color>
|
||||
</resources>
|
|
@ -0,0 +1,4 @@
|
|||
<resources>
|
||||
<string name="app_name">SampleAndroidApp</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
</resources>
|
|
@ -0,0 +1,11 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,122 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}</ProjectGuid>
|
||||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<TemplateGuid>{122416d6-6b49-4ee2-a1e8-b825f31c79fe}</TemplateGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SampleAndroidApp</RootNamespace>
|
||||
<AssemblyName>SampleAndroidApp</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>True</Deterministic>
|
||||
<AndroidApplication>True</AndroidApplication>
|
||||
<AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
|
||||
<AndroidResgenClass>Resource</AndroidResgenClass>
|
||||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
|
||||
<AndroidUseLatestPlatformSdk>false</AndroidUseLatestPlatformSdk>
|
||||
<TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
|
||||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<AndroidEnableSGenConcurrent>true</AndroidEnableSGenConcurrent>
|
||||
<AndroidUseAapt2>true</AndroidUseAapt2>
|
||||
<AndroidHttpClientHandlerType>Xamarin.Android.Net.AndroidClientHandler</AndroidHttpClientHandlerType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>False</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
|
||||
<AndroidLinkMode>None</AndroidLinkMode>
|
||||
<EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugSymbols>True</DebugSymbols>
|
||||
<DebugType>portable</DebugType>
|
||||
<Optimize>True</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AndroidManagedSymbols>true</AndroidManagedSymbols>
|
||||
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
|
||||
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
|
||||
<EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="Mono.Android" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="MainActivity.cs" />
|
||||
<Compile Include="Resources\Resource.designer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\AboutResources.txt" />
|
||||
<None Include="Properties\AndroidManifest.xml" />
|
||||
<None Include="Assets\AboutAssets.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\activity_main.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
<AndroidResource Include="Resources\values\colors.xml" />
|
||||
<AndroidResource Include="Resources\values\ic_launcher_background.xml" />
|
||||
<AndroidResource Include="Resources\values\strings.xml" />
|
||||
<AndroidResource Include="Resources\values\styles.xml" />
|
||||
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher.xml" />
|
||||
<AndroidResource Include="Resources\mipmap-anydpi-v26\ic_launcher_round.xml" />
|
||||
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-hdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-mdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xhdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxhdpi\ic_launcher_round.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_foreground.png" />
|
||||
<AndroidResource Include="Resources\mipmap-xxxhdpi\ic_launcher_round.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\drawable\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.AndroidX.AppCompat">
|
||||
<Version>1.2.0.5</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Binding.Helpers" Version="0.1.0" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SampleAndroidBinding\SampleAndroidBinding.csproj">
|
||||
<Project>{a4d2280b-c68c-4835-a930-be03d64809bc}</Project>
|
||||
<Name>SampleAndroidBinding</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,48 @@
|
|||
Additions allow you to add arbitrary C# to the generated classes
|
||||
before they are compiled. This can be helpful for providing convenience
|
||||
methods or adding pure C# classes.
|
||||
|
||||
== Adding Methods to Generated Classes ==
|
||||
|
||||
Let's say the library being bound has a Rectangle class with a constructor
|
||||
that takes an x and y position, and a width and length size. It will look like
|
||||
this:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (int x, int y, int width, int height)
|
||||
{
|
||||
// JNI bindings
|
||||
}
|
||||
}
|
||||
|
||||
Imagine we want to add a constructor to this class that takes a Point and
|
||||
Size structure instead of 4 ints. We can add a new file called Rectangle.cs
|
||||
with a partial class containing our new method:
|
||||
|
||||
public partial class Rectangle
|
||||
{
|
||||
public Rectangle (Point location, Size size) :
|
||||
this (location.X, location.Y, size.Width, size.Height)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
At compile time, the additions class will be added to the generated class
|
||||
and the final assembly will a Rectangle class with both constructors.
|
||||
|
||||
|
||||
== Adding C# Classes ==
|
||||
|
||||
Another thing that can be done is adding fully C# managed classes to the
|
||||
generated library. In the above example, let's assume that there isn't a
|
||||
Point class available in Java or our library. The one we create doesn't need
|
||||
to interact with Java, so we'll create it like a normal class in C#.
|
||||
|
||||
By adding a Point.cs file with this class, it will end up in the binding library:
|
||||
|
||||
public class Point
|
||||
{
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
This directory is for Android .jars.
|
||||
|
||||
There are 2 types of jars that are supported:
|
||||
|
||||
== Input Jar ==
|
||||
|
||||
This is the jar that bindings should be generated for.
|
||||
|
||||
For example, if you were binding the Google Maps library, this would
|
||||
be Google's "maps.jar".
|
||||
|
||||
Set the build action for these jars in the properties page to "InputJar".
|
||||
|
||||
|
||||
== Reference Jars ==
|
||||
|
||||
These are jars that are referenced by the input jar. C# bindings will
|
||||
not be created for these jars. These jars will be used to resolve
|
||||
types used by the input jar.
|
||||
|
||||
NOTE: Do not add "android.jar" as a reference jar. It will be added automatically
|
||||
based on the Target Framework selected.
|
||||
|
||||
Set the build action for these jars in the properties page to "ReferenceJar".
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="MSBuild.Sdk.Extras/2.1.2">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>MonoAndroid10.0</TargetFrameworks>
|
||||
<IsBindingProject>true</IsBindingProject>
|
||||
<AssemblyName>Xamarin.Binding.Helpers.Sample.Android</AssemblyName>
|
||||
<MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
|
||||
<MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
|
||||
<AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
|
||||
<AndroidUseIntermediateDesignerFile>True</AndroidUseIntermediateDesignerFile>
|
||||
<RootNamespace>Xamarin.Binding.Helpers.Sample.Android</RootNamespace>
|
||||
<AndroidClassParser>class-parse</AndroidClassParser>
|
||||
<AndroidCodegenTarget>XAJavaInterop1</AndroidCodegenTarget>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageId>Xamarin.Binding.Helpers.Sample.Android</PackageId>
|
||||
<Title>Sample Binding Helpers Project</Title>
|
||||
<PackageVersion>1.0.0</PackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Transforms\*.xml" />
|
||||
<TransformFile Include="Transforms\*.xml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Xamarin.Binding.Helpers" Version="0.1.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Naxam.SoLoader.Droid" Version="0.6.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Mono.Android" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AndroidStudioProject Include="C:\Users\jondi\Downloads\DuoNativeSamples\MyApplication" Module="mylibrary" />
|
||||
<MavenNuGetMapping Include="com.google.code.gson:gson" MavenGroupId="com.google.code.gson" MavenArtifactId="gson" NuGetPackageId="GoogleGson" NuGetVersion="2.8.5" />
|
||||
<MavenNuGetMapping Include="com.squareup.okhttp3:okhttp" MavenGroupId="com.squareup.okhttp3" MavenArtifactId="okhttp" NuGetPackageId="Square.OkHttp" NuGetVersion="3.12.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target
|
||||
Name="GetProjectIntermediateOutputPath"
|
||||
DependsOnTargets="_ResolveMonoAndroidSdks"
|
||||
Outputs="@(XamarinAndroidBindngHelperSuggestionFile)">
|
||||
<ItemGroup>
|
||||
<XamarinAndroidBindngHelperSuggestionFile Include="$(IntermediateOutputPath)\xbh\_xbhpackagerefs.txt" />
|
||||
</ItemGroup>
|
||||
<Message Text="Project Intermediate Output Path: $(IntermediateOutputPath)" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,14 @@
|
|||
<enum-field-mappings>
|
||||
<!--
|
||||
This example converts the constants Fragment_id, Fragment_name,
|
||||
and Fragment_tag from android.support.v4.app.FragmentActivity.FragmentTag
|
||||
to an enum called Android.Support.V4.App.FragmentTagType with values
|
||||
Id, Name, and Tag.
|
||||
|
||||
<mapping jni-class="android/support/v4/app/FragmentActivity$FragmentTag" clr-enum-type="Android.Support.V4.App.FragmentTagType">
|
||||
<field jni-name="Fragment_name" clr-name="Name" value="0" />
|
||||
<field jni-name="Fragment_id" clr-name="Id" value="1" />
|
||||
<field jni-name="Fragment_tag" clr-name="Tag" value="2" />
|
||||
</mapping>
|
||||
-->
|
||||
</enum-field-mappings>
|
|
@ -0,0 +1,13 @@
|
|||
<enum-method-mappings>
|
||||
<!--
|
||||
This example changes the Java method:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (int flags)
|
||||
to be:
|
||||
android.support.v4.app.Fragment.SavedState.writeToParcel (Android.OS.ParcelableWriteFlags flags)
|
||||
when bound in C#.
|
||||
|
||||
<mapping jni-class="android/support/v4/app/Fragment.SavedState">
|
||||
<method jni-name="writeToParcel" parameter="flags" clr-enum-type="Android.OS.ParcelableWriteFlags" />
|
||||
</mapping>
|
||||
-->
|
||||
</enum-method-mappings>
|
|
@ -0,0 +1,9 @@
|
|||
<metadata>
|
||||
<!--
|
||||
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
|
||||
|
||||
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
|
||||
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
|
||||
-->
|
||||
</metadata>
|
|
@ -0,0 +1,294 @@
|
|||
using NuGet.Frameworks;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Versioning;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
using System.Xml.XPath;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml;
|
||||
using Xamarin.Binding.Helpers.NugetResolvers;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.Tests
|
||||
{
|
||||
public class UnitTest1
|
||||
{
|
||||
const string dependenciesTree =
|
||||
@"
|
||||
> Task :mylibrary:dependencies
|
||||
|
||||
------------------------------------------------------------
|
||||
Project :mylibrary
|
||||
------------------------------------------------------------
|
||||
|
||||
implementation - Implementation only dependencies for 'main' sources.
|
||||
+--- com.mapbox.mapboxsdk:mapbox-android-sdk:9.5.0
|
||||
| +--- com.mapbox.mapboxsdk:mapbox-android-telemetry:6.1.0
|
||||
| | +--- com.squareup.okhttp3:okhttp:3.12.0 -> 3.12.3
|
||||
| | | \--- com.squareup.okio:okio:1.15.0
|
||||
| | +--- com.google.code.gson:gson:2.8.5 -> 2.8.6
|
||||
| | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | +--- com.mapbox.mapboxsdk:mapbox-android-core:3.0.0
|
||||
| | \--- androidx.legacy:legacy-support-core-utils:1.0.0
|
||||
| | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | +--- androidx.core:core:1.0.0 -> 1.3.0
|
||||
| | | +--- androidx.annotation:annotation:1.1.0
|
||||
| | | +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.1.0
|
||||
| | | | +--- androidx.lifecycle:lifecycle-common:2.1.0
|
||||
| | | | | \--- androidx.annotation:annotation:1.1.0
|
||||
| | | | +--- androidx.arch.core:core-common:2.1.0
|
||||
| | | | | \--- androidx.annotation:annotation:1.1.0
|
||||
| | | | \--- androidx.annotation:annotation:1.1.0
|
||||
| | | +--- androidx.versionedparcelable:versionedparcelable:1.1.0
|
||||
| | | | +--- androidx.annotation:annotation:1.1.0
|
||||
| | | | \--- androidx.collection:collection:1.0.0 -> 1.1.0
|
||||
| | | | \--- androidx.annotation:annotation:1.1.0
|
||||
| | | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|
||||
| | +--- androidx.documentfile:documentfile:1.0.0
|
||||
| | | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | +--- androidx.loader:loader:1.0.0
|
||||
| | | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | | +--- androidx.core:core:1.0.0 -> 1.3.0 (*)
|
||||
| | | +--- androidx.lifecycle:lifecycle-livedata:2.0.0
|
||||
| | | | +--- androidx.arch.core:core-runtime:2.0.0
|
||||
| | | | | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | | | | \--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
|
||||
| | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.0.0
|
||||
| | | | | +--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.1.0 (*)
|
||||
| | | | | +--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
|
||||
| | | | | \--- androidx.arch.core:core-runtime:2.0.0 (*)
|
||||
| | | | \--- androidx.arch.core:core-common:2.0.0 -> 2.1.0 (*)
|
||||
| | | \--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 -> 2.1.0
|
||||
| | | \--- androidx.annotation:annotation:1.1.0
|
||||
| | +--- androidx.localbroadcastmanager:localbroadcastmanager:1.0.0
|
||||
| | | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | \--- androidx.print:print:1.0.0
|
||||
| | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| +--- com.mapbox.mapboxsdk:mapbox-sdk-geojson:5.3.0
|
||||
| | \--- com.google.code.gson:gson:2.8.6
|
||||
| +--- com.mapbox.mapboxsdk:mapbox-android-gestures:0.7.0
|
||||
| | +--- androidx.core:core:1.0.0 -> 1.3.0 (*)
|
||||
| | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| +--- com.mapbox.mapboxsdk:mapbox-android-accounts:0.7.0
|
||||
| | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| +--- com.mapbox.mapboxsdk:mapbox-android-sdk-gl-core:5.0.0
|
||||
| +--- com.mapbox.mapboxsdk:mapbox-sdk-turf:5.3.0
|
||||
| | \--- com.mapbox.mapboxsdk:mapbox-sdk-geojson:5.3.0 (*)
|
||||
| +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| +--- androidx.fragment:fragment:1.0.0 -> 1.1.0
|
||||
| | +--- androidx.annotation:annotation:1.1.0
|
||||
| | +--- androidx.core:core:1.1.0 -> 1.3.0 (*)
|
||||
| | +--- androidx.collection:collection:1.1.0 (*)
|
||||
| | +--- androidx.viewpager:viewpager:1.0.0
|
||||
| | | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | | +--- androidx.core:core:1.0.0 -> 1.3.0 (*)
|
||||
| | | \--- androidx.customview:customview:1.0.0
|
||||
| | | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | | \--- androidx.core:core:1.0.0 -> 1.3.0 (*)
|
||||
| | +--- androidx.loader:loader:1.0.0 (*)
|
||||
| | +--- androidx.activity:activity:1.0.0
|
||||
| | | +--- androidx.annotation:annotation:1.1.0
|
||||
| | | +--- androidx.core:core:1.1.0 -> 1.3.0 (*)
|
||||
| | | +--- androidx.lifecycle:lifecycle-runtime:2.1.0 (*)
|
||||
| | | +--- androidx.lifecycle:lifecycle-viewmodel:2.1.0 (*)
|
||||
| | | \--- androidx.savedstate:savedstate:1.0.0
|
||||
| | | +--- androidx.annotation:annotation:1.1.0
|
||||
| | | +--- androidx.arch.core:core-common:2.0.1 -> 2.1.0 (*)
|
||||
| | | \--- androidx.lifecycle:lifecycle-common:2.0.0 -> 2.1.0 (*)
|
||||
| | \--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 -> 2.1.0 (*)
|
||||
| \--- com.squareup.okhttp3:okhttp:3.12.3 (*)
|
||||
+--- androidx.appcompat:appcompat:1.2.0
|
||||
| +--- androidx.annotation:annotation:1.1.0
|
||||
| +--- androidx.core:core:1.3.0 (*)
|
||||
| +--- androidx.cursoradapter:cursoradapter:1.0.0
|
||||
| | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| +--- androidx.fragment:fragment:1.1.0 (*)
|
||||
| +--- androidx.appcompat:appcompat-resources:1.2.0
|
||||
| | +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|
||||
| | +--- androidx.annotation:annotation:1.1.0
|
||||
| | +--- androidx.core:core:1.0.1 -> 1.3.0 (*)
|
||||
| | +--- androidx.vectordrawable:vectordrawable:1.1.0
|
||||
| | | +--- androidx.annotation:annotation:1.1.0
|
||||
| | | +--- androidx.core:core:1.1.0 -> 1.3.0 (*)
|
||||
| | | \--- androidx.collection:collection:1.1.0 (*)
|
||||
| | \--- androidx.vectordrawable:vectordrawable-animated:1.1.0
|
||||
| | +--- androidx.vectordrawable:vectordrawable:1.1.0 (*)
|
||||
| | +--- androidx.interpolator:interpolator:1.0.0
|
||||
| | | \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | \--- androidx.collection:collection:1.1.0 (*)
|
||||
| +--- androidx.drawerlayout:drawerlayout:1.0.0
|
||||
| | +--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
| | +--- androidx.core:core:1.0.0 -> 1.3.0 (*)
|
||||
| | \--- androidx.customview:customview:1.0.0 (*)
|
||||
| \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|
||||
\--- com.google.android.material:material:1.2.1
|
||||
+--- androidx.annotation:annotation:1.0.1 -> 1.1.0
|
||||
+--- androidx.appcompat:appcompat:1.1.0 -> 1.2.0 (*)
|
||||
+--- androidx.cardview:cardview:1.0.0
|
||||
| \--- androidx.annotation:annotation:1.0.0 -> 1.1.0
|
||||
+--- androidx.coordinatorlayout:coordinatorlayout:1.1.0
|
||||
| +--- androidx.annotation:annotation:1.1.0
|
||||
| +--- androidx.core:core:1.1.0 -> 1.3.0 (*)
|
||||
| +--- androidx.customview:customview:1.0.0 (*)
|
||||
| \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|
||||
+--- androidx.core:core:1.2.0 -> 1.3.0 (*)
|
||||
+--- androidx.annotation:annotation-experimental:1.0.0
|
||||
+--- androidx.fragment:fragment:1.0.0 -> 1.1.0 (*)
|
||||
+--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.1.0 (*)
|
||||
+--- androidx.recyclerview:recyclerview:1.0.0 -> 1.1.0
|
||||
| +--- androidx.annotation:annotation:1.1.0
|
||||
| +--- androidx.core:core:1.1.0 -> 1.3.0 (*)
|
||||
| +--- androidx.customview:customview:1.0.0 (*)
|
||||
| \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|
||||
+--- androidx.transition:transition:1.2.0
|
||||
| +--- androidx.annotation:annotation:1.1.0
|
||||
| +--- androidx.core:core:1.0.1 -> 1.3.0 (*)
|
||||
| \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*)
|
||||
+--- androidx.vectordrawable:vectordrawable:1.1.0 (*)
|
||||
\--- androidx.viewpager2:viewpager2:1.0.0
|
||||
+--- androidx.annotation:annotation:1.1.0
|
||||
+--- androidx.fragment:fragment:1.1.0 (*)
|
||||
+--- androidx.recyclerview:recyclerview:1.1.0 (*)
|
||||
+--- androidx.core:core:1.1.0 -> 1.3.0 (*)
|
||||
\--- androidx.collection:collection:1.1.0 (*)
|
||||
|
||||
(*) - dependencies omitted (listed previously)
|
||||
|
||||
A web-based, searchable dependency report is available by adding the --scan option.
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
1 actionable task: 1 executed
|
||||
";
|
||||
[Fact]
|
||||
public void Test1()
|
||||
{
|
||||
var deps = GradleUtil.ParseDependenciesTree(dependenciesTree.Split(Environment.NewLine));
|
||||
|
||||
var tree = GradleUtil.PrintTree(deps);
|
||||
|
||||
Console.WriteLine(tree);
|
||||
|
||||
Assert.NotEmpty(deps);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("androidx.collection", "collection", "1.0.0", "1.1.0", "Xamarin.AndroidX.Collection", "1.1.0")]
|
||||
[InlineData("androidx.vectordrawable", "vectordrawable-animated", "1.1.0", null, "Xamarin.AndroidX.VectorDrawable.Animated", "1.1.0")]
|
||||
[InlineData("com.google.android.gms", "play-services-basement", "17.0.0", "17.1.0", "Xamarin.GooglePlayServices.Basement", "117.2.1")]
|
||||
[InlineData("com.squareup.okhttp3", "okhttp", "3.12.3", null, "Square.OkHttp3", "3.12.3")]
|
||||
[InlineData("com.squareup.okio", "okio", "1.15.0", null, "Square.OkIO", "1.15.0")]
|
||||
public async Task Test2(string groupId, string artifactId, string reqVersion, string resolvedVersion, string packageId, string nugetVerison)
|
||||
{
|
||||
var r = await MavenNuGetSomelier.SuggestNuget(new LocalMavenArtifact
|
||||
{
|
||||
GroupId = groupId,
|
||||
ArtifactId = artifactId,
|
||||
RequestedVersion = reqVersion,
|
||||
ResolvedVersion = resolvedVersion
|
||||
},
|
||||
new AndroidXMavenNugetResolver(),
|
||||
new GooglePlayServicesMavenNugetResolver(),
|
||||
new FirebaseMavenNugetResolver(),
|
||||
new ExplicitMavenNugetResolver(
|
||||
new ExplicitMavenNugetMapping("com.squareup.okhttp3", "okhttp", "3.12.3", "Square.OkHttp3", "3.12.3"),
|
||||
new ExplicitMavenNugetMapping("com.squareup.okio", "okio", "1.15.0", "Square.OkIO", "1.15.0")));
|
||||
|
||||
Assert.Equal(packageId, r.PackageId, true, true);
|
||||
|
||||
var atLeastVersion = SemanticVersion.Parse(nugetVerison);
|
||||
Assert.True(NuGetVersion.Parse(r.Version) >= atLeastVersion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test3()
|
||||
{
|
||||
var r = await GradleUtil.RunGradleProjectCommand(
|
||||
@"C:\Users\jondi\Downloads\DuoNativeSamples\MyApplication",
|
||||
"mylibrary:dependencies", "--configuration", "implementation");
|
||||
|
||||
Assert.NotNull(r);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Test4()
|
||||
{
|
||||
var androidProject = @"C:\Users\jondi\Downloads\DuoNativeSamples\MyApplication";
|
||||
|
||||
var depTreeText = await GradleUtil.RunGradleProjectCommand(androidProject, "mylibrary:dependencies", "--configuration", "implementation");
|
||||
var resolvedDepText = await GradleUtil.RunGradleProjectCommand(androidProject, "mylibrary:fetchXamarinBindingInfo");
|
||||
|
||||
var deps = GradleUtil.ParseDependenciesTree(depTreeText);
|
||||
|
||||
var bindingDeps = await MavenNuGetSomelier.MapNuGets(deps,
|
||||
new AndroidXMavenNugetResolver(),
|
||||
new GooglePlayServicesMavenNugetResolver(),
|
||||
new FirebaseMavenNugetResolver(),
|
||||
new ExplicitMavenNugetResolver(
|
||||
new ExplicitMavenNugetMapping("com.squareup.okhttp3", "okhttp", "3.12.3", "Square.OkHttp3", "3.12.3"),
|
||||
new ExplicitMavenNugetMapping("com.squareup.okio", "okio", "1.15.0", "Square.OkIO", "1.15.0"),
|
||||
new ExplicitMavenNugetMapping("com.google.code.gson", "gson", "2.8.5", "GoogleGson", "2.8.5"),
|
||||
new ExplicitMavenNugetMapping("com.google.android.material", "material", "1.2.1", "Xamarin.Google.Android.Material", "1.2.1-rc1")));
|
||||
|
||||
|
||||
var mavenArtifactLocalFiles = new Dictionary<string, string>();
|
||||
|
||||
const string xamGradleArtifactPrefix = "XAMARIN.GRADLE.ARTIFACT|";
|
||||
|
||||
var localArtifacts = new List<string>();
|
||||
|
||||
foreach (var line in resolvedDepText)
|
||||
{
|
||||
if (!line.StartsWith(xamGradleArtifactPrefix))
|
||||
continue;
|
||||
|
||||
var parts = line.Substring(xamGradleArtifactPrefix.Length).Split('|', 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if ((parts?.Length ?? 0) != 2)
|
||||
continue;
|
||||
|
||||
if (parts[0] == "LOCAL")
|
||||
localArtifacts.Add(parts[1]);
|
||||
else
|
||||
{
|
||||
var bindingDep = bindingDeps.FirstOrDefault(bd =>
|
||||
$"{bd.MavenDependency.GroupId}:{bd.MavenDependency.ArtifactId}".Equals(parts[0], StringComparison.OrdinalIgnoreCase));
|
||||
if (bindingDep != null)
|
||||
bindingDep.MavenDependency.File = parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var text = new StringBuilder();
|
||||
|
||||
text.AppendLine("<ItemGroup>");
|
||||
foreach(var bd in bindingDeps.Where(b => b.NuGet != null))
|
||||
{
|
||||
text.AppendLine($" <PackageReference Include=\"{bd.NuGet.PackageId}\" Version=\"{bd.NuGet.Version}\" />");
|
||||
}
|
||||
text.AppendLine("</ItemGroup>");
|
||||
|
||||
text.AppendLine("<ItemGroup>");
|
||||
foreach (var bd in bindingDeps.Where(b => b.NuGet == null))
|
||||
{
|
||||
var ext = System.IO.Path.GetExtension(bd.MavenDependency.File);
|
||||
|
||||
var isAar = ext?.Equals(".aar", StringComparison.OrdinalIgnoreCase) ?? false;
|
||||
|
||||
if (isAar)
|
||||
text.AppendLine($" <AndroidAarLibrary Include=\"{bd.MavenDependency.File}\" />");
|
||||
else
|
||||
text.AppendLine($" <AndroidExternalJavaLibrary Include=\"{bd.MavenDependency.File}\" />");
|
||||
}
|
||||
text.AppendLine("</ItemGroup>");
|
||||
|
||||
Assert.NotNull(text.ToString());
|
||||
Assert.NotEmpty(bindingDeps);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
||||
<PackageReference Include="NuGet.Protocol" Version="5.8.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Xamarin.Binding.Helpers\Xamarin.Binding.Helpers.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30711.63
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Binding.Helpers", "Xamarin.Binding.Helpers\Xamarin.Binding.Helpers.csproj", "{AA7C4773-1CB4-4226-A34D-CA5D9A5136F0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Binding.Helpers.Tests", "Xamarin.Binding.Helpers.Tests\Xamarin.Binding.Helpers.Tests.csproj", "{1A242704-924D-4072-93D0-FDAF4A9F0C26}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleAndroidBinding", "Samples\SampleAndroidBinding\SampleAndroidBinding.csproj", "{A4D2280B-C68C-4835-A930-BE03D64809BC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleAndroidApp", "Samples\SampleAndroidApp\SampleAndroidApp.csproj", "{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AA7C4773-1CB4-4226-A34D-CA5D9A5136F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA7C4773-1CB4-4226-A34D-CA5D9A5136F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA7C4773-1CB4-4226-A34D-CA5D9A5136F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA7C4773-1CB4-4226-A34D-CA5D9A5136F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1A242704-924D-4072-93D0-FDAF4A9F0C26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1A242704-924D-4072-93D0-FDAF4A9F0C26}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1A242704-924D-4072-93D0-FDAF4A9F0C26}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1A242704-924D-4072-93D0-FDAF4A9F0C26}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A4D2280B-C68C-4835-A930-BE03D64809BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A4D2280B-C68C-4835-A930-BE03D64809BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A4D2280B-C68C-4835-A930-BE03D64809BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A4D2280B-C68C-4835-A930-BE03D64809BC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F5FED1BB-5BCF-4323-AAE5-E0232E15E4E5}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C256DFCD-0CFF-411A-B930-DA1851859201}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Binding.Helpers.NugetResolvers;
|
||||
|
||||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
public class AndroidStudioProjectInfo
|
||||
{
|
||||
public string ModuleArtifact { get; set; }
|
||||
|
||||
public List<MavenArtifactNuGetPairing> AllDependencies { get; set; }
|
||||
|
||||
public IEnumerable<NuGetSuggestion> NuGetDependencies =>
|
||||
AllDependencies
|
||||
.Where(nd => !string.IsNullOrEmpty(nd.NuGet?.Version) && !string.IsNullOrEmpty(nd.NuGet?.PackageId))
|
||||
.Select(nd => nd.NuGet);
|
||||
|
||||
public IEnumerable<LocalMavenArtifact> MavenArtifacts =>
|
||||
AllDependencies
|
||||
.Where(ma => !string.IsNullOrEmpty(ma.MavenDependency?.File))
|
||||
.Select(ma => ma.MavenDependency);
|
||||
|
||||
}
|
||||
public class AndroidStudioProject
|
||||
{
|
||||
public AndroidStudioProject(string projectPath)
|
||||
{
|
||||
ProjectPath = projectPath;
|
||||
}
|
||||
|
||||
public string ProjectPath { get; set; }
|
||||
|
||||
public async Task<AndroidStudioProjectInfo> GetDependencies(string module, IEnumerable<ExplicitMavenNugetMapping> mavenNugetMappings)
|
||||
{
|
||||
var depTreeText = await GradleUtil.RunGradleProjectCommand(ProjectPath, $"{module}:dependencies", "--configuration", "implementation");
|
||||
var resolvedDepText = await GradleUtil.RunGradleProjectCommand(ProjectPath, $"{module}:fetchXamarinBindingInfo");
|
||||
|
||||
await GradleUtil.RunGradleProjectCommand(ProjectPath, $"{module}:bundleReleaseAar");
|
||||
|
||||
var deps = GradleUtil.ParseDependenciesTree(depTreeText);
|
||||
|
||||
var bindingDeps = await MavenNuGetSomelier.MapNuGets(deps,
|
||||
new ExplicitMavenNugetResolver(mavenNugetMappings),
|
||||
new AndroidXMavenNugetResolver(),
|
||||
new GooglePlayServicesMavenNugetResolver(),
|
||||
new FirebaseMavenNugetResolver(),
|
||||
new KnownMavenNugetResolver());
|
||||
|
||||
var mavenArtifactLocalFiles = new Dictionary<string, string>();
|
||||
|
||||
const string xamGradleArtifactPrefix = "XAMARIN.GRADLE.ARTIFACT|";
|
||||
|
||||
var localArtifacts = new List<string>();
|
||||
|
||||
string libraryLocalAar = null;
|
||||
|
||||
foreach (var line in resolvedDepText)
|
||||
{
|
||||
if (!line.StartsWith(xamGradleArtifactPrefix))
|
||||
continue;
|
||||
|
||||
var parts = line.Substring(xamGradleArtifactPrefix.Length).Split(new [] { '|' }, 2, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if ((parts?.Length ?? 0) != 2)
|
||||
continue;
|
||||
|
||||
if (parts[0] == "LOCAL")
|
||||
localArtifacts.Add(parts[1]);
|
||||
else if (parts[0] == "LIBRARY")
|
||||
libraryLocalAar = parts[1];
|
||||
else
|
||||
{
|
||||
var bindingDep = bindingDeps.FirstOrDefault(bd =>
|
||||
$"{bd.MavenDependency.GroupId}:{bd.MavenDependency.ArtifactId}".Equals(parts[0], StringComparison.OrdinalIgnoreCase));
|
||||
if (bindingDep != null)
|
||||
bindingDep.MavenDependency.File = parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
return new AndroidStudioProjectInfo { AllDependencies = bindingDeps.ToList(), ModuleArtifact = libraryLocalAar };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
configurations.implementation.canBeResolved = true
|
||||
|
||||
task fetchXamarinBindingInfo() {
|
||||
doLast {
|
||||
|
||||
println("<!--BEGIN XAMARIN.GRADLE.ARTIFACT-->")
|
||||
def config = configurations.implementation
|
||||
|
||||
config.files.each { ff ->
|
||||
if (!config.resolvedConfiguration.resolvedArtifacts.any { art -> art.file.absolutePath == ff.absolutePath })
|
||||
{
|
||||
println "XAMARIN.GRADLE.ARTIFACT|LOCAL|${ff.absolutePath}"
|
||||
}
|
||||
}
|
||||
|
||||
config.resolvedConfiguration.resolvedArtifacts.each { art ->
|
||||
println "XAMARIN.GRADLE.ARTIFACT|${art.moduleVersion.id.group}:${art.moduleVersion.id.name}|${art.file.absolutePath}"
|
||||
}
|
||||
|
||||
def psep = File.separatorChar
|
||||
|
||||
println "XAMARIN.GRADLE.ARTIFACT|LIBRARY|${project.projectDir}${psep}build${psep}outputs${psep}aar${psep}${project.name}-release.aar";
|
||||
|
||||
println("<!--END XAMARIN.GRADLE.ARTIFACT-->")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
public class GradleUtil
|
||||
{
|
||||
static bool IsWindows => Environment.OSVersion.Platform == PlatformID.Win32NT;
|
||||
|
||||
|
||||
|
||||
public static async Task<IEnumerable<string>> RunGradleProjectCommand(string projectPath, params string[] args)
|
||||
{
|
||||
|
||||
var parg = new ProcessArgumentBuilder();
|
||||
foreach (var a in args)
|
||||
parg.Append(a);
|
||||
|
||||
var r = await ProcessRunner.RunAsync(new FileInfo(Path.Combine(projectPath, "gradlew" + (IsWindows ? ".bat" : string.Empty))), parg, new DirectoryInfo(projectPath));
|
||||
|
||||
return r.StandardOutput;
|
||||
}
|
||||
|
||||
const string rxpTreeDepth = @"(?<depth>\| |\+--- |\\--- | ){1,}(?<group>[^:]+):(?<artifact>[^:]+):(?<requestedVersion>[0-9\.]+)(\s?->\s?(?<resolvedVersion>[0-9.]+))?";
|
||||
|
||||
public static List<LocalMavenArtifact> ParseDependenciesTree(IEnumerable<string> lines)
|
||||
{
|
||||
var rxDepth = new Regex(rxpTreeDepth, RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
|
||||
var rootDependencies = new List<LocalMavenArtifact>();
|
||||
|
||||
|
||||
LocalMavenArtifact parentDependency = null;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var match = rxDepth.Match(line);
|
||||
|
||||
if (!match.Success)
|
||||
continue;
|
||||
|
||||
var depth = match.Groups?["depth"]?.Captures?.Count ?? 0;
|
||||
|
||||
var groupId = match.Groups?["group"]?.Value;
|
||||
var artifactId = match.Groups?["artifact"]?.Value;
|
||||
var reqVersion = match.Groups?["requestedVersion"]?.Value;
|
||||
var resVersion = match.Groups?["resolvedVersion"]?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(groupId) || string.IsNullOrEmpty(artifactId) || string.IsNullOrEmpty(reqVersion))
|
||||
continue;
|
||||
|
||||
var dep = new LocalMavenArtifact
|
||||
{
|
||||
GroupId = groupId,
|
||||
ArtifactId = artifactId,
|
||||
RequestedVersion = reqVersion,
|
||||
ResolvedVersion = resVersion,
|
||||
Depth = depth
|
||||
};
|
||||
|
||||
if (dep.Depth == 1)
|
||||
{
|
||||
// No parent, this is a root level dependency
|
||||
rootDependencies.Add(dep);
|
||||
}
|
||||
else if (dep.Depth > parentDependency.Depth)
|
||||
{
|
||||
// item is a dependency of hte parent
|
||||
dep.Parent = parentDependency;
|
||||
parentDependency.Dependencies.Add(dep);
|
||||
}
|
||||
else if (dep.Depth < parentDependency.Depth)
|
||||
{
|
||||
// This is up a level and a sibling of the parent
|
||||
var climbUp = parentDependency.Depth - dep.Depth;
|
||||
var actualParent = parentDependency.Parent;
|
||||
for (int i = 0; i < climbUp; i++)
|
||||
actualParent = actualParent.Parent;
|
||||
dep.Parent = actualParent;
|
||||
actualParent.Dependencies.Add(dep);
|
||||
}
|
||||
else if (dep.Depth == parentDependency.Depth)
|
||||
{
|
||||
// This is a sibling of the current parent
|
||||
dep.Parent = parentDependency.Parent;
|
||||
parentDependency.Parent.Dependencies.Add(dep);
|
||||
}
|
||||
|
||||
parentDependency = dep;
|
||||
|
||||
}
|
||||
|
||||
return rootDependencies;
|
||||
}
|
||||
|
||||
public static string PrintTree(List<LocalMavenArtifact> dependencies)
|
||||
{
|
||||
var text = new StringBuilder();
|
||||
|
||||
foreach (var d in dependencies)
|
||||
PrintDependency(0, text, d);
|
||||
|
||||
return text.ToString();
|
||||
}
|
||||
|
||||
static void PrintDependency(int depth, StringBuilder text, LocalMavenArtifact dependency)
|
||||
{
|
||||
text.Append(new string(' ', depth * 4));
|
||||
text.Append($"{dependency.GroupId}:{dependency.ArtifactId}:{dependency.RequestedVersion}");
|
||||
if (!string.IsNullOrEmpty(dependency.ResolvedVersion))
|
||||
text.Append($" -> {dependency.ResolvedVersion}");
|
||||
text.AppendLine();
|
||||
|
||||
if (dependency.Dependencies != null && dependency.Dependencies.Count > 0)
|
||||
{
|
||||
foreach (var d in dependency.Dependencies)
|
||||
PrintDependency(depth + 1, text, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Binding.Helpers.NugetResolvers;
|
||||
|
||||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
public class MavenNuGetSomelier
|
||||
{
|
||||
public static async Task<NuGetSuggestion> SuggestNuget(LocalMavenArtifact dependency, params MavenNugetResolver[] resolvers)
|
||||
{
|
||||
foreach (var r in resolvers)
|
||||
{
|
||||
var n = await r.Resolve(dependency.GroupId, dependency.ArtifactId, dependency.RequestedVersion, dependency.ResolvedVersion);
|
||||
|
||||
if (n != null)
|
||||
return n;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<MavenArtifactNuGetPairing>> MapNuGets(IEnumerable<LocalMavenArtifact> mavenDependencies, params MavenNugetResolver[] resolvers)
|
||||
{
|
||||
var results = new List<MavenArtifactNuGetPairing>();
|
||||
|
||||
foreach (var mavenDep in mavenDependencies)
|
||||
await MapNuGets(mavenDep, results, resolvers);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
static async Task MapNuGets(LocalMavenArtifact mavenDep, List<MavenArtifactNuGetPairing> bindingDeps, params MavenNugetResolver[] resolvers)
|
||||
{
|
||||
var nuget = await SuggestNuget(mavenDep, resolvers);
|
||||
|
||||
// Did we already add one?
|
||||
if (!bindingDeps.Any(bd => bd.MavenDependency.GroupId.Equals(mavenDep.GroupId, StringComparison.OrdinalIgnoreCase) && bd.MavenDependency.ArtifactId.Equals(mavenDep.ArtifactId, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
bindingDeps.Add(new MavenArtifactNuGetPairing
|
||||
{
|
||||
NuGet = await SuggestNuget(mavenDep, resolvers),
|
||||
MavenDependency = mavenDep
|
||||
});
|
||||
|
||||
if (nuget == null)
|
||||
{
|
||||
foreach (var child in mavenDep.Dependencies)
|
||||
{
|
||||
await MapNuGets(child, bindingDeps, resolvers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
public class LocalMavenArtifact
|
||||
{
|
||||
public string GroupId { get; set; }
|
||||
public string ArtifactId { get; set; }
|
||||
public string RequestedVersion { get; set; }
|
||||
public string ResolvedVersion { get; set; }
|
||||
public string File { get; set; }
|
||||
|
||||
bool? isAar;
|
||||
|
||||
public bool IsAar
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!isAar.HasValue)
|
||||
isAar = !string.IsNullOrEmpty(File) && Path.GetExtension(File).Equals(".aar", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
return isAar.Value;
|
||||
}
|
||||
}
|
||||
|
||||
bool? isJar;
|
||||
|
||||
public bool IsJar
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!isJar.HasValue)
|
||||
isJar = !string.IsNullOrEmpty(File) && Path.GetExtension(File).Equals(".jar", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
return isJar.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public LocalMavenArtifact Parent { get; set; } = null;
|
||||
|
||||
public int Depth { get; set; } = 0;
|
||||
|
||||
public List<LocalMavenArtifact> Dependencies { get; set; } = new List<LocalMavenArtifact>();
|
||||
|
||||
public override string ToString()
|
||||
=> $"{GroupId}:{ArtifactId} -> {RequestedVersion} ({ResolvedVersion}) -> {Depth}";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
public class MavenArtifactNuGetPairing
|
||||
{
|
||||
public NuGetSuggestion NuGet { get; set; }
|
||||
|
||||
public LocalMavenArtifact MavenDependency { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.NugetResolvers
|
||||
{
|
||||
public class AndroidXMavenNugetResolver : MavenNugetResolver
|
||||
{
|
||||
public override async Task<NuGetSuggestion> Resolve(string mavenGroupId, string mavenArtifactId, string mavenRequestedVersion, string mavenResolvedVersion)
|
||||
{
|
||||
if (!mavenGroupId.StartsWith("androidx."))
|
||||
{
|
||||
// Material design is a different pattern
|
||||
if (mavenGroupId.Equals("com.google.android.material", StringComparison.OrdinalIgnoreCase)
|
||||
&& mavenArtifactId.Equals("material", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var materialPkgId = "Xamarin.Google.Android.Material";
|
||||
var materialNugetVersion = await NuGetUtil.FindBestVersion(materialPkgId, mavenRequestedVersion, mavenResolvedVersion, true);
|
||||
|
||||
if (materialNugetVersion != null)
|
||||
return new NuGetSuggestion { PackageId = materialPkgId, Version = materialNugetVersion.ToNormalizedString() };
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var firstDashIndex = mavenArtifactId.IndexOf('-');
|
||||
|
||||
var packageId = mavenGroupId + "." + mavenArtifactId.Replace("-", ".");
|
||||
|
||||
|
||||
if (firstDashIndex > 0 && mavenGroupId.EndsWith(mavenArtifactId.Substring(0, firstDashIndex)))
|
||||
packageId = mavenGroupId + "." + mavenArtifactId.Substring(firstDashIndex + 1).Replace("-", ".");
|
||||
else if (mavenGroupId.EndsWith(mavenArtifactId, StringComparison.OrdinalIgnoreCase))
|
||||
packageId = mavenGroupId;
|
||||
|
||||
packageId = "xamarin." + packageId;
|
||||
|
||||
var nugetVersion = await NuGetUtil.FindBestVersion(packageId, mavenRequestedVersion, mavenResolvedVersion);
|
||||
|
||||
if (nugetVersion != null)
|
||||
return new NuGetSuggestion { PackageId = packageId, Version = nugetVersion.ToNormalizedString() };
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
namespace Xamarin.Binding.Helpers.NugetResolvers
|
||||
{
|
||||
public class ExplicitMavenNugetMapping
|
||||
{
|
||||
public ExplicitMavenNugetMapping(string mavenGroupId, string mavenArtifactId, string mavenVersion, string nugetPackageId, string nugetVersion)
|
||||
{
|
||||
MavenGroupId = mavenGroupId;
|
||||
MavenArtifactId = mavenArtifactId;
|
||||
MavenVersion = mavenVersion;
|
||||
NuGetPackageId = nugetPackageId;
|
||||
NuGetVersion = nugetVersion;
|
||||
}
|
||||
|
||||
public string MavenGroupId { get; set; }
|
||||
public string MavenArtifactId { get; set; }
|
||||
public string MavenVersion { get; set; }
|
||||
|
||||
public string NuGetPackageId { get; set; }
|
||||
public string NuGetVersion { get; set; }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
using NuGet.Versioning;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.NugetResolvers
|
||||
{
|
||||
public class ExplicitMavenNugetResolver : MavenNugetResolver
|
||||
{
|
||||
public List<ExplicitMavenNugetMapping> Mappings { get; set; } = new List<ExplicitMavenNugetMapping>();
|
||||
|
||||
public ExplicitMavenNugetResolver()
|
||||
{
|
||||
}
|
||||
|
||||
public ExplicitMavenNugetResolver(IEnumerable<ExplicitMavenNugetMapping> mappings)
|
||||
{
|
||||
Mappings.AddRange(mappings);
|
||||
}
|
||||
|
||||
public ExplicitMavenNugetResolver(params ExplicitMavenNugetMapping[] mappings)
|
||||
{
|
||||
Mappings.AddRange(mappings);
|
||||
}
|
||||
|
||||
public override async Task<NuGetSuggestion> Resolve(string mavenGroupId, string mavenArtifactId, string mavenRequestedVersion, string mavenResolvedVersion)
|
||||
{
|
||||
foreach (var m in Mappings)
|
||||
{
|
||||
// Empty nuget package id means don't resolve
|
||||
if (string.IsNullOrEmpty(m.NuGetPackageId))
|
||||
return null;
|
||||
|
||||
// If no nuget version specified, try latest
|
||||
if (string.IsNullOrEmpty(m.NuGetVersion))
|
||||
{
|
||||
m.NuGetVersion = (await NuGetUtil.GetVersions(m.NuGetPackageId))?.LastOrDefault()?.ToNormalizedString();
|
||||
if (string.IsNullOrEmpty(m.NuGetVersion))
|
||||
return null;
|
||||
}
|
||||
|
||||
// Are group and artifact id's equal?
|
||||
if (m.MavenGroupId.Equals(mavenGroupId, StringComparison.OrdinalIgnoreCase)
|
||||
&& m.MavenArtifactId.Equals(mavenArtifactId, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// make sure we can parse the maven version of the mapping
|
||||
if (SemanticVersion.TryParse(m.MavenVersion, out var mapMavenSemVer))
|
||||
{
|
||||
// Check two possibilities:
|
||||
// 1. The map version is >= resolved maven version
|
||||
// 2. The map version is >= than the requested maven version
|
||||
if ((SemanticVersion.TryParse(mavenResolvedVersion, out var mavenResSemver)
|
||||
&& mapMavenSemVer >= mavenResSemver)
|
||||
|| (SemanticVersion.TryParse(mavenRequestedVersion, out var mavenReqSemver)
|
||||
&& mapMavenSemVer >= mavenReqSemver))
|
||||
return new NuGetSuggestion
|
||||
{
|
||||
PackageId = m.NuGetPackageId,
|
||||
Version = m.NuGetVersion
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
return new NuGetSuggestion
|
||||
{
|
||||
PackageId = m.NuGetPackageId,
|
||||
Version = m.NuGetVersion
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.NugetResolvers
|
||||
{
|
||||
public class FirebaseMavenNugetResolver : MavenNugetResolver
|
||||
{
|
||||
public override async Task<NuGetSuggestion> Resolve(string mavenGroupId, string mavenArtifactId, string mavenRequestedVersion, string mavenResolvedVersion)
|
||||
{
|
||||
if (!mavenGroupId.StartsWith("com.google.firebase"))
|
||||
return null;
|
||||
|
||||
var packageId = "Xamarin.Firebase." + mavenArtifactId.Replace("firebase-", string.Empty).Replace("-", ".");
|
||||
|
||||
var nugetVersion = await NuGetUtil.FindBestVersion(packageId, "1" + mavenRequestedVersion, "1" + mavenResolvedVersion);
|
||||
|
||||
if (nugetVersion != null)
|
||||
return new NuGetSuggestion { PackageId = packageId, Version = nugetVersion.ToNormalizedString() };
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.NugetResolvers
|
||||
{
|
||||
public class GooglePlayServicesMavenNugetResolver : MavenNugetResolver
|
||||
{
|
||||
public override async Task<NuGetSuggestion> Resolve(string mavenGroupId, string mavenArtifactId, string mavenRequestedVersion, string mavenResolvedVersion)
|
||||
{
|
||||
if (!mavenGroupId.StartsWith("com.google.android.gms"))
|
||||
return null;
|
||||
|
||||
var packageId = "Xamarin.GooglePlayServices." + mavenArtifactId.Replace("play-services-", string.Empty).Replace("-", ".");
|
||||
|
||||
var nugetVersion = await NuGetUtil.FindBestVersion(packageId, "1" + mavenRequestedVersion, "1" + mavenResolvedVersion);
|
||||
|
||||
if (nugetVersion != null)
|
||||
return new NuGetSuggestion { PackageId = packageId, Version = nugetVersion.ToNormalizedString() };
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.NugetResolvers
|
||||
{
|
||||
public class KnownMavenNugetResolver : MavenNugetResolver
|
||||
{
|
||||
static Dictionary<string, string> map = new Dictionary<string, string>
|
||||
{
|
||||
{ "com.squareup.okio.okio", "Square.OkIO" },
|
||||
{ "com.squareup.okhttp3.okhttp", "Square.OkHttp3" },
|
||||
{ "com.squareup.okhttp3.okhttp-ws", "Square.OkHttp3.WS" },
|
||||
{ "com.squareup.okhttp3.okhttp-urlconnection", "Square.OkHttp.UrlConnection" },
|
||||
{ "com.squareup.okhttp.okhttp", "Square.OkHttp" },
|
||||
{ "com.squareup.okhttp.okhttp-ws", "Square.OkHttp.WS" },
|
||||
{ "com.squareup.okhttp.okhttp-urlconnection", "Square.OkHttp.UrlConnection" },
|
||||
{ "com.squareup.picasso.picasso", "Square.Picasso" },
|
||||
{ "com.squareup.retrofit2.retrofit", "Square.Retrofit2" },
|
||||
{ "com.squareup.retrofit2.converter-gson", "Square.Retrofit2.ConverterGson" },
|
||||
{ "com.squareup.retrofit2.adapter-rxjava", "Square.Retrofit2.AdapterRxJava2" },
|
||||
{ "com.squareup.moshi.moshi", "Square.Moshi" },
|
||||
{ "com.squareup.seismic", "Square.Seismic" },
|
||||
|
||||
{ "com.jakewharton.picasso.picasso2-okhttp3-downloader", "JakeWharton.Picasso2OkHttp3Downloader" },
|
||||
{ "com.jakewharton.threetenabp.threetenabp", "Xamarin.Android.JakeWharton.ThreeTenAbp" },
|
||||
{ "com.jakewharton.timber.timber", "Xamarin.JakeWharton.Timber" },
|
||||
|
||||
{ "com.github.bumptech.glide.glide", "Xamarin.Android.Glide" },
|
||||
{ "com.github.bumptech.glide.disklrucache", "Xamarin.Android.Glide.DiskLruCache" },
|
||||
{ "com.github.bumptech.glide.gifdecoder", "Xamarin.Android.Glide.GifDecoder" },
|
||||
{ "com.github.bumptech.glide.recyclerview-integration", "Xamarin.Android.Glide.RecyclerViewIntegration" },
|
||||
|
||||
{ "org.reactivestreams.reactive-streams", "Xamarin.Android.ReactiveStreams" },
|
||||
|
||||
{ "io.reactivex.rxjava2.rxandroid", "Xamarin.Android.ReactiveX.RxAndroid" },
|
||||
{ "io.reactivex.rxjava2.rxjava", "Xamarin.Android.ReactiveX.RxJava" },
|
||||
|
||||
{ "com.android.volley.volley", "Xamarin.Android.Volley" },
|
||||
|
||||
{ "com.facebook.android.facebook-android-sdk", "Xamarin.Facebook.Android" },
|
||||
{ "com.facebook.android.account-kit-sdk", "Xamarin.Facebook.AccountKit.Android" },
|
||||
{ "com.facebook.android.facebook-applinks", "Xamarin.Facebook.AppLinks.Android" },
|
||||
{ "com.facebook.android.audience-network-sdk", "Xamarin.Facebook.AudienceNetwork.Android" },
|
||||
{ "com.facebook.android.facebook-common", "Xamarin.Facebook.Common.Android" },
|
||||
{ "com.facebook.android.facebook-core", "Xamarin.Facebook.Core.Android" },
|
||||
{ "com.facebook.android.facebook-livestreaming", "Xamarin.Facebook.LiveStreaming.Android" },
|
||||
{ "com.facebook.android.facebook-login", "Xamarin.Facebook.Login.Android" },
|
||||
{ "com.facebook.android.facebook-loginkit", "Xamarin.Facebook.LoginKit.Android" },
|
||||
{ "com.facebook.android.facebook-marketing", "Xamarin.Facebook.Marketing.Android" },
|
||||
{ "com.facebook.android.notifications", "Xamarin.Facebook.Notifications.Android" },
|
||||
{ "com.facebook.android.facebook-places", "Xamarin.Facebook.Places.Android" },
|
||||
{ "com.facebook.android.facebook-share", "Xamarin.Facebook.Share.Android" },
|
||||
|
||||
{ "com.google.android.datatransport.transport-api", "Xamarin.Google.Android.DataTransport.TransportApi" },
|
||||
{ "com.google.android.datatransport.transport-backend-cct", "Xamarin.Google.Android.DataTransport.TransportBackendCct" },
|
||||
{ "com.google.android.datatransport.transport-runtime", "Xamarin.Google.Android.DataTransport.TransportRuntime" },
|
||||
|
||||
{ "com.google.android.libraries.places", "Xamarin.Google.Android.Places" },
|
||||
|
||||
{ "com.google.android.play.core", "Xamarin.Google.Android.Play.Core" },
|
||||
|
||||
{ "com.google.auto.value.auto-value-annotations", "Xamarin.Google.AutoValue.Annotations" },
|
||||
|
||||
{ "com.google.dagger.dagger", "Xamarin.Google.Dagger" },
|
||||
|
||||
{ "com.google.guava.guava", "Xamarin.Google.Guava" },
|
||||
|
||||
{ "com.google.guava.failureaccess", "Xamarin.Google.Guava.FailureAccess" },
|
||||
|
||||
{ "com.google.guava.listenablefuture", "Xamarin.Google.Guava.ListenableFuture" },
|
||||
|
||||
{ "com.googlecode.libphonenumber.libphonenumber", "Xamarin.Google.LibPhoneNumber" },
|
||||
|
||||
|
||||
{ "com.google.zxing.core", "Xamarin.Google.ZXing.Core" },
|
||||
|
||||
{ "io.grpc.grpc-android", "Xamarin.Grpc.Android" },
|
||||
{ "io.grpc.grpc-context", "Xamarin.Grpc.Context" },
|
||||
{ "io.grpc.grpc-core", "Xamarin.Grpc.Core" },
|
||||
{ "io.grpc.grpc-okhttp", "Xamarin.Grpc.OkHttp" },
|
||||
{ "io.grpc.grpc-protobuf-lite", "Xamarin.Grpc.Protobuf.Lite" },
|
||||
{ "io.grpc.grpc-stub", "Xamarin.Grpc.Stub" },
|
||||
|
||||
{ "io.opencensus.opencensus-api", "Xamarin.Io.OpenCensus.OpenCensusApi" },
|
||||
{ "io.opencensus.opencensus-contrib-grpc-metrics", "Xamarin.Io.OpenCensus.OpenCensusContribGrpcMetrics" },
|
||||
|
||||
{ "io.perfmark.perfmark-api", "Xamarin.Io.PerfMark.PerfMarkApi" },
|
||||
|
||||
{ "javax.inject.inject", "Xamarin.JavaX.Inject" },
|
||||
{ "org.jetbrains.annotations", "Xamarin.Jetbrains.Annotations" },
|
||||
|
||||
{ "org.jetbrains.kotlin.kotlin-reflect", "Xamarin.Kotlin.Reflect" },
|
||||
{ "org.jetbrains.kotlin.kotlin-stdlib", "Xamarin.Kotlin.StdLib" },
|
||||
{ "org.jetbrains.kotlin.kotlin-stdlib-common", "Xamarin.Kotlin.StdLib.Common" },
|
||||
{ "org.jetbrains.kotlin.kotlin-stdlib-jdk7", "Xamarin.Kotlin.StdLib.Jdk7" },
|
||||
{ "org.jetbrains.kotlin.kotlin-stdlib-jdk8", "Xamarin.Kotlin.StdLib.Jdk8" },
|
||||
{ "org.jetbrains.kotlin.kotlin-stdlib-jre7", "Xamarin.Kotlin.StdLib.Jre7" },
|
||||
{ "org.jetbrains.kotlin.kotlin-stdlib-jre8", "Xamarin.Kotlin.StdLib.Jre8" },
|
||||
|
||||
{ "org.tensorflow.tensorflow-lite", "Xamarin.TensorFlow.Lite" },
|
||||
{ "org.tensorflow.tensorflow-lite-gpu", "Xamarin.TensorFlow.Lite.Gpu" },
|
||||
};
|
||||
|
||||
public override async Task<NuGetSuggestion> Resolve(string mavenGroupId, string mavenArtifactId, string mavenRequestedVersion, string mavenResolvedVersion)
|
||||
{
|
||||
var id = $"{mavenGroupId}.{mavenArtifactId}";
|
||||
|
||||
var v = await NuGetUtil.FindBestVersion(id, mavenRequestedVersion, mavenResolvedVersion, true);
|
||||
|
||||
if (v != null)
|
||||
return new NuGetSuggestion { Version = v.ToNormalizedString(), PackageId = id };
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.NugetResolvers
|
||||
{
|
||||
public abstract class MavenNugetResolver
|
||||
{
|
||||
public abstract Task<NuGetSuggestion> Resolve(string mavenGroupId, string mavenArtifactId, string mavenRequestedVersion, string mavenResolvedVersion);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using NuGet.Frameworks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
public class NuGetSuggestion
|
||||
{
|
||||
public string PackageId { get; set; }
|
||||
public string Version { get; set; }
|
||||
|
||||
public NuGetFramework Framework { get; set; }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using NuGet.Protocol;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Repositories;
|
||||
using NuGet.Protocol.Core.Types;
|
||||
using NuGet.Common;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using NuGet.Versioning;
|
||||
using System.Linq;
|
||||
|
||||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
public class NuGetUtil
|
||||
{
|
||||
public static async Task<IEnumerable<NuGetVersion>> GetVersions(string packageId)
|
||||
{
|
||||
var cache = new SourceCacheContext();
|
||||
var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
|
||||
FindPackageByIdResource resource = await repository.GetResourceAsync<FindPackageByIdResource>();
|
||||
|
||||
var versions = await resource.GetAllVersionsAsync(
|
||||
packageId,
|
||||
cache,
|
||||
NullLogger.Instance,
|
||||
CancellationToken.None);
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
public static async Task<NuGetVersion> FindBestVersion(string packageId, string minVersion, string idealVersion = null, bool allowPrerelease = false)
|
||||
{
|
||||
var versions = await GetVersions(packageId);
|
||||
|
||||
if (versions != null)
|
||||
{
|
||||
SemanticVersion.TryParse(minVersion, out var semMinVer);
|
||||
SemanticVersion.TryParse(idealVersion, out var semIdealVer);
|
||||
|
||||
//foreach (var version in versions)
|
||||
//{
|
||||
// if (version == semIdealVer)
|
||||
// return version;
|
||||
//}
|
||||
|
||||
foreach (var version in versions.Reverse())
|
||||
{
|
||||
if (!allowPrerelease && version.IsPrerelease)
|
||||
continue;
|
||||
|
||||
if (semIdealVer != null && version >= semIdealVer)
|
||||
return version;
|
||||
if (semMinVer != null && version >= semMinVer)
|
||||
return version;
|
||||
}
|
||||
|
||||
return versions.FirstOrDefault();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Xamarin.Binding.Helpers
|
||||
{
|
||||
internal class ProcessArgumentBuilder
|
||||
{
|
||||
public List<string> args = new List<string>();
|
||||
|
||||
public ProcessArgumentBuilder Append(string arg)
|
||||
{
|
||||
args.Add(arg);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProcessArgumentBuilder AppendQuoted(string arg)
|
||||
{
|
||||
args.Add($"\"{arg}\"");
|
||||
return this;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> string.Join(" ", args);
|
||||
}
|
||||
|
||||
internal class ProcessRunner
|
||||
{
|
||||
public static ProcessResult Run(FileInfo exe, ProcessArgumentBuilder builder, DirectoryInfo workingDirectory = null)
|
||||
{
|
||||
var p = new ProcessRunner(exe, builder, workingDirectory);
|
||||
return p.WaitForExit();
|
||||
}
|
||||
|
||||
public static Task<ProcessResult> RunAsync(FileInfo exe, ProcessArgumentBuilder builder, DirectoryInfo workingDirectory = null)
|
||||
{
|
||||
var p = new ProcessRunner(exe, builder, workingDirectory);
|
||||
return p.WaitForExitAsync();
|
||||
}
|
||||
|
||||
readonly List<string> standardOutput;
|
||||
readonly List<string> standardError;
|
||||
readonly Process process;
|
||||
|
||||
public ProcessRunner(FileInfo executable, ProcessArgumentBuilder builder, DirectoryInfo workingDirectory = null)
|
||||
: this(executable, builder, System.Threading.CancellationToken.None, false, workingDirectory)
|
||||
{ }
|
||||
|
||||
public ProcessRunner(FileInfo executable, ProcessArgumentBuilder builder, System.Threading.CancellationToken cancelToken, bool redirectStandardInput = false, DirectoryInfo workingDirectory = null)
|
||||
{
|
||||
standardOutput = new List<string>();
|
||||
standardError = new List<string>();
|
||||
|
||||
//* Create your Process
|
||||
process = new Process();
|
||||
process.StartInfo.FileName = executable.FullName;
|
||||
process.StartInfo.Arguments = builder.ToString();
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
|
||||
if (workingDirectory != null && workingDirectory.Exists)
|
||||
process.StartInfo.WorkingDirectory = workingDirectory.FullName;
|
||||
|
||||
if (redirectStandardInput)
|
||||
process.StartInfo.RedirectStandardInput = true;
|
||||
|
||||
process.OutputDataReceived += (s, e) =>
|
||||
{
|
||||
if (e.Data != null)
|
||||
standardOutput.Add(e.Data);
|
||||
};
|
||||
process.ErrorDataReceived += (s, e) =>
|
||||
{
|
||||
if (e.Data != null)
|
||||
standardError.Add(e.Data);
|
||||
};
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.BeginErrorReadLine();
|
||||
|
||||
if (cancelToken != System.Threading.CancellationToken.None)
|
||||
{
|
||||
cancelToken.Register(() =>
|
||||
{
|
||||
try { process.Kill(); }
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public int ExitCode
|
||||
=> process.HasExited ? process.ExitCode : -1;
|
||||
|
||||
public bool HasExited
|
||||
=> process?.HasExited ?? false;
|
||||
|
||||
public void Kill()
|
||||
=> process?.Kill();
|
||||
|
||||
public void StandardInputWrite(string input)
|
||||
{
|
||||
if (!process.StartInfo.RedirectStandardInput)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
process.StandardInput.Write(input);
|
||||
}
|
||||
|
||||
public void StandardInputWriteLine(string input)
|
||||
{
|
||||
if (!process.StartInfo.RedirectStandardInput)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
process.StandardInput.WriteLine(input);
|
||||
}
|
||||
|
||||
public ProcessResult WaitForExit()
|
||||
{
|
||||
process.WaitForExit();
|
||||
|
||||
if (standardError?.Any(l => l?.Contains("error: more than one device/emulator") ?? false) ?? false)
|
||||
throw new Exception("More than one Device/Emulator detected, you must specify which Serial to target.");
|
||||
|
||||
return new ProcessResult(standardOutput, standardError, process.ExitCode);
|
||||
}
|
||||
|
||||
public Task<ProcessResult> WaitForExitAsync()
|
||||
{
|
||||
var tcs = new TaskCompletionSource<ProcessResult>();
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
var r = WaitForExit();
|
||||
tcs.TrySetResult(r);
|
||||
});
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessResult
|
||||
{
|
||||
public readonly List<string> StandardOutput;
|
||||
public readonly List<string> StandardError;
|
||||
|
||||
public readonly int ExitCode;
|
||||
|
||||
public bool Success
|
||||
=> ExitCode == 0;
|
||||
|
||||
internal ProcessResult(List<string> stdOut, List<string> stdErr, int exitCode)
|
||||
{
|
||||
StandardOutput = stdOut;
|
||||
StandardError = stdErr;
|
||||
ExitCode = exitCode;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.Build.Framework;
|
||||
using NuGet.Frameworks;
|
||||
using Xamarin.Build;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.Tasks
|
||||
{
|
||||
public class XbhAddDependenciesToNupkgTask : AsyncTask
|
||||
{
|
||||
public ITaskItem[] NuGetPackOutput { get; set; }
|
||||
|
||||
public ITaskItem[] TargetFrameworks { get; set; }
|
||||
|
||||
[Required]
|
||||
public string IntermediateOutputPath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DoExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Complete();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return base.Execute();
|
||||
}
|
||||
|
||||
async Task DoExecute()
|
||||
{
|
||||
var fullIntermediateOutputPath = new System.IO.DirectoryInfo(IntermediateOutputPath);
|
||||
if (!fullIntermediateOutputPath.Exists)
|
||||
fullIntermediateOutputPath.Create();
|
||||
|
||||
// Find package refs for any tfm's
|
||||
var packageRefFiles = new Dictionary<string, NuGetFramework>();
|
||||
|
||||
foreach (var tfm in TargetFrameworks)
|
||||
{
|
||||
var nugetFramework = NuGetFramework.Parse(tfm.ItemSpec);
|
||||
|
||||
var pkgRefFile = Path.Combine(fullIntermediateOutputPath.FullName, nugetFramework?.GetShortFolderName() ?? ".", "xbh", "_xbhpackagerefs.txt");
|
||||
if (File.Exists(pkgRefFile))
|
||||
packageRefFiles.Add(pkgRefFile, nugetFramework);
|
||||
|
||||
LogMessage($"Found: {tfm.ItemSpec} -> {pkgRefFile}");
|
||||
}
|
||||
|
||||
|
||||
var pkgRefs = new List<NuGetSuggestion>();
|
||||
|
||||
|
||||
foreach (var pkgRefFile in packageRefFiles)
|
||||
{
|
||||
var lines = File.ReadAllLines(pkgRefFile.Key);
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
|
||||
var parts = line?.Split(new[] { '|' }, 2);
|
||||
if ((parts?.Length ?? 0) == 2)
|
||||
pkgRefs.Add(new NuGetSuggestion
|
||||
{
|
||||
PackageId = parts[0],
|
||||
Version = parts[1],
|
||||
Framework = pkgRefFile.Value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var ns in pkgRefs)
|
||||
LogMessage($"NuGet Suggestion: {ns.PackageId} ({ns.Version}) for {ns.Framework}");
|
||||
|
||||
foreach (var item in NuGetPackOutput)
|
||||
{
|
||||
var file = new FileInfo(item.ItemSpec);
|
||||
|
||||
if (file.Exists && file.Extension.Equals(".nupkg", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
LogMessage($"Adding nuget deps to: {file.FullName}");
|
||||
AddPackageReferencesToNupkg(file.FullName, pkgRefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddPackageReferencesToNupkg(string nupkg, IEnumerable<NuGetSuggestion> pkgRefs)
|
||||
{
|
||||
var pkgRefsByTfm = pkgRefs.GroupBy(p => p.Framework);
|
||||
|
||||
using (var zipa = new ZipArchive(new FileStream(nupkg, FileMode.Open), ZipArchiveMode.Update))
|
||||
{
|
||||
string nuspecEntryName = zipa.Entries.FirstOrDefault(e => Path.GetExtension(e.Name).Equals(".nuspec", StringComparison.OrdinalIgnoreCase))?.FullName;
|
||||
|
||||
var nuspecEntry = zipa.GetEntry(nuspecEntryName);
|
||||
var updatedNuspec = new MemoryStream();
|
||||
XNamespace xmlns = null;
|
||||
|
||||
using (var entryStream = nuspecEntry.Open())
|
||||
{
|
||||
var xdoc = XDocument.Load(entryStream);
|
||||
|
||||
xmlns = xdoc.Root.GetDefaultNamespace();
|
||||
|
||||
var depsElem = xdoc.Descendants().FirstOrDefault(d => d.Name.LocalName == "dependencies");
|
||||
|
||||
// It's possible dependencies element doesn't exist yet, so we may need to add it
|
||||
if (depsElem == null)
|
||||
{
|
||||
LogMessage("dependencies element missing, creating...");
|
||||
var metadataElem = xdoc.Descendants().FirstOrDefault(d => d.Name?.LocalName == "metadata");
|
||||
depsElem = new XElement(XName.Get("dependencies", xmlns.NamespaceName));
|
||||
metadataElem.Add(depsElem);
|
||||
}
|
||||
|
||||
// Find existing dependency->group elements
|
||||
var depGroupElems = depsElem.Descendants().Where(d2 => d2.Name.LocalName == "group");
|
||||
|
||||
// Parse out frameworks and keep the element so we can match existing ones later
|
||||
var existingDepGroups = new List<(NuGetFramework, XElement)>();
|
||||
|
||||
foreach (var depGroupElem in depGroupElems)
|
||||
{
|
||||
var tfm = depGroupElem?.Attributes().FirstOrDefault(a => a?.Name?.LocalName == "targetFramework")?.Value;
|
||||
|
||||
if (!string.IsNullOrEmpty(tfm))
|
||||
existingDepGroups.Add((NuGetFramework.Parse(tfm), depGroupElem));
|
||||
}
|
||||
|
||||
// Go through each tfm we have package refs for
|
||||
// try and find the existing element to add to, otherwise create a new one
|
||||
foreach (var tfmGrp in pkgRefsByTfm)
|
||||
{
|
||||
var depGrp = existingDepGroups.FirstOrDefault(d => d.Item1.Equals(tfmGrp.Key));
|
||||
|
||||
// Add the dependency group for this TFM if it doesn't exist
|
||||
if (depGrp == default || depGrp.Item1 == null || depGrp.Item2 == null)
|
||||
{
|
||||
LogMessage($"Dependency Group Missing, creating: {tfmGrp.Key.Framework}...");
|
||||
var newDepGrpElem = new XElement(XName.Get("group", xmlns.NamespaceName),
|
||||
new XAttribute("targetFramework", tfmGrp.Key.Framework));
|
||||
|
||||
depsElem.Add(newDepGrpElem);
|
||||
|
||||
depGrp = (tfmGrp.Key, newDepGrpElem);
|
||||
}
|
||||
|
||||
// Add all the dependencies to the group
|
||||
foreach (var pkgRef in tfmGrp)
|
||||
{
|
||||
depGrp.Item2.Add(new XElement(XName.Get("dependency", xmlns.NamespaceName),
|
||||
new XAttribute("id", pkgRef.PackageId),
|
||||
new XAttribute("version", pkgRef.Version),
|
||||
new XAttribute("include", "All")));
|
||||
}
|
||||
}
|
||||
|
||||
using (var xmlWriter = XmlWriter.Create(updatedNuspec))
|
||||
{
|
||||
xdoc.WriteTo(xmlWriter);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old entry, add new one
|
||||
nuspecEntry.Delete();
|
||||
var newEntry = zipa.CreateEntry(nuspecEntryName);
|
||||
using (var newStream = newEntry.Open())
|
||||
{
|
||||
updatedNuspec.Position = 0;
|
||||
updatedNuspec.CopyTo(newStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Build.Framework;
|
||||
using NuGet.Packaging;
|
||||
using Xamarin.Binding.Helpers.NugetResolvers;
|
||||
using Xamarin.Build;
|
||||
using MSBuildTaskItem = Microsoft.Build.Utilities.TaskItem;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.Tasks
|
||||
{
|
||||
public class XbhAndroidStudioProjectTask : AsyncTask
|
||||
{
|
||||
|
||||
[Required]
|
||||
public string IntermediateOutputPath { get; set; }
|
||||
|
||||
public ITaskItem[] Projects { get; set; }
|
||||
|
||||
public ITaskItem[] MavenNugetPairings { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] ResolvedArtifacts { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] NugetReferences { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] LocalAarArtifacts { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] LocalJarArtifacts { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] BindableLocalAars { get;set; }
|
||||
|
||||
[Required]
|
||||
public string TargetFrameworkPath { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DoExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Complete();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return base.Execute();
|
||||
}
|
||||
|
||||
async Task DoExecute()
|
||||
{
|
||||
var mappings = new List<ExplicitMavenNugetMapping>();
|
||||
|
||||
if (MavenNugetPairings != null)
|
||||
{
|
||||
foreach (var m in MavenNugetPairings)
|
||||
{
|
||||
var gid = m.GetMetadata("MavenGroupId");
|
||||
var aid = m.GetMetadata("MavenArtifactId");
|
||||
var mv = m.GetMetadata("MavenVersion");
|
||||
var nid = m.GetMetadata("NuGetPackageId");
|
||||
var nv = m.GetMetadata("NuGetVersion");
|
||||
|
||||
if (string.IsNullOrEmpty(gid))
|
||||
throw new ArgumentNullException("MavenNuGetMapping item is missing the 'MavenGroupId' attribute.");
|
||||
if (string.IsNullOrEmpty(aid))
|
||||
throw new ArgumentNullException("MavenNuGetMapping item is missing the 'MavenArtifactId' attribute.");
|
||||
if (string.IsNullOrEmpty(nid))
|
||||
throw new ArgumentNullException("MavenNuGetMapping item is missing the 'NuGetPackageId' attribute.");
|
||||
if (string.IsNullOrEmpty(nv))
|
||||
throw new ArgumentNullException("MavenNuGetMapping item is missing the 'NuGetVersion' attribute.");
|
||||
|
||||
mappings.Add(new ExplicitMavenNugetMapping(gid, aid, mv, nid, nv));
|
||||
}
|
||||
}
|
||||
|
||||
var bindableAars = new List<ITaskItem>();
|
||||
var allDeps = new List<MavenArtifactNuGetPairing>();
|
||||
|
||||
foreach (var p in Projects)
|
||||
{
|
||||
var projectPath = p.ItemSpec;
|
||||
var module = p.GetMetadata("Module");
|
||||
|
||||
if (string.IsNullOrEmpty(module))
|
||||
throw new ArgumentNullException("AndroidStudioProject item is missing the 'Module' attribute.");
|
||||
|
||||
var ap = new AndroidStudioProject(projectPath);
|
||||
|
||||
var projInfo = await ap.GetDependencies(module, mappings);
|
||||
allDeps.AddRange(projInfo.AllDependencies);
|
||||
|
||||
if (!string.IsNullOrEmpty(projInfo.ModuleArtifact))
|
||||
{
|
||||
bindableAars.Add(new MSBuildTaskItem(projInfo.ModuleArtifact, new Dictionary<string, string> {
|
||||
{
|
||||
"MavenIdentityHash",
|
||||
Convert.ToBase64String(System.Security.Cryptography.SHA256.Create().ComputeHash(
|
||||
Encoding.UTF8.GetBytes(projInfo.ModuleArtifact))).Substring(0, 8)
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
BindableLocalAars = bindableAars.ToArray();
|
||||
|
||||
var resolvedArtifacts = new List<MSBuildTaskItem>();
|
||||
var nugetReferences = new List<MSBuildTaskItem>();
|
||||
var localAarArtifacts = new List<MSBuildTaskItem>();
|
||||
var localJarArtifacts = new List<MSBuildTaskItem>();
|
||||
|
||||
var targetsArtifacts = new List<string>();
|
||||
|
||||
foreach (var d in allDeps)
|
||||
{
|
||||
var attr = new Dictionary<string, string>();
|
||||
string itemSpec = $"{d.MavenDependency.GroupId}:{d.MavenDependency.ArtifactId}:{d.MavenDependency.ResolvedVersion}";
|
||||
var artifactType = string.Empty;
|
||||
if (!string.IsNullOrEmpty(d.MavenDependency.GroupId))
|
||||
attr.Add("MavenGroupId", d.MavenDependency.GroupId);
|
||||
if (!string.IsNullOrEmpty(d.MavenDependency.ArtifactId))
|
||||
attr.Add("MavenArtifactId", d.MavenDependency.ArtifactId);
|
||||
if (!string.IsNullOrEmpty(d.MavenDependency.ArtifactId) && !string.IsNullOrEmpty(d.MavenDependency.GroupId))
|
||||
attr.Add("MavenIdentity", $"{d.MavenDependency.GroupId}.{d.MavenDependency.ArtifactId}");
|
||||
if (!string.IsNullOrEmpty(d.MavenDependency.ResolvedVersion))
|
||||
attr.Add("MavenVersion", d.MavenDependency.ResolvedVersion);
|
||||
if (!string.IsNullOrEmpty(d.MavenDependency.RequestedVersion))
|
||||
attr.Add("MavenRequestedVersion", d.MavenDependency.RequestedVersion);
|
||||
if (!string.IsNullOrEmpty(d.MavenDependency.File))
|
||||
{
|
||||
attr.Add("Path", d.MavenDependency.File);
|
||||
if (d.MavenDependency.IsAar || d.MavenDependency.IsJar)
|
||||
attr.Add("ArtifactType", d.MavenDependency.IsAar ? "aar" : "jar");
|
||||
}
|
||||
|
||||
if (d.NuGet != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(d.NuGet.PackageId))
|
||||
attr.Add("NuGetPackageId", d.NuGet.PackageId);
|
||||
if (!string.IsNullOrEmpty(d.NuGet.Version))
|
||||
attr.Add("NuGetVersion", d.NuGet.Version);
|
||||
|
||||
nugetReferences.Add(new MSBuildTaskItem(itemSpec, attr));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d.MavenDependency.IsAar)
|
||||
{
|
||||
localAarArtifacts.Add(new MSBuildTaskItem(itemSpec, attr));
|
||||
if (File.Exists(d.MavenDependency.File))
|
||||
targetsArtifacts.Add(Path.GetFileName(d.MavenDependency.File));
|
||||
}
|
||||
else if (d.MavenDependency.IsJar)
|
||||
localJarArtifacts.Add(new MSBuildTaskItem(itemSpec, attr));
|
||||
}
|
||||
|
||||
resolvedArtifacts.Add(new MSBuildTaskItem(itemSpec, attr));
|
||||
}
|
||||
|
||||
ResolvedArtifacts = resolvedArtifacts.ToArray();
|
||||
NugetReferences = nugetReferences.ToArray();
|
||||
LocalAarArtifacts = localAarArtifacts.ToArray();
|
||||
LocalJarArtifacts = localJarArtifacts.ToArray();
|
||||
|
||||
var fullIntermediateOutputPath = new DirectoryInfo(IntermediateOutputPath);
|
||||
if (!fullIntermediateOutputPath.Exists)
|
||||
fullIntermediateOutputPath.Create();
|
||||
|
||||
using (var w = new StreamWriter(Path.Combine(fullIntermediateOutputPath.FullName, "package.targets"), false))
|
||||
{
|
||||
w.WriteLine(@"<?xml version=""1.0"" encoding=""utf-8""?>");
|
||||
w.WriteLine(@"<Project ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">");
|
||||
w.WriteLine(" <ItemGroup>");
|
||||
|
||||
foreach (var a in targetsArtifacts)
|
||||
w.WriteLine(@" <AndroidAarLibrary Include=""$(MSBuildThisFileDirectory)..\..\build\" + TargetFrameworkPath + "\\" + a + "\" />");
|
||||
|
||||
w.WriteLine(" </ItemGroup>");
|
||||
w.WriteLine(@"</Project>");
|
||||
}
|
||||
|
||||
using (var w = new StreamWriter(Path.Combine(fullIntermediateOutputPath.FullName, "_xbhpackagerefs.txt")))
|
||||
{
|
||||
foreach (var d in allDeps)
|
||||
{
|
||||
if (d.NuGet != null && !string.IsNullOrEmpty(d.NuGet.PackageId) && !string.IsNullOrEmpty(d.NuGet.Version))
|
||||
w.WriteLine($"{d.NuGet.PackageId}|{d.NuGet.Version}");
|
||||
}
|
||||
}
|
||||
|
||||
using (var w = new StreamWriter(Path.Combine(fullIntermediateOutputPath.FullName, "_xbhartifacts.txt"), false))
|
||||
{
|
||||
foreach (var d in allDeps)
|
||||
{
|
||||
if (d.NuGet == null && d.MavenDependency != null && d.MavenDependency.IsAar)
|
||||
w.WriteLine($"{d.MavenDependency.File}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
using Microsoft.Build.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Build;
|
||||
using MSBuildTaskItem = Microsoft.Build.Utilities.TaskItem;
|
||||
|
||||
namespace Xamarin.Binding.Helpers.Tasks
|
||||
{
|
||||
public class XbhFetchBindingSuggestionsTask : AsyncTask
|
||||
{
|
||||
public ITaskItem[] Projects { get; set; }
|
||||
|
||||
[Output]
|
||||
public ITaskItem[] AndroidAars { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await DoExecute();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.LogErrorFromException(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Complete();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return base.Execute();
|
||||
}
|
||||
|
||||
async Task DoExecute()
|
||||
{
|
||||
var aars = new List<MSBuildTaskItem>();
|
||||
|
||||
foreach (var proj in Projects)
|
||||
{
|
||||
var intermediateOutputPath = proj.GetMetadata("IntermediateOutputPath");
|
||||
|
||||
var packageRefs = Path.Combine(intermediateOutputPath, "xbh", "_xbhpackagerefs.txt");
|
||||
|
||||
var pkgRefs = new List<NuGetSuggestion>();
|
||||
|
||||
// PackageId|Version
|
||||
if (File.Exists(packageRefs))
|
||||
{
|
||||
var lines = File.ReadAllLines(packageRefs) ?? new string[0];
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
|
||||
var parts = line?.Split(new[] { '|' }, 2);
|
||||
if ((parts?.Length ?? 0) == 2)
|
||||
pkgRefs.Add(new NuGetSuggestion
|
||||
{
|
||||
PackageId = parts[0],
|
||||
Version = parts[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var artifacts = Path.Combine(intermediateOutputPath, "_xbhartifacts.txt");
|
||||
|
||||
if (File.Exists(artifacts))
|
||||
{
|
||||
var lines = File.ReadAllLines(artifacts) ?? new string[0];
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
|
||||
aars.Add(new MSBuildTaskItem(line));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AndroidAars = aars.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
|
||||
<PackageId>Xamarin.Binding.Helpers</PackageId>
|
||||
<Title>Xamarin Binding Helpers</Title>
|
||||
<Version>0.1</Version>
|
||||
<Authors>Redth</Authors>
|
||||
<Owners>Redth</Owners>
|
||||
<summary>Add helpful functionality to your Xamarin.iOS and Xamarin.Android binding projects.</summary>
|
||||
<PackageDescription>
|
||||
Add helpful functionality to your Xamarin.iOS and Xamarin.Android binding projects.
|
||||
</PackageDescription>
|
||||
<Copyright>Copyright © Redth</Copyright>
|
||||
<PackageProjectUrl>https://github.com/redth/Resizetizer</PackageProjectUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryUrl>https://github.com/redth/ResizetizerNT</RepositoryUrl>
|
||||
<PackageOutputPath>..\output</PackageOutputPath>
|
||||
<IncludeBuildOutput>False</IncludeBuildOutput>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NuGet.Protocol" Version="5.8.0" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
<PackageReference Include="NuGet.Packaging" Version="5.8.0" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
<PackageReference Include="NuGet.Configuration" Version="5.8.0" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
<PackageReference Include="NuGet.Versioning" Version="5.8.0" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
<PackageReference Include="NuGet.Common" Version="5.8.0" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
<PackageReference Include="NuGet.Frameworks" Version="5.8.0" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="16.6.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.6.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Xamarin.Build.AsyncTask" Version="0.3.4" PrivateAssets="all" GeneratePathProperty="true" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="$(TargetPath)" Pack="True" PackagePath="build\" />
|
||||
<None Include="$(TargetPath)" Pack="True" PackagePath="buildMultitargeting\" />
|
||||
<Content Include="Xamarin.Binding.Helpers.targets" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Xamarin.Binding.Helpers.multitargeting.targets" Pack="True" PackagePath="buildMultitargeting\Xamarin.Binding.Helpers.targets">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="$(PkgNuGet_Protocol)\lib\netstandard2.0\NuGet.Protocol.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PkgNuGet_Packaging)\lib\netstandard2.0\NuGet.Packaging.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PkgNuGet_Configuration)\lib\netstandard2.0\NuGet.Configuration.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PkgNuGet_Versioning)\lib\netstandard2.0\NuGet.Versioning.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PkgNuGet_Common)\lib\netstandard2.0\NuGet.Common.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PkgNuGet_Frameworks)\lib\netstandard2.0\NuGet.Frameworks.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PkgXamarin_Build_AsyncTask)\lib\netstandard2.0\Xamarin.Build.AsyncTask.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="$(PkgNewtonsoft_Json)\lib\netstandard2.0\Newtonsoft.Json.dll" Visible="False" Pack="True" PackagePath="build\">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="$(TargetPath)" Pack="True" PackagePath="buildTransitive\" />
|
||||
<Content Include="Xamarin.Binding.Helpers.targets" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgNuGet_Protocol)\lib\netstandard2.0\NuGet.Protocol.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgNuGet_Packaging)\lib\netstandard2.0\NuGet.Packaging.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgNuGet_Configuration)\lib\netstandard2.0\NuGet.Configuration.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgNuGet_Versioning)\lib\netstandard2.0\NuGet.Versioning.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgNuGet_Common)\lib\netstandard2.0\NuGet.Common.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgNuGet_Frameworks)\lib\netstandard2.0\NuGet.Frameworks.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgXamarin_Build_AsyncTask)\lib\netstandard2.0\Xamarin.Build.AsyncTask.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
<None Include="$(PkgNewtonsoft_Json)\lib\netstandard2.0\Newtonsoft.Json.dll" Visible="False" Pack="True" PackagePath="buildTransitive\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<UsingTask
|
||||
AssemblyFile="Xamarin.Binding.Helpers.dll"
|
||||
TaskName="Xamarin.Binding.Helpers.Tasks.XbhAddDependenciesToNupkgTask" />
|
||||
|
||||
<Target Name="_XbhAddDependenciesToNupkgTask"
|
||||
AfterTargets="GenerateNuspec">
|
||||
|
||||
<XbhAddDependenciesToNupkgTask
|
||||
IntermediateOutputPath="$(IntermediateOutputPath)"
|
||||
NuGetPackOutput="@(NuGetPackOutput)"
|
||||
TargetFrameworks="@(_TargetFrameworks)"
|
||||
/>
|
||||
|
||||
</Target>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,152 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<ItemGroup>
|
||||
<AvailableItemName Include="AndroidStudioProject" />
|
||||
<AvailableItemName Include="MavenNuGetMapping" />
|
||||
</ItemGroup>
|
||||
|
||||
<UsingTask
|
||||
AssemblyFile="Xamarin.Binding.Helpers.dll"
|
||||
TaskName="Xamarin.Binding.Helpers.Tasks.XbhAndroidStudioProjectTask" />
|
||||
|
||||
<UsingTask
|
||||
AssemblyFile="Xamarin.Binding.Helpers.dll"
|
||||
TaskName="Xamarin.Binding.Helpers.Tasks.XbhFetchBindingSuggestionsTask" />
|
||||
|
||||
<PropertyGroup>
|
||||
<CleanDependsOn>
|
||||
$(CleanDependsOn);
|
||||
_CleanXbh;
|
||||
</CleanDependsOn>
|
||||
|
||||
<_XbhIntermediateOutputPath>$(IntermediateOutputPath)xbh\</_XbhIntermediateOutputPath>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Hack to include our tasks -->
|
||||
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);_XbhBuildAndroidStudioProjects</TargetsForTfmSpecificContentInPackage>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="_XbhBuildAndroidStudioProjects"
|
||||
BeforeTargets="_ResolveLibraryProjectImports;Pack"
|
||||
Condition="'@(AndroidStudioProject)' != ''">
|
||||
|
||||
<GetNuGetShortFolderName
|
||||
TargetFrameworkMoniker="$(TargetFrameworkMoniker)"
|
||||
TargetPlatformMoniker="$(TargetPlatformMoniker)">
|
||||
<Output TaskParameter="NuGetShortFolderName" PropertyName="_NuGetShortFolderName" />
|
||||
</GetNuGetShortFolderName>
|
||||
|
||||
<!--
|
||||
Executes several gradle tasks for the given project and module:
|
||||
1. bundleReleaseAar
|
||||
2. dependencies configuration implementation
|
||||
3. fetchXamarinBindingInfo
|
||||
This parses out the dependency tree, finds the built aar, and tries to
|
||||
match up which nugets we can use, or pulls the .aar/.jar locally if we can't find one
|
||||
-->
|
||||
<XbhAndroidStudioProjectTask
|
||||
Projects="@(AndroidStudioProject)"
|
||||
IntermediateOutputPath="$(_XbhIntermediateOutputPath)"
|
||||
MavenNugetPairings="@(MavenNugetMapping)"
|
||||
TargetFrameworkPath="$(_NuGetShortFolderName)">
|
||||
<Output TaskParameter="ResolvedArtifacts" ItemName="_XbhAndroidStudioProjectResolvedArtifacts" />
|
||||
<Output TaskParameter="NugetReferences" ItemName="_XbhAndroidStudioProjectNugetReferences" />
|
||||
<Output TaskParameter="LocalAarArtifacts" ItemName="_XbhAndroidStudioProjectLocalAarArtifacts" />
|
||||
<Output TaskParameter="LocalJarArtifacts" ItemName="_XbhAndroidStudioProjectLocalJarArtifacts" />
|
||||
<Output TaskParameter="BindableLocalAars" ItemName="_XbhAndroidStudioProjectBindableLocalAars" />
|
||||
</XbhAndroidStudioProjectTask>
|
||||
|
||||
<!-- Copy all the .jar artifacts to an obj intermediate dir -->
|
||||
<Copy
|
||||
SourceFiles="@(_XbhAndroidStudioProjectLocalJarArtifacts->'%(Path)')"
|
||||
DestinationFolder="$(_XbhIntermediateOutputPath)\artifacts\"
|
||||
SkipUnchangedFiles="True" />
|
||||
|
||||
<!-- Copy all the .aar artifacts to an obj intermediate dir -->
|
||||
<Copy
|
||||
SourceFiles="@(_XbhAndroidStudioProjectLocalAarArtifacts->'%(Path)')"
|
||||
DestinationFolder="$(_XbhIntermediateOutputPath)\artifacts\"
|
||||
SkipUnchangedFiles="True" />
|
||||
|
||||
<!-- Copy all the bindable .aar artifacts to an obj intermediate dir -->
|
||||
<Copy
|
||||
SourceFiles="@(_XbhAndroidStudioProjectBindableLocalAars->'%(Identity)')"
|
||||
DestinationFolder="$(_XbhIntermediateOutputPath)\artifacts\"
|
||||
SkipUnchangedFiles="True" />
|
||||
|
||||
<!-- Unzip all of the .aar's -->
|
||||
<Microsoft.Build.Tasks.Unzip
|
||||
Condition="'@_XbhAndroidStudioProjectLocalAarArtifacts' != ''"
|
||||
SourceFiles="%(_XbhAndroidStudioProjectLocalAarArtifacts.Path)"
|
||||
DestinationFolder="$(_XbhIntermediateOutputPath)\artifacts\%(_XbhAndroidStudioProjectLocalAarArtifacts.MavenIdentity)"
|
||||
SkipUnchangedFiles="True" />
|
||||
|
||||
<!-- Unzip all of the bindable .aar's -->
|
||||
<Microsoft.Build.Tasks.Unzip
|
||||
Condition="'@_XbhAndroidStudioProjectBindableLocalAars' != ''"
|
||||
SourceFiles="%(_XbhAndroidStudioProjectBindableLocalAars.Identity)"
|
||||
DestinationFolder="$(_XbhIntermediateOutputPath)\artifacts\%(_XbhAndroidStudioProjectBindableLocalAars.MavenIdentityHash)"
|
||||
SkipUnchangedFiles="True" />
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Add the .jar's for the bindable .aar's to actually have bindings generated for -->
|
||||
<InputJar Include="$(_XbhIntermediateOutputPath)\artifacts\%(_XbhAndroidStudioProjectBindableLocalAars.MavenIdentityHash)\*.jar" />
|
||||
|
||||
<!-- Add the .jar's from all the other .aar's to have their .jar's available for the binding generator -->
|
||||
<ReferenceJar Include="$(_XbhIntermediateOutputPath)\artifacts\%(_XbhAndroidStudioProjectLocalAarArtifacts.MavenIdentity)\*.jar" />
|
||||
|
||||
<!-- We can simply embed the .jar's that are also to be referenced by the .aar we are binding -->
|
||||
<!-- Eventually we should package these just like .aar's in the nuget and use ReferenceJar instead here -->
|
||||
<EmbeddedReferenceJar Include="$(_XbhIntermediateOutputPath)\artifacts\*.jar" />
|
||||
|
||||
<!-- Add all the artifacts to the nuget package generated -->
|
||||
<TfmSpecificPackageFile Include="$(_XbhIntermediateOutputPath)\artifacts\*.aar" Pack="True" PackagePath="build\$(_NuGetShortFolderName)" />
|
||||
|
||||
<!-- Add the .targets file we generate with AndroidAarLibrary items into the nupkg -->
|
||||
<TfmSpecificPackageFile Include="$(_XbhIntermediateOutputPath)\package.targets" Pack="True" PackagePath="build\$(_NuGetShortFolderName)\$(PackageId).targets" />
|
||||
<TfmSpecificPackageFile Include="$(_XbhIntermediateOutputPath)\package.targets" Pack="True" PackagePath="buildTransitive\$(_NuGetShortFolderName)\$(PackageId).targets" />
|
||||
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
|
||||
<Target Name="_XbhFetchXamarinAndroidBindingHelperSuggestions"
|
||||
Condition="'@(ProjectReference)' != ''"
|
||||
BeforeTargets="_ResolveLibraryProjectImports">
|
||||
|
||||
<MSBuild
|
||||
Targets="_XbhGetProjectIntermediateOutputPath"
|
||||
Projects="@(ProjectReference)"
|
||||
SkipNonexistentProjects="true"
|
||||
SkipNonexistentTargets="true">
|
||||
<Output
|
||||
TaskParameter="TargetOutputs"
|
||||
ItemName="_XbhPackageRefsFile" />
|
||||
</MSBuild>
|
||||
|
||||
<XbhFetchBindingSuggestionsTask
|
||||
Projects="@(ProjectReference)">
|
||||
<Output TaskParameter="AndroidAars" ItemName="AndroidAarLibrary" />
|
||||
</XbhFetchBindingSuggestionsTask>
|
||||
|
||||
</Target>
|
||||
|
||||
<Target Name="_XbhGetProjectIntermediateOutputPath" Outputs="@(_XbhPackageRefsFile)">
|
||||
<ItemGroup>
|
||||
<_XbhPackageRefsFile Include="$(IntermediateOutputPath)\xbh\_xbhpackagerefs.txt" />
|
||||
</ItemGroup>
|
||||
<Message Text="Project Intermediate Output Path: $(IntermediateOutputPath)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_CleanXbh">
|
||||
<PropertyGroup>
|
||||
<_XbhIntermediateOutputPath>$(IntermediateOutputPath)xbh\</_XbhIntermediateOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<RemoveDir Directories="$(_XbhIntermediateOutputPath)" Condition="Exists ('$(_XbhIntermediateOutputPath)' )" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
New-Item -ItemType Directory -Path .\logs\ -Force
|
||||
New-Item -ItemType Directory -Path .\output\ -Force
|
||||
|
||||
& msbuild /t:Restore .\Xamarin.Binding.Helpers\Xamarin.Binding.Helpers.csproj
|
||||
& msbuild /t:Rebuild .\Xamarin.Binding.Helpers\Xamarin.Binding.Helpers.csproj /bl:logs\xbh.binlog
|
||||
|
||||
Remove-Item .\Samples\packages\xamarin.binding.helpers -Force -Recurse
|
||||
|
||||
# Run restore/rebuilds
|
||||
& msbuild /t:Restore .\Samples\SampleAndroidBinding\SampleAndroidBinding.csproj
|
||||
& msbuild /t:Rebuild .\Samples\SampleAndroidBinding\SampleAndroidBinding.csproj /bl:logs\android.binlog
|
||||
& msbuild /t:Pack .\Samples\SampleAndroidBinding\SampleAndroidBinding.csproj /bl:logs\android-pack.binlog
|
||||
|
||||
& msbuild /r /t:Rebuild .\Samples\SampleAndroidApp\SampleAndroidApp.csproj /bl:logs\android-app.binlog
|
||||
|