Skip to Content
Nueva versión 12 disponible 🎉
LicensingActivación de licencia en MAUI

Activación de licencia en MAUI

Esta guía explica cómo implementar la activación de licencia en una aplicación .NET MAUI con Babel Licensing. Este enfoque permite vincular de forma segura las licencias a dispositivos concretos, de modo que el software solo se use conforme a los términos de su licencia. Con este patrón de implementación creará un sistema de licencias sólido que funciona de manera coherente en varias plataformas y aprovecha la información del dispositivo específica de cada una.

Requisitos previos

Antes de empezar, compruebe que dispone de lo siguiente:

  • Visual Studio 2022 con la carga de trabajo de .NET MAUI instalada
  • El paquete NuGet Babel.Licensing (versión 11.0.0 o posterior)
  • Una instancia del Babel Licensing Service en ejecución (en local o en un servidor)
  • Conocimientos básicos del desarrollo de aplicaciones .NET MAUI
  • Una licencia de Babel Licensing de la edición Server o Data Center

Proyecto de ejemplo

Puede descargar el proyecto de ejemplo completo de GitHub con el comando siguiente:

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

Este repositorio contiene una aplicación MAUI totalmente implementada, con Babel Licensing integrado en todas las plataformas admitidas.

Aplicación MAUI con licencia

¿Por qué la activación de licencia en MAUI?

MAUI (Multi-platform App UI) permite a los desarrolladores crear aplicaciones multiplataforma a partir de una única base de código. Sin embargo, al implementar las licencias hay que tener en cuenta las características propias de cada plataforma. La activación de licencia resulta especialmente adecuada para las aplicaciones MAUI porque:

  1. Vinculación al dispositivo: las licencias se vinculan al dispositivo concreto en el que se ejecuta la aplicación, lo que impide el uso no autorizado en varios dispositivos.
  2. Funcionamiento sin conexión: una vez activadas, las aplicaciones pueden funcionar sin una conexión continua con el servidor, lo que resulta ideal para las aplicaciones móviles.
  3. Compatibilidad multiplataforma: el modelo de licencia funciona de manera coherente en las distintas plataformas (Android, iOS, Windows, MacCatalyst).

Preparar la estructura del proyecto

El ejemplo MauiLicApp muestra una manera bien organizada de implementar Babel Licensing en una aplicación 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

Esta estructura separa la gestión de licencias del resto de la aplicación y mantiene las implementaciones específicas de cada plataforma donde hacen falta.

Implementar la clase base SystemInformation

El núcleo del sistema de licencias multiplataforma es la clase abstracta SystemInformationBase, que define una interfaz independiente de la plataforma para reunir la información del sistema necesaria para la activación de licencia:

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... }

Esta clase implementa la interfaz ISystemInformation de Babel Licensing, lo que garantiza la compatibilidad con el sistema de licencias y proporciona una abstracción coherente entre plataformas.

Información del sistema específica de la plataforma

En una aplicación MAUI, las implementaciones de SystemInformationBase específicas de cada plataforma son fundamentales por varias razones:

  1. Diferencias en el acceso al hardware: cada plataforma tiene sus propias API y sus propios métodos para acceder a la información del hardware. Por ejemplo, Android usa Build.SERIAL o Settings.Secure.ANDROID_ID, mientras que iOS usa UIDevice.CurrentDevice.IdentifierForVendor.
  2. Restricciones de seguridad: las plataformas móviles tienen modelos de seguridad distintos que restringen el acceso a determinada información del sistema. Las implementaciones específicas de cada plataforma pueden tratar esas restricciones de la manera adecuada.
  3. Identificadores únicos: la manera de generar identificadores de dispositivo fiables y persistentes varía según la plataforma. Lo que funciona en Windows no funciona en iOS ni en Android.
  4. Disponibilidad de funciones: parte de la información de hardware disponible en una plataforma puede no estar accesible en otra, lo que exige alternativas específicas de la plataforma.

Así funciona en la práctica en las distintas plataformas:

Implementación para Android

La implementación para Android usa las API propias de Android para reunir la información del 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... }

Implementación para iOS

La implementación para iOS usa las API propias de 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... }

Implementación para Windows

La implementación para Windows usa Instrumental de administración de Windows (WMI) para recopilar la información del 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... }

Registrar las implementaciones específicas de la plataforma

Cada plataforma debe registrar su implementación específica de SystemInformation durante el inicio de la aplicación. Normalmente se hace en el punto de entrada específico de la plataforma:

Para 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(); }

Para 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)); } }

Para 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); } }

Configurar Babel Licensing en MAUI

Una vez preparadas las implementaciones específicas de cada plataforma, hay que configurar Babel Licensing para la aplicación MAUI. Esto se hace con métodos de extensión que se integran en el sistema de inserción de dependencias de 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; }

Este método de extensión se usa después en MauiProgram.cs para aplicar la configuración de licencias:

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(); }

Crear el LicensingService

La clase LicensingService proporciona una interfaz simplificada para las operaciones de licencias en toda la aplicación:

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

Este servicio encapsula la API de Babel Licensing tras una interfaz sencilla y específica de la aplicación. Se puede insertar en cualquier página o modelo de vista que necesite la funcionalidad de licencias.

Implementar la activación de licencia en la interfaz de usuario

Con la infraestructura de licencias preparada, ya puede implementar la activación de licencia en la interfaz de usuario. Este es un ejemplo de 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"); } }

Esta implementación permite a los usuarios introducir una clave de licencia y activar la aplicación. Una vez activada, la licencia queda vinculada al dispositivo y se puede validar en los inicios posteriores de la aplicación.

Añadir informes de excepción

Babel Licensing admite también los informes de excepción, que se pueden integrar en la aplicación MAUI con la clase 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}"); } }

Esta funcionalidad se puede registrar en los controladores de excepciones no controladas de la aplicación:

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

Informe de excepción

Prácticas recomendadas para la activación de licencia en MAUI

Para que la experiencia de licencias en su aplicación MAUI sea fluida:

  1. Control de errores: implemente un control de errores completo para las operaciones de red y de licencias, sobre todo en las aplicaciones móviles, cuya conectividad puede ser intermitente.
  2. Degradación controlada: cuando la validación de la licencia falle por problemas de conectividad, ofrezca un período de gracia o una funcionalidad limitada en lugar de bloquear por completo la aplicación.
  3. Información en la interfaz: muestre con claridad en la interfaz de usuario el estado de la licencia, de modo que sea evidente cuándo una licencia está activa, caducada o no es válida.
  4. Pruebas: pruebe su implementación de licencias en todas las plataformas de destino para garantizar un comportamiento coherente en todos los dispositivos.

Conclusión

Implementar la activación de licencia en una aplicación .NET MAUI con Babel Licensing exige un planteamiento que resuelva las diferencias entre plataformas y mantenga a la vez una experiencia de licencias coherente. Al crear una abstracción independiente de la plataforma con implementaciones específicas de cada una, puede reunir de forma fiable la información del sistema necesaria para una activación de licencia segura.

El ejemplo MauiLicApp muestra una implementación completa que funciona en las plataformas Android, iOS, Windows y MacCatalyst. Si sigue este patrón y las prácticas recomendadas descritas en esta guía, podrá proteger eficazmente sus aplicaciones MAUI con un sistema de licencias sólido.

Este enfoque garantiza que sus aplicaciones solo se usen conforme a los términos de su licencia y ofrece a la vez una experiencia sin fricciones a los usuarios legítimos en todas las plataformas admitidas.

Last updated on