Skip to Content
Nuova versione 12 disponibile 🎉
LicensingAttivazione della licenza in MAUI

Attivazione della licenza in MAUI

In questa guida vediamo come implementare l’attivazione della licenza in un’applicazione .NET MAUI con Babel Licensing. Questo approccio ti permette di vincolare in modo sicuro le licenze a dispositivi specifici, così il tuo software viene usato solo secondo i termini della tua licenza. Seguendo questo schema di implementazione crei un sistema di licenze solido, che funziona in modo coerente su più piattaforme e sfrutta le informazioni sul dispositivo specifiche di ogni piattaforma.

Prerequisiti

Prima di iniziare, assicurati di avere:

  • Visual Studio 2022 con il carico di lavoro .NET MAUI installato
  • Il pacchetto NuGet Babel.Licensing (versione 11.0.0 o successiva)
  • Un’istanza del Babel Licensing Service in esecuzione (in locale o su un server)
  • Una conoscenza di base dello sviluppo di applicazioni .NET MAUI
  • Una licenza di Babel Licensing in edizione Server o Data Center

Progetto di esempio

Puoi scaricare il progetto di esempio completo da GitHub con il seguente comando:

git clone https://github.com/babelfornet/maui-licensed-app.git

Questo repository contiene un’applicazione MAUI completa, con l’integrazione di Babel Licensing su tutte le piattaforme supportate.

Applicazione MAUI con licenza

Perché l’attivazione della licenza in MAUI?

MAUI (Multi-platform App UI) permette agli sviluppatori di creare applicazioni multipiattaforma da un’unica base di codice. Quando implementi le licenze, però, devi tenere conto delle caratteristiche proprie di ogni piattaforma. L’attivazione della licenza è particolarmente adatta alle applicazioni MAUI perché:

  1. Vincolo al dispositivo: le licenze sono legate al dispositivo specifico su cui è in esecuzione l’applicazione, e questo impedisce l’uso non autorizzato su più dispositivi.
  2. Funzionamento offline: una volta attivate, le applicazioni possono funzionare senza una connessione continua al server, cosa ideale per le applicazioni mobili.
  3. Compatibilità multipiattaforma: il modello di licensing funziona in modo coerente sulle diverse piattaforme (Android, iOS, Windows, MacCatalyst).

Impostare la struttura del progetto

L’esempio MauiLicApp mostra un approccio ben organizzato all’implementazione di Babel Licensing in un’applicazione MAUI:

MauiLicensedApp/ ├── Licensing/ # Core licensing implementation │ ├── BabelLicensingExtensions.cs │ ├── ISystemInformation.cs │ └── LicensingService.cs ├── Platforms/ # Platform-specific implementations │ ├── Android/ │ ├── iOS/ │ ├── MacCatalyst/ │ └── Windows/ ├── Reporting/ # Exception reporting functionality │ └── BabelReportingExtensions.cs └── MauiProgram.cs # Application initialization

Questa struttura separa gli aspetti legati alle licenze dal resto dell’applicazione e mantiene le implementazioni specifiche della piattaforma dove servono.

Implementare la classe base SystemInformation

Il cuore del nostro sistema di licenze multipiattaforma è la classe astratta SystemInformationBase, che definisce un’interfaccia indipendente dalla piattaforma per raccogliere le informazioni di sistema necessarie all’attivazione della licenza:

public abstract class SystemInformationBase : ISystemInformation { public abstract string DeviceId { get; } public abstract string DeviceManufacturer { get; } public abstract string DeviceModel { get; } public abstract string OsVersion { get; } // Additional system properties... }

Questa classe implementa l’interfaccia ISystemInformation di Babel Licensing: garantisce la compatibilità con il sistema di licenze e offre un’astrazione coerente tra le piattaforme.

Informazioni di sistema specifiche della piattaforma

In un’applicazione MAUI, le implementazioni di SystemInformationBase specifiche della piattaforma sono fondamentali per diversi motivi:

  1. Differenze nell’accesso all’hardware: ogni piattaforma ha API e metodi propri per accedere alle informazioni sull’hardware. Per esempio, Android usa Build.SERIAL o Settings.Secure.ANDROID_ID, mentre iOS usa UIDevice.CurrentDevice.IdentifierForVendor.
  2. Restrizioni di sicurezza: le piattaforme mobili hanno modelli di sicurezza diversi, che limitano l’accesso a determinate informazioni di sistema. Le implementazioni specifiche della piattaforma possono gestire queste restrizioni nel modo appropriato.
  3. Identificatori univoci: il modo di generare identificatori del dispositivo affidabili e persistenti varia da piattaforma a piattaforma. Ciò che funziona su Windows non funziona su iOS o Android.
  4. Disponibilità delle funzionalità: alcune informazioni sull’hardware disponibili su una piattaforma possono non essere accessibili su un’altra, e richiedono alternative specifiche della piattaforma.

Ecco come funziona in pratica sulle diverse piattaforme:

Implementazione per Android

L’implementazione per Android usa le API specifiche di Android per raccogliere le informazioni di sistema:

public class SystemInformation : SystemInformationBase { public override string DeviceId { get { try { return Settings.Secure.GetString(_context.ContentResolver, Settings.Secure.AndroidId) ?? string.Empty; } catch (Exception) { return string.Empty; } } } public override string DeviceManufacturer => Build.Manufacturer ?? string.Empty; // Other implementations... }

Implementazione per iOS

L’implementazione per iOS usa le API specifiche di iOS:

public class SystemInformation : SystemInformationBase { public override string DeviceId { get { try { return UIDevice.CurrentDevice?.IdentifierForVendor?.AsString() ?? string.Empty; } catch (Exception) { return string.Empty; } } } public override string DeviceManufacturer => "Apple"; // Other implementations... }

Implementazione per Windows

L’implementazione per Windows usa Windows Management Instrumentation (WMI) per raccogliere le informazioni di sistema:

public class SystemInformation : SystemInformationBase { public override string SystemUuid { get { try { using var searcher = new ManagementObjectSearcher( "SELECT UUID FROM Win32_ComputerSystemProduct"); foreach (var obj in searcher.Get()) { return obj["UUID"]?.ToString() ?? string.Empty; } return string.Empty; } catch (Exception) { return string.Empty; } } } // Other implementations... }

Registrare le implementazioni specifiche della piattaforma

Ogni piattaforma deve registrare la propria implementazione di SystemInformation all’avvio dell’applicazione. Di solito avviene nel punto di ingresso specifico della piattaforma:

Per Android (MainApplication.cs):

[Application] public class MainApplication : MauiApplication { public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership) { // Register the SystemInformation service for licensing LicenseServices.Current.AddService(typeof(ISystemInformation), new SystemInformation()); } protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); }

Per iOS (Program.cs):

public class Program { static void Main(string[] args) { // Register the SystemInformation service for licensing LicenseServices.Current.AddService(typeof(ISystemInformation), new SystemInformation()); UIApplication.Main(args, null, typeof(AppDelegate)); } }

Per Windows (App.xaml.cs):

public partial class App : MauiWinUIApplication { protected override void OnLaunched(LaunchActivatedEventArgs args) { // Register the SystemInformation service for licensing LicenseServices.Current.AddService(typeof(ISystemInformation), new SystemInformation()); base.OnLaunched(args); } }

Configurare Babel Licensing in MAUI

Con le implementazioni specifiche della piattaforma pronte, devi configurare Babel Licensing per l’applicazione MAUI. Lo fai con metodi di estensione che si integrano con il sistema di inserimento delle dipendenze di MAUI:

public static MauiAppBuilder UseBabelLicensing( this MauiAppBuilder builder, Action<BabelLicensingConfiguration>? configureClient = null) { // Register platform-specific system information service builder.Services.AddSingleton<SystemInformationBase>(serviceProvider => { return LicenseServices.Current.GetService(typeof(ISystemInformation)) as SystemInformationBase ?? throw new InvalidOperationException("SystemInformation service not registered."); }); // Create the BabelLicensing configuration var config = new BabelLicensingConfiguration { // Set the default client ID ClientId = AppInfo.Current.Name, // Set the machine ID using system UUID and name MachineId = new HardwareId( HardwareComponents.SystemUuid | HardwareComponents.SystemName).ToMachineKey(), // Set the signature provider with public key for license verification SignatureProvider = RSASignature.FromKeys("PUBLIC_KEY_HERE") }; // Apply custom configuration configureClient?.Invoke(config); // Register services builder.Services.AddSingleton<BabelLicensing>(/* ... */); builder.Services.AddSingleton<BabelServiceLicenseProvider>(/* ... */); return builder; }

Questo metodo di estensione viene poi usato in MauiProgram.cs per applicare la configurazione delle licenze:

public static MauiApp CreateMauiApp() { // Configure BabelLicensing service URL string babelHttpServiceUrl = "https://your-license-server:5455"; var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseBabelLicensing(config => { config.ServiceUrl = babelHttpServiceUrl; }) .UseBabelReporting(config => { config.ServiceUrl = babelHttpServiceUrl; }) .ConfigureFonts(fonts => { /* ... */ }); // Register the LicensingService for dependency injection builder.Services.AddSingleton<LicensingService>(); return builder.Build(); }

Creare il LicensingService

La classe LicensingService offre un’interfaccia semplificata per le operazioni sulle licenze in tutta l’applicazione:

public class LicensingService { private readonly BabelLicensing _client; private readonly BabelServiceLicenseProvider _licenseProvider; public LicensingService(BabelLicensing client, BabelServiceLicenseProvider licenseProvider) { _client = client; _licenseProvider = licenseProvider; } public BabelLicensing Client => _client; public bool IsLicensed => BabelLicenseManager.IsLicensed(typeof(BabelLicensingExtensions)); public string? UserKey => _licenseProvider.UserKey; public async Task ActivateLicenseAsync(string userKey) { await _client.ActivateLicenseAsync(userKey, typeof(BabelLicensingExtensions)); } public async Task DeactivateLicenseAsync() { if (!string.IsNullOrEmpty(UserKey)) { await _client.DeactivateLicenseAsync(UserKey); } } public async Task<ILicense> ValidateLicenseAsync() { return await BabelLicenseManager.ValidateAsync(typeof(BabelLicensingExtensions)); } }

Questo servizio incapsula l’API di Babel Licensing dietro un’interfaccia semplice e specifica dell’applicazione. Può essere inserito in qualsiasi pagina o viewmodel che abbia bisogno delle funzionalità di licenza.

Implementare l’attivazione della licenza nell’interfaccia utente

Con l’infrastruttura delle licenze pronta, puoi implementare l’attivazione della licenza nella tua interfaccia utente. Ecco un esempio tratto da MainPage.xaml.cs:

private async void OnActivateClicked(object sender, EventArgs e) { try { if (_licensingService.IsLicensed) { // If licensed, validate the license var license = await _licensingService.ValidateLicenseAsync(); ActivateBtn.Text = $"License valid: {license.Id}"; // Show system information await DisplayAlert("System Info", $"Device: {_systemInfo.DeviceManufacturer} {_systemInfo.DeviceModel}\n" + $"OS: {_systemInfo.OperatingSystem} {_systemInfo.OsVersion}\n" + $"System: {_systemInfo.SystemName}\n" + $"UUID: {_systemInfo.SystemUuid}", "OK"); } else { // If not licensed, prompt for activation string userKey = await DisplayPromptAsync("License Activation", "Enter your license key:", accept: "Activate", cancel: "Cancel"); if (!string.IsNullOrEmpty(userKey)) { try { await _licensingService.ActivateLicenseAsync(userKey); await DisplayAlert("Success", "License activated successfully!", "OK"); UpdateLicenseStatus(); } catch (Exception ex) { await DisplayAlert("Activation Failed", $"Could not activate license: {ex.Message}", "OK"); } } } } catch (Exception ex) { await DisplayAlert("Error", $"License operation failed: {ex.Message}", "OK"); } }

Questa implementazione permette agli utenti di inserire una chiave di licenza e attivare l’applicazione. Una volta attivata, la licenza è vincolata al dispositivo e può essere convalidata agli avvii successivi dell’applicazione.

Aggiungere i report di eccezione

Babel Licensing supporta anche i report di eccezione, che puoi integrare nella tua applicazione MAUI con la classe BabelReportingExtensions:

public static void ReportUnhandledException(this Exception ex) { try { var task = Task.Run(async () => { try { await ex.SendReportAsync(); } catch (Exception innerEx) { Debug.WriteLine($"Failed to report exception: {innerEx.Message}"); } }); task.Wait(TimeSpan.FromSeconds(5)); } catch (Exception reportEx) { Debug.WriteLine($"Failed to report exception: {reportEx.Message}"); } }

Questa funzionalità può essere registrata nei gestori delle eccezioni non gestite dell’applicazione:

// In App.xaml.cs private void SetupExceptionHandling() { AppDomain.CurrentDomain.UnhandledException += (sender, args) => { var ex = args.ExceptionObject as Exception; ex?.ReportUnhandledException(); }; }

Report di eccezione

Procedure consigliate per l’attivazione della licenza in MAUI

Per offrire un’esperienza di licenza senza intoppi nella tua applicazione MAUI:

  1. Gestione degli errori: implementa una gestione completa degli errori per le operazioni di rete e di licenza, soprattutto per le applicazioni mobili, che possono avere una connettività intermittente.
  2. Degradazione controllata: quando la convalida della licenza non riesce per problemi di connettività, prevedi un periodo di tolleranza o funzionalità limitate invece di bloccare del tutto l’applicazione.
  3. Riscontro nell’interfaccia utente: mostra con chiarezza lo stato della licenza nell’interfaccia utente, in modo che sia evidente quando una licenza è attiva, scaduta o non valida.
  4. Test: prova la tua implementazione delle licenze su tutte le piattaforme di destinazione, per garantire un comportamento coerente su tutti i dispositivi.

Conclusione

Implementare l’attivazione della licenza in un’applicazione .NET MAUI con Babel Licensing richiede un approccio ragionato, che gestisca le differenze tra le piattaforme e mantenga un’esperienza di licenza coerente. Creando un’astrazione indipendente dalla piattaforma con implementazioni specifiche per ognuna, puoi raccogliere in modo affidabile le informazioni di sistema necessarie a un’attivazione sicura della licenza.

L’esempio MauiLicApp mostra un’implementazione completa che funziona sulle piattaforme Android, iOS, Windows e MacCatalyst. Seguendo questo schema e le procedure consigliate descritte in questa guida, puoi proteggere in modo efficace le tue applicazioni MAUI con un sistema di licenze solido.

Con questo approccio le tue applicazioni vengono usate solo secondo i termini della tua licenza, e gli utenti legittimi hanno un’esperienza fluida su tutte le piattaforme supportate.

Last updated on