Implementato sdk honeywell e metodi per lo scanner barcode

This commit is contained in:
2026-02-24 17:49:25 +01:00
parent e8adb76256
commit 7fa96eeb09
27 changed files with 477 additions and 53 deletions

View File

@@ -1,5 +1,4 @@
using System.Data; using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using SteUp.Data.LocalDb; using SteUp.Data.LocalDb;
@@ -7,6 +6,8 @@ using SteUp.Data.LocalDb.EntityServices;
using SteUp.Maui.Core.Services; using SteUp.Maui.Core.Services;
using SteUp.Maui.Core.System; using SteUp.Maui.Core.System;
using SteUp.Maui.Core.System.Network; using SteUp.Maui.Core.System.Network;
using SteUp.Shared.Core.BarcodeReader;
using SteUp.Shared.Core.BarcodeReader.Contracts;
using SteUp.Shared.Core.Data; using SteUp.Shared.Core.Data;
using SteUp.Shared.Core.Data.Contracts; using SteUp.Shared.Core.Data.Contracts;
using SteUp.Shared.Core.Interface; using SteUp.Shared.Core.Interface;
@@ -14,6 +15,7 @@ using SteUp.Shared.Core.Interface.IntegryApi;
using SteUp.Shared.Core.Interface.LocalDb; using SteUp.Shared.Core.Interface.LocalDb;
using SteUp.Shared.Core.Interface.System; using SteUp.Shared.Core.Interface.System;
using SteUp.Shared.Core.Interface.System.Network; using SteUp.Shared.Core.Interface.System.Network;
using SteUp.Shared.Core.Messages.Scanner;
using SteUp.Shared.Core.Messages.Scheda; using SteUp.Shared.Core.Messages.Scheda;
using SteUp.Shared.Core.Services; using SteUp.Shared.Core.Services;
@@ -21,27 +23,31 @@ namespace SteUp.Maui.Core;
public static class CoreModule public static class CoreModule
{ {
public static void RegisterAppServices(this MauiAppBuilder builder) extension(MauiAppBuilder builder)
{
public void RegisterAppServices()
{ {
builder.Services.AddSingleton<IFormFactor, FormFactor>(); builder.Services.AddSingleton<IFormFactor, FormFactor>();
builder.Services.AddSingleton<IGenericSystemService, GenericSystemService>(); builder.Services.AddSingleton<IGenericSystemService, GenericSystemService>();
builder.Services.AddScoped<ISteupDataService, SteupDataService>(); builder.Services.AddScoped<ISteupDataService, SteupDataService>();
builder.Services.AddSingleton<IBarcodeManager, BarcodeManager>();
} }
public static void RegisterIntegryServices(this MauiAppBuilder builder) public void RegisterIntegryServices()
{ {
builder.Services.AddScoped<IIntegryApiService, IntegryApiService>(); builder.Services.AddScoped<IIntegryApiService, IntegryApiService>();
builder.Services.AddScoped<IIntegrySteupService, IntegrySteupService>(); builder.Services.AddScoped<IIntegrySteupService, IntegrySteupService>();
} }
public static void RegisterSystemService(this MauiAppBuilder builder) public void RegisterSystemService()
{ {
builder.Services.AddSingleton<INetworkService, NetworkService>(); builder.Services.AddSingleton<INetworkService, NetworkService>();
builder.Services.AddSingleton<IAttachedService, AttachedService>(); builder.Services.AddSingleton<IAttachedService, AttachedService>();
builder.Services.AddSingleton<IBarcodeReaderService, HoneywellScannerService>();
} }
public static void AddAuthorizationCore(this MauiAppBuilder builder) public void AddAuthorizationCore()
{ {
builder.Services.AddAuthorizationCore(); builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AppAuthenticationStateProvider>(); builder.Services.AddScoped<AppAuthenticationStateProvider>();
@@ -49,13 +55,14 @@ public static class CoreModule
provider.GetRequiredService<AppAuthenticationStateProvider>()); provider.GetRequiredService<AppAuthenticationStateProvider>());
} }
public static void RegisterMessageServices(this MauiAppBuilder builder) public void RegisterMessageServices()
{ {
builder.Services.AddSingleton<IMessenger, WeakReferenceMessenger>(); builder.Services.AddSingleton<IMessenger, WeakReferenceMessenger>();
builder.Services.AddSingleton<NewSchedaService>(); builder.Services.AddSingleton<NewSchedaService>();
builder.Services.AddSingleton<OnScannerService>();
} }
public static void RegisterDbServices(this MauiAppBuilder builder) public void RegisterDbServices()
{ {
builder.Services.AddSingleton<IDbPathProvider, DbPathProvider>(); builder.Services.AddSingleton<IDbPathProvider, DbPathProvider>();
builder.Services.AddDbContext<AppDbContext>((sp, options) => builder.Services.AddDbContext<AppDbContext>((sp, options) =>
@@ -66,4 +73,5 @@ public static class CoreModule
builder.Services.AddSingleton<IDbInitializer, DbInitializer>(); builder.Services.AddSingleton<IDbInitializer, DbInitializer>();
builder.Services.AddSingleton<IIspezioniService, IspezioniService>(); builder.Services.AddSingleton<IIspezioniService, IspezioniService>();
} }
}
} }

View File

@@ -0,0 +1,24 @@
using SteUp.Shared.Core.BarcodeReader.Contracts;
using SteUp.Shared.Core.BarcodeReader.Dto;
using SteUp.Shared.Core.Interface.System;
namespace SteUp.Maui.Core.System;
public partial class HoneywellScannerService : IBarcodeReaderService
{
protected Action<BarcodeScanDto>? OnScanSuccessful;
protected Action<Exception>? OnScanFailed;
public partial bool IsRightAdapter();
public partial void Init(Action onDeviceReady);
public partial void Deinit();
public partial string GetAdapterName();
public partial void OnKeyEvent(object keyEvent);
public partial void ChangeSettings(List<(string Key, object Value)> settings);
public void Register(Action<BarcodeScanDto> onScanSuccessful, Action<Exception> onScanFailed)
{
OnScanSuccessful = onScanSuccessful;
OnScanFailed = onScanFailed;
}
}

View File

@@ -0,0 +1,140 @@
using Android.OS;
using Com.Honeywell.Aidc;
using SteUp.Shared.Core.BarcodeReader.Dto;
namespace SteUp.Maui.Core.System;
public partial class HoneywellScannerService
{
private AidcManager? _aidcManager;
private BarcodeReader? _barcodeReader;
private static readonly List<string> CompatibleModels = ["EDA50", "EDA51", "EDA52", "CT60"];
public partial bool IsRightAdapter()
{
return CompatibleModels.Contains(Build.Model ?? string.Empty);
}
public partial string GetAdapterName() => "Honeywell";
public partial void Init(Action onDeviceReady)
{
if (!IsRightAdapter())
throw new Exception($"Adapter non trovato per il modello: {Build.Model}");
AidcManager.Create(
Android.App.Application.Context,
new AidcCreatedCallback(this, onDeviceReady)
);
}
public partial void Deinit()
{
_barcodeReader?.Close();
_barcodeReader = null;
_aidcManager?.Close();
_aidcManager = null;
}
public partial void OnKeyEvent(object keyEvent)
{
// Honeywell gestisce il trigger hardware internamente, non serve implementazione
}
public partial void ChangeSettings(List<(string Key, object Value)> settings)
{
if (_barcodeReader == null) return;
var properties = GetDefaultProperties();
foreach (var (key, value) in settings)
{
switch (key)
{
case "TRIGGER_SCAN_MODE":
var scanMode = (string)value switch
{
"ONE_SHOT" => BarcodeReader.TriggerScanModeOneshot,
"CONTINUOUS" => BarcodeReader.TriggerScanModeContinuous,
"READ_ON_SECOND_TRIGGER_PRESS" => BarcodeReader.TriggerScanModeReadOnSecondTriggerPress,
"READ_ON_RELEASE" => BarcodeReader.TriggerScanModeReadOnRelease,
_ => BarcodeReader.TriggerScanModeOneshot
};
properties[BarcodeReader.PropertyTriggerScanMode] = scanMode!;
break;
case "TRIGGER_SCAN_DELAY":
properties[BarcodeReader.PropertyTriggerScanDelay] = int.Parse((string)value);
break;
}
}
_barcodeReader.SetProperties(properties);
try { _barcodeReader.Claim(); }
catch (ScannerUnavailableException ex) { OnScanFailed?.Invoke(ex); }
}
private void RegisterListenersInternal()
{
_barcodeReader?.AddBarcodeListener(new BarcodeEventListener(this));
}
private void DispatchEvent(BarcodeReadEvent e)
{
var dto = new BarcodeScanDto
{
StringValue = e.BarcodeData,
Type = e.CodeId,
Name = e.CodeId
};
OnScanSuccessful?.Invoke(dto);
}
private static Dictionary<string, Java.Lang.Object> GetDefaultProperties() => new()
{
{ BarcodeReader.PropertyEan8Enabled, true },
{ BarcodeReader.PropertyEan13Enabled, true },
{ BarcodeReader.PropertyCode39Enabled, true },
{ BarcodeReader.PropertyCode128Enabled, true },
{ BarcodeReader.PropertyGs1128Enabled, true },
{ BarcodeReader.PropertyUpcAEnable, true },
{ BarcodeReader.PropertyEan8CheckDigitTransmitEnabled, true },
{ BarcodeReader.PropertyEan13CheckDigitTransmitEnabled, true },
{ BarcodeReader.PropertyUpcACheckDigitTransmitEnabled, true }
};
private class AidcCreatedCallback(HoneywellScannerService service, Action onDeviceReady)
: Java.Lang.Object, AidcManager.ICreatedCallback
{
public void OnCreated(AidcManager? manager)
{
service._aidcManager = manager;
try
{
if (manager == null) throw new Exception("AidcManager null");
service._barcodeReader = manager.CreateBarcodeReader();
service.RegisterListenersInternal();
}
catch (Exception ex)
{
service.OnScanFailed?.Invoke(ex);
}
onDeviceReady.Invoke();
}
}
private class BarcodeEventListener(HoneywellScannerService service)
: Java.Lang.Object, BarcodeReader.IBarcodeListener
{
public void OnBarcodeEvent(BarcodeReadEvent? e) => service.DispatchEvent(e!);
public void OnFailureEvent(BarcodeFailureEvent? e) =>
service.OnScanFailed?.Invoke(new Exception($"Scan failure: {e}"));
}
}

View File

@@ -0,0 +1,17 @@
namespace SteUp.Maui.Core.System;
public partial class HoneywellScannerService
{
public partial bool IsRightAdapter() => false;
public partial void Init(Action onDeviceReady) =>
throw new NotSupportedException("Honeywell SDK non disponibile su iOS.");
public partial void Deinit() { }
public partial string GetAdapterName() => "Honeywell";
public partial void OnKeyEvent(object keyEvent) { }
public partial void ChangeSettings(List<(string Key, object Value)> settings) { }
}

View File

@@ -124,6 +124,10 @@
<PackageReference Include="SkiaSharp" Version="3.119.2" /> <PackageReference Include="SkiaSharp" Version="3.119.2" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<ProjectReference Include="..\Steup.HoneywellScanner\Steup.HoneywellScanner.csproj" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SteUp.Shared\SteUp.Shared.csproj" /> <ProjectReference Include="..\SteUp.Shared\SteUp.Shared.csproj" />
<ProjectReference Include="..\SteUp.Data\SteUp.Data.csproj" /> <ProjectReference Include="..\SteUp.Data\SteUp.Data.csproj" />

View File

@@ -1,10 +1,12 @@
@page "/login" @page "/login"
@using SteUp.Shared.Components.Layout.Spinner @using SteUp.Shared.Components.Layout.Spinner
@using SteUp.Shared.Core.BarcodeReader.Contracts
@using SteUp.Shared.Core.Interface.System @using SteUp.Shared.Core.Interface.System
@using SteUp.Shared.Core.Services @using SteUp.Shared.Core.Services
@inject IUserAccountService UserAccountService @inject IUserAccountService UserAccountService
@inject AppAuthenticationStateProvider AuthenticationStateProvider @inject AppAuthenticationStateProvider AuthenticationStateProvider
@inject IGenericSystemService GenericSystemService @inject IGenericSystemService GenericSystemService
@inject IBarcodeManager BarcodeManager
@if (Spinner) @if (Spinner)
{ {
@@ -90,6 +92,7 @@ else
await UserAccountService.Login(UserData.Username, UserData.Password, UserData.CodHash); await UserAccountService.Login(UserData.Username, UserData.Password, UserData.CodHash);
AuthenticationStateProvider.NotifyAuthenticationState(); //Chiamato per forzare il refresh AuthenticationStateProvider.NotifyAuthenticationState(); //Chiamato per forzare il refresh
await SteupDataService.Init(); await SteupDataService.Init();
BarcodeManager.Init();
LocalStorage.SetString("codHash", UserData.CodHash); LocalStorage.SetString("codHash", UserData.CodHash);
NavigationManager.NavigateTo("/"); NavigationManager.NavigateTo("/");

View File

@@ -1,5 +1,7 @@
@using SteUp.Shared.Components.SingleElements.Modal.ExceptionModal @using SteUp.Shared.Components.SingleElements.Modal.ExceptionModal
@using SteUp.Shared.Core.BarcodeReader.Contracts
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@inject IBarcodeManager BarcodeManager
<ErrorBoundary @ref="ErrorBoundary"> <ErrorBoundary @ref="ErrorBoundary">
<ChildContent> <ChildContent>
@@ -43,5 +45,6 @@
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
await SteupDataService.Init(); await SteupDataService.Init();
BarcodeManager.Init();
} }
} }

View File

@@ -1,6 +1,6 @@
.card-form-modal { .card-form-modal {
background: var(--mud-palette-table-striped); background: var(--mud-palette-table-striped);
border-radius: 1em; border-radius: 20px;
padding: .5rem 1rem; padding: .5rem 1rem;
width: -webkit-fill-available; width: -webkit-fill-available;
} }

View File

@@ -8,11 +8,13 @@
@using SteUp.Shared.Core.Interface.LocalDb @using SteUp.Shared.Core.Interface.LocalDb
@using SteUp.Shared.Core.Interface.System @using SteUp.Shared.Core.Interface.System
@using SteUp.Shared.Core.Interface.System.Network @using SteUp.Shared.Core.Interface.System.Network
@using SteUp.Shared.Core.Messages.Scanner
@inject INetworkService NetworkService @inject INetworkService NetworkService
@inject IDialogService Dialog @inject IDialogService Dialog
@inject IIntegryApiService IntegryApiService @inject IIntegryApiService IntegryApiService
@inject IAttachedService AttachedService @inject IAttachedService AttachedService
@inject IIspezioniService IspezioniService @inject IIspezioniService IspezioniService
@inject OnScannerService OnScannerService
<MudDialog Class="customDialog-form"> <MudDialog Class="customDialog-form">
<DialogContent> <DialogContent>
@@ -159,6 +161,9 @@
protected override void OnInitialized() protected override void OnInitialized()
{ {
OnScannerService.OnNewScanSuccessful += OnNewScanSuccessful;
OnScannerService.OnErrorScan += OnErrorScan;
_originalScheda = Scheda.Clone(); _originalScheda = Scheda.Clone();
Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter; Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;
@@ -419,4 +424,19 @@
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
}); });
} }
#region Scanner
public static void OnNewScanSuccessful(string? value)
{
//To be implemented
}
private static void OnErrorScan(string? value)
{
//To be implemented
}
#endregion
} }

View File

@@ -0,0 +1,32 @@
using CommunityToolkit.Mvvm.Messaging;
using SteUp.Shared.Core.BarcodeReader.Contracts;
using SteUp.Shared.Core.Messages.Scanner;
namespace SteUp.Shared.Core.BarcodeReader;
public class BarcodeManager(
IBarcodeReaderService scanner,
IMessenger messenger) : IBarcodeManager
{
public void Init()
{
if (!scanner.IsRightAdapter())
{
Console.WriteLine("Dispositivo non compatibile con lo scanner Honeywell.");
return;
}
scanner.Register(
onScanSuccessful: dto =>
{
messenger.Send(new NewScannerMessage(dto.StringValue));
},
onScanFailed: ex =>
{
messenger.Send(new ErrorScannerMessage(ex.Message));
}
);
scanner.Init(() => { scanner.ChangeSettings([("TRIGGER_SCAN_MODE", "ONE_SHOT")]); });
}
}

View File

@@ -0,0 +1,6 @@
namespace SteUp.Shared.Core.BarcodeReader.Contracts;
public interface IBarcodeManager
{
void Init();
}

View File

@@ -0,0 +1,14 @@
using SteUp.Shared.Core.BarcodeReader.Dto;
namespace SteUp.Shared.Core.BarcodeReader.Contracts;
public interface IBarcodeReaderService
{
bool IsRightAdapter();
void Init(Action onDeviceReady);
void Deinit();
void Register(Action<BarcodeScanDto> onScanSuccessful, Action<Exception> onScanFailed);
string GetAdapterName();
void OnKeyEvent(object keyEvent);
void ChangeSettings(List<(string Key, object Value)> settings);
}

View File

@@ -0,0 +1,8 @@
namespace SteUp.Shared.Core.BarcodeReader.Dto;
public class BarcodeScanDto
{
public string? StringValue { get; set; }
public string? Type { get; set; }
public string? Name { get; set; }
}

View File

@@ -1,5 +1,6 @@
using IntegryApiClient.Core.Domain.Abstraction.Contracts.Account; using IntegryApiClient.Core.Domain.Abstraction.Contracts.Account;
using IntegryApiClient.Core.Domain.Abstraction.Contracts.Device; using IntegryApiClient.Core.Domain.Abstraction.Contracts.Device;
using SteUp.Shared.Core.BarcodeReader.Contracts;
using SteUp.Shared.Core.Data.Contracts; using SteUp.Shared.Core.Data.Contracts;
using SteUp.Shared.Core.Dto; using SteUp.Shared.Core.Dto;
using SteUp.Shared.Core.Dto.PageState; using SteUp.Shared.Core.Dto.PageState;

View File

@@ -0,0 +1,5 @@
using CommunityToolkit.Mvvm.Messaging.Messages;
namespace SteUp.Shared.Core.Messages.Scanner;
public class ErrorScannerMessage(string? value = null) : ValueChangedMessage<string?>(value);

View File

@@ -0,0 +1,5 @@
using CommunityToolkit.Mvvm.Messaging.Messages;
namespace SteUp.Shared.Core.Messages.Scanner;
public class NewScannerMessage(string? value = null) : ValueChangedMessage<string?>(value);

View File

@@ -0,0 +1,15 @@
using CommunityToolkit.Mvvm.Messaging;
namespace SteUp.Shared.Core.Messages.Scanner;
public class OnScannerService
{
public event Action<string?>? OnNewScanSuccessful;
public event Action<string?>? OnErrorScan;
public OnScannerService(IMessenger messenger)
{
messenger.Register<NewScannerMessage>(this, (_, x) => { OnNewScanSuccessful?.Invoke(x.Value); });
messenger.Register<ErrorScannerMessage>(this, (_, x) => { OnErrorScan?.Invoke(x.Value); });
}
}

View File

@@ -197,7 +197,7 @@ h1:focus {
aspect-ratio: 1; aspect-ratio: 1;
border-radius: 50%; border-radius: 50%;
border: 8px solid #0000; border: 8px solid #0000;
border-right-color: var(--mud-palette-secondary); border-right-color: var(--mud-palette-primary);
position: relative; position: relative;
animation: l24 1s infinite linear; animation: l24 1s infinite linear;
} }

View File

@@ -26,14 +26,8 @@ function monitorBottomSheetClass(mutations) {
}); });
} }
// Esegui la funzione tabindex inizialmente
addTabindexToButtons();
// Observer combinato per tutte le funzionalità // Observer combinato per tutte le funzionalità
const observer = new MutationObserver((mutations) => { const observer = new MutationObserver((mutations) => {
// Aggiungi tabindex ai nuovi bottoni
addTabindexToButtons();
// Monitora bottom-sheet-container // Monitora bottom-sheet-container
monitorBottomSheetClass(mutations); monitorBottomSheetClass(mutations);
}); });

View File

@@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteUp.Web", "SteUp.Web\SteU
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SteUp.Data", "SteUp.Data\SteUp.Data.csproj", "{A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SteUp.Data", "SteUp.Data\SteUp.Data.csproj", "{A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Steup.HoneywellScanner", "Steup.HoneywellScanner\Steup.HoneywellScanner.csproj", "{49E17405-466C-44AC-9F85-E2A4DB149170}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -71,6 +73,18 @@ Global
{A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}.Release|x64.Build.0 = Release|Any CPU {A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}.Release|x64.Build.0 = Release|Any CPU
{A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}.Release|x86.ActiveCfg = Release|Any CPU {A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}.Release|x86.ActiveCfg = Release|Any CPU
{A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}.Release|x86.Build.0 = Release|Any CPU {A1AB9749-A367-4E5C-8A80-2D4CEF68DA59}.Release|x86.Build.0 = Release|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Debug|Any CPU.Build.0 = Debug|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Debug|x64.ActiveCfg = Debug|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Debug|x64.Build.0 = Debug|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Debug|x86.ActiveCfg = Debug|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Debug|x86.Build.0 = Debug|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Release|Any CPU.ActiveCfg = Release|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Release|Any CPU.Build.0 = Release|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Release|x64.ActiveCfg = Release|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Release|x64.Build.0 = Release|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Release|x86.ActiveCfg = Release|Any CPU
{49E17405-466C-44AC-9F85-E2A4DB149170}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -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; }
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0-android</TargetFramework>
<SupportedOSPlatformVersion>24</SupportedOSPlatformVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<!--
Enable trim analyzers for Android class libraries.
To learn more, see: https://learn.microsoft.com/dotnet/core/deploying/trimming/prepare-libraries-for-trimming
-->
<IsTrimmable>true</IsTrimmable>
<!--
NOTE: you can simply add .aar or .jar files in this directory to be included in the project.
To learn more, see: https://learn.microsoft.com/dotnet/maui/migration/android-binding-projects
-->
</PropertyGroup>
<ItemGroup>
<AndroidLibrary Include="libs\DataCollection.aar" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.AndroidX.Annotation" Version="1.9.1.6" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.17.0.1" />
<PackageReference Include="Xamarin.Kotlin.StdLib" Version="2.3.0.1" />
</ItemGroup>
</Project>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>