[Xamarin.Forms] Utilizando LiteDB

Database-WFIntroducción

El trabajo con datos en dispositivos móviles se ha convertido ya en algo común y habitual en el desarrollo de aplicaciones. Existe una gran variedad de tipos de datos y formas de almacenamiento:

  • Archivos de texto. Texto plano o html cacheado en el espacio de almacenamiento aislado de la aplicación.
  • Imágenes. En el espacio de almacenamiento aislado de la aplicación o almacenadas en directorios conocidos del sistema.
  • Archivos serializados. Archivos XML o Json con objetos serializados.
  • Bases de datos. Cuando se requieren datos estructurados, obtener información más compleja con consultas avanzadas entre otro tipo de necesidades, la posibilidad de las bases de datos es la elección idónea.

En este artículo, vamos a conocer LiteDB y como utilizarlo con una aplicación Xamarin.Forms.

Recuerda

El mismo ejemplo que vemos en este artículo lo hemos visto previamente con:

Introducción a LiteDB

LiteDB es una base de da motor de base de datos Open Source  distribuido en una pequeña librería escrita en C# y compatible con .NET y .NET Standard. Inspirada en MongoDB almacena documentos BSON (Binary JSON).

Al ser compatible con .NET Standard 2.0, podemos utilizarla con Xamarin.iOS, Xamarin.Android y UWP con aplicaciones Xamarin.Forms.

Preparando el entorno

Comenzamos creando una aplicación Xamarin.Forms utilizando una librería .NET Standard:

Xamarin.Forms con librería .NET Standard

Tras crear la aplicación, añadimos las carpetas básicas para aplicar el patrón MVVM además del paquete NuGet de Autofac para la gestión del contenedor de dependencias.

Estructura del proyecto

Con el proyecto y estructura base creada, vamos a añadir LitrDB al proyecto. LiteDB esta disponible en NuGet. Vamos a añadir en cada proyecto de la solución la última versión disponible del paquete utilizando NuGet. El paquete a utilizar es LiteDB, implementación Open Source compatible con librerías .NET Standard.

LiteDB

Tras añadir la referencia vamos a crear una interfaz que defina como obtener la conexión con la base de datos y abstraer la funcionalidad específica de cada plataforma. Trabajando con LiteDB, el único trabajo específico a implementar en cada plataforma es determinar la ruta a la base de datos y establecer la conexión.

public interface IPathService
{
     string GetDatabasePath();
}

En Android, la implementación de IPathService nos permite establecer la conexión con la base de datos.

public class PathService : IPathService
{
     public string GetDatabasePath()
     {
          var path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), AppSettings.DatabaseName);
          if (!File.Exists(path))
          {
               File.Create(path).Dispose();
          }
          return path;
     }
}

NOTA: Utilizamos el atributo assembly:Dependency para poder realizar la resolución de la implementación con DependencyService.

En iOS, la implementación de IPathService nos permite establecer la conexión con la base de datos. El archivo de la base de datos lo situamos dentro de la carpeta Library dentro del espacio de almacenamiento de la aplicación.

public class PathService : IPathService
{
     public string GetDatabasePath()
     {
          string docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
          string libFolder = Path.Combine(docFolder, "..", "Library", "Databases");
          if (!Directory.Exists(libFolder))
          {
               Directory.CreateDirectory(libFolder);
          }
          return Path.Combine(libFolder, AppSettings.DatabaseName);
     }
}

Y por último en UWP:

public class PathService : IPathService
{
     public string GetDatabasePath()
     {
          return Path.Combine(ApplicationData.Current.LocalFolder.Path, AppSettings.DatabaseName);
     }
}

Todo listo para comenzar!

La definición de modelos

En nuestra aplicación, trabajaremos con elementos del listado ToDo, una única entidad sencilla.

public class TodoItem
{
     public int Id { get; set; }
     public string Name { get; set; }
     public string Notes { get; set; }
     public bool Done { get; set; }
}

La interfaz de usuario

En nuestra aplicación contaremos con dos vistas, un listado de tareas y una vista de detalles para crear, editar o eliminar una tarea específica.

Comenzamos definiendo la vista principal. Tendremos un listado de tareas:

<ListView ItemsSource="{Binding Items}"
     SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
     <ListView.ItemTemplate>
          <DataTemplate>
               <ViewCell>
                    <ViewCell.View>
                         <StackLayout Padding="20,0,20,0"
                              Orientation="Horizontal"
                              HorizontalOptions="FillAndExpand">
                              <Label Text="{Binding Name}"
                                   VerticalTextAlignment="Center"
                                   HorizontalOptions="StartAndExpand" />
                              <Image HorizontalOptions="End"
                                   IsVisible="{Binding Done}">
                                   <Image.Source>
                                        <OnPlatform x:TypeArguments="ImageSource">
                                             <On Platform="Android, iOS"
                                                  Value="check" />
                                             <On Platform="UWP"
                                                  Value="Assets/check.png" />
                                        </OnPlatform>
                                   </Image.Source>
                              </Image>
                         </StackLayout>
                    </ViewCell.View>
               </ViewCell>
          </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

A parte de definir como se visualizará cada elemento de la lista definiendo el DataTemplate establecemos la fuente de información, propiedad ItemsSource enlazada a propiedad de la ViewModel que obtendrá los datos de la base de datos.

Además del listado, debemos añadir en nuestra interfaz una forma de poder insertar nuevas tareas. Para ello, una de las opciones más habituales e idóneas es utilizar una Toolbar.

<ContentPage.ToolbarItems>
     <ToolbarItem Name="Add"
          Command="{Binding AddCommand}">
          <ToolbarItem.Icon>
                <OnPlatform x:TypeArguments="FileImageSource">
                     <On Platform="Android, iOS"
                         Value="plus" />
                     <On Platform="UWP"
                         Value="Assets/plus.png" />
                </OnPlatform>
          </ToolbarItem.Icon>
     </ToolbarItem>
</ContentPage.ToolbarItems>

Añadimos un ToolbarItem que permitirá añadir elementos.

La clase Device es muy importante en Xamarin.Forms ya que nos permite acceder a una serie de propiedades y métodos con el objetivo de personalizar la aplicación según dispositivo y plataforma. Además de permitirnos detectar el tipo de dispositivo, podemos detectar la plataforma gracias a la enumeración Device.OS o personalizar elementos de la interfaz gracias al método Device.OnPlatform entre otras opciones. En nuestro ejemplo, personalizamos el icono de añadir en base a la plataforma.

Nuestra interfaz:

Vista principal

Vista principal

Enlazamos la View con la ViewModel estableciendo una instancia de la ViewModel a la propiedad BindingContext de la página.

BindingContext = App.Locator.TodoListViewModel;

En la ViewModel contaremos con una propiedad pública para definir el listado de tareas, además de la tarea seleccionada (utilizada para la navegación):

private ObservableCollection<TodoItem> _items;
private TodoItem _selectedItem;

public ObservableCollection<TodoItem> Items
{
     get { return _items; }
     set
     {
          _items = value;
          OnPropertyChanged();
     }
}
public TodoItem SelectedItem
{
     get { return _selectedItem; }
     set
     {
          _selectedItem = value;
          OnPropertyChanged();
     }
}

Añadimos elementos con un comando disponible en la ViewModel.

private ICommand _addCommand;

public ICommand AddCommand
{
     get { return _addCommand = _addCommand ?? new Command(AddCommandExecute); }
}

private void AddCommandExecute()
{
}

Al pulsar y lanzar el comando, navegaremos a la vista de detalles.

var todoItem = new TodoItem();
_navigationService.NavigateTo<TodoItemViewModel>(todoItem);

Si creamos un nuevo elemento pasaremos como parámetro una nueva entidad de TodoItem, en caso de seleccionar una existente, pasaremos el seleccionado disponible en la propiedad SelectedItem.

Definimos la interfaz de la vista de detalles:

<StackLayout VerticalOptions="StartAndExpand"
     Padding="20">
     <Label Text="Name" />
     <Entry Text="{Binding Item.Name}" />
     <Label Text="Notes" />
     <Entry Text="{Binding Item.Notes}" />
     <Label Text="Done" />
     <Switch x:Name="DoneEntry"
          IsToggled="{Binding Item.Done}" />
     <Button Text="Save"
          Command="{Binding SaveCommand}" />
     <Button Text="Delete"
          Command="{Binding DeleteCommand}" />
     <Button Text="Cancel"
          Command="{Binding CancelCommand}" />
</StackLayout>

Añadimos cajas de texto para poder editar toda la información de una tarea además de botones para poder guardar, borrar o cancelar y navegar atrás.

El resultado:

Detalle

Detalle

Para enlazar la información de un elemento seleccionado, debemos capturar la información enviada en la navegación. Creamos una propiedad pública para enlazar con la UI de la tarea:

private TodoItem _item;

public TodoItem Item
{
     get { return _item; }
     set
     {
          _item = value;
          OnPropertyChanged();
     }
}

¿Cómo capturamos el elemento seleccionado en la navegación?. Utilizamos el método OnAppearing para capturar el parámetro NavigationContext.

public override void OnAppearing(object navigationContext)
{
     if (navigationContext is TodoItem todoItem)
     {
          Item = todoItem;
     }

     base.OnAppearing(navigationContext);
}

En cuanto a cada botón, cada uno de ellos estará enlazado a un comando:

Trabajando con LiteDB

Para trabajar con la base de datos utilizaremos DependencyService para obtener la implementación de IPathService y obtener una conexión.

var db = new LiteDatabase(DependencyService.Get<IPathService>().GetDatabasePath());

Para almacenar nuestras tareas, comenzamos creando la colección necesaria en la base de datos.

_collection = db.GetCollection<TodoItem>();

Si la colección no existe en la base de datos, es creada.

Cada elemento guardado en LiteDB cuenta con una propiedad Id utilizado para identificarlo de manera única. Debeemos indicarle a LiteDB qué propiedad de nuestro objeto actuará como identificador. Podemos hacerlo usando atributos o un mapeador. Aquí utilizaremos Mappers.

var mapper = BsonMapper.Global;

mapper.Entity<TodoItem>()
.Id(x => x.Id);

Para obtener el listado de elementos de una colección utilizaremos el método FindAll:

var all = _collection.FindAll();

A la hora de insertar, verificamos si estamos ante un registro existente o no, para realizar el registro de un nuevo elemento o actualizar uno existente con los métodos Insert o Update respectivamente.

var existingTodoItem = _collection.FindById(item.Id);

if (existingTodoItem == null)
_collection.Insert(item);
else
_collection.Update(item);

Eliminar es una acción sencilla realizada con el método Delete.

_collection.Delete(i => i.Id.Equals(item.Id));

Tenéis el código fuente disponible e GitHub:

Ver GitHub

Recordad que podéis dejar cualquier comentario, sugerencia o duda en los comentarios.

Más información

Anuncios

[Material] Taller Xamarin en OpenSouthCode 2018

El evento

El pasado 01 y 02 de Junio se celebró en Málaga OpenSouthCode 2018, un evento gratuito para promocionar y dar a conocer las tecnologías abiertas: software/hardware libre y opensource.

El Material

He tenido la oportunidad de participar este año con un divertido taller de desarrollo con Xamarin.

El objetivo fue realizar una aplicación multiplataforma con Xamarin.Forms para Android, iOS, UWP, macOS y Linux utilizando una Custom Vision. Tras una breve introducción donde repasamos conceptos básicos, comenzamos a crear la aplicación. Vimos una introducción al concepto de enlace a datos, MVVM y su aplicación, acceso a APIs nativas de cada plataforma y acabamos realizando peticiones HTTP para obtener información.

La aplicación realizada fue HotDotOrNot en inspiración de la serie “Silicon Valley”.

HotDotOrNot

Para acabar el taller nos relajamos con un divertido concurso de preguntas, algunos pequeños regalos, preguntas y networking.

Puedes encontrar la App realizada paso a paso en GitHub:

Ver GitHub

Más información

[Material DotNet2018] Xamarin.Forms Everywhere

El evento

El pasado 29 de Mayo tenía lugar la DotNet2018. Un gran día repleto de sesiones técnicas cubriendo todo el espectro de tecnologías .NET, desde Xamarin, Azure, IoT, VR, etc.

Fue un día genial de grandes sesiones pero también de encontrarte con grandes amigos, desvirtualizar a nuevos amigos, networking, etc. Quisiera agradecer a todos los ponentes y asistentes por hacer posible el evento. Y por supuesto, mi enhorabuena a toda la organización por hacer que algo tan grande y complejo fluyese de forma tan natural y sencilla.

El material

He tenido en placer de poder participar en el evento con una sesión acerca de Xamarin.Forms y nuevas plataformas o posibilidades.

Comenzamos el evento revisando Xamarin.Forms en Linux:

Xamarin.Forms en Linux

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Continuamos viendo estado y opciones de Xamarin.Forms en WPF:

Xamarin.Forms WPF

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Y continuamos con nuevos backends de Xamarin.Forms, y en esta ocasión hablamos de Ooui de Frank Krueger.

Desde el navegador!

Repasamos estado, un poco de WebAssembly y continuamos. Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHubContinuamos viendo los primeros pasos del backend de Windows Forms y dimos paso a nuevas posibilidades.

Hablamos de wearables y Tizen.CircularUI, donde repasamos opciones principales, etc.

Posteriormente llegço el turno de IoT. Tras una breve introducción a Xamarin.IoT vimos como ya contamos con plantillas de proyectos e integración entre Xamarin.Forms (backend GTK#) con Xamarin.IoT.

Monitor de temperatura realizado con Xamarin.IoT y Xamarin.Forms

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Tras ver nuevas plataformas o dispositivos con IoT o Wearables, nos centramos en nuevas posibilidades en UI. Hicimos un repaso de:

  • VisualStateManager
  • FexLayout
  • SkiaSharp
  • Etc

En este punto, vimos como crear interfaces combinadas con elementos 3D con Wave Engine o como combinar ARCore con Xamarin.Forms creando Custom Renderers.

ARCore

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Completamos el evento utilizando Xamarin.Forms para crear la UI de addins para Visual Studio en Windows y macOS.

El ejemplo:

Ver GitHub

Hasta el año próximo!

Y ya tenemos evento confirmado para el próximo año!. Apunta la fecha, 23 de Mayo.

DotNet 2019!

Allí nos vemos!

Más información

[Xamarin.Forms] Aplicaciones con contenido 3D utilizando Wave Engine

Introducción

A la hora de desarrollar aplicaciones móviles, nos encontramos con una enorme variedad de requisitos a nivel visual y de contenido. En Xamarin.Forms gracias al avance en novedades (pestañas en la parte inferior, bordes redondeados, etc.) junto a SkiaSharp, estilos, efectos y Custom Renderers otorgan grandes opciones para desarrollar aplicaciones visualmente atractivas.

En determinadas ocasiones, la visualización e interacción con elementos 3D o cámaras en 360 grados por ejemplo, otorga una mejor experiencia en nuestras aplicaciones. Por ejemplo, la visualización de edificios y diferentes plantas o la previsulización de un coche que deseamos comprar. Para conseguir la visualización e integración con elementos 3D tenemos diferentes opciones como Urho o Wave Engine.

En este artículo, vamos a ver como integrar elementos 3D en una aplicación Xamarin.Forms utilizando Wave Engine.

Wave Engine

Wave Engine es un motor de videojuegos 2D y 3D multiplataforma, basado en componentes y totalmente gratuito (no hay licencias ni tampoco ningún tipo de royalty). Nos ofrece una API para trabajar con físicas, animaciones, sonido, etc. utilizando C# sin tener que profundizar a más bajo nivel y tener que trabajar con DirectX directamente.

Podemos desarrollar para Android, iOS, Linux, macOS, Windows, etc..

Creando la escena 3D

Vamos a realizar un ejemplo sencillo pero suficientemente interesante para conocer:

  • La creación de una escena 3D.
  • Integrar una escena 3D en Xamarin.Forms.
  • Interactuar desde una vista XAML de Xamarin.Forms con la escena 3D.

Crearemos una escena con un coche y podremos modificar el color del mismo desde un ListView de Xamarin.Forms.

¿Y de dónde obtenemos el modelo 3D?

Para este ejemplo, vamos a utilizar un modelo 3D totalmente gratuito de Sketchfab gracias a Karol Miklas.

Sketchfab

Tras descargar el modelo 3D, arrancamos el editor de Wave Engine.

Editor Wave Engine

NOTA: Puedes descargar Wave Engine desde este enlace.

Creamos nuevo proyecto, y arrastramos el modelo descargado a la carpeta Assets en el apartado Assets Details. Podemos hacer doble clic en el archivo fbx para asegurar que todo es correcto.

Cargar el modelo

Comenzamos a montar nuestra escena arrastrando el modelo que acabamos de previsualizar desde Assets Details a la Scene:

Creando la escena

Llegados a este punto, tenemos suficiente. Podemos mejorar la escena con pequeños cambios como:

  • Añadir entidad plano 3D para ele suelo.
  • Añadir una esfera en forma de cúpula, para añadir “límites” al escenario.
  • Añadir más luces a la añadida por defecto.
  • Etc.

Integrando la escena con proyecto Xamarin.Forms

De momento, tenemos un proyecto Windows (proyecto creado por defecto) con nuestra escena. Podemos lanzar y probar nuestro proyecto.

Ejemplo en Windows

Pero…¿y cómo llegamos a integrarlo todo en Xamarin.Forms?. Wave Engine es un motor multiplataforma. Se pueden crear proyectos para plataformas como Android, iOS, UWP, Linux o macOS. Entre las diferentes opciones, para Android, iOS y UWP hay proyectos con integración con Xamarin.Forms.

Desde el editor de Wave Engine, Edit > Project Properties…

Nuevo perfil

Podemos elegir entre diferentes plataformas, y en cada plataforma diferentes Launchers. En Android, iOS y UWP contamos con Launcher Xamarin.Forms.

Xamarin.Forms

Esto nos crea automáticamente un nuevo proyecto utilizando Xamarin.Forms.

Estructura del proyecto

Tenemos una proyecto Shared con toda la lógica compartida de Wave Engine (escenas, behaviors, componentes, etc.) y otro proyecto de igual tipo donde tenemos la aplicación Xamarin.Forms con las vistas, etc.

Al final, trabajamos con una aplicación Xamarin.Forms habitual donde la carga de la escena 3D se realiza vía Custom Renderer. Contamos con el siguiente control:

public class WaveEngineSurface : View, IViewController
{
     public static readonly BindableProperty GameProperty = BindableProperty.Create(
     propertyName: "Game",
     returnType: typeof(IGame),
     declaringType: typeof(WaveEngineSurface),
     defaultValue: null);

     public IGame Game
     {
          get { return (IGame)GetValue(GameProperty); }
          set { SetValue(GameProperty, value); }
     }
}

Desde una vista XAML:

<AbsoluteLayout>
     <controls:WaveEngineSurface x:Name="WaveEngineSurface"
          AbsoluteLayout.LayoutFlags="All"
          AbsoluteLayout.LayoutBounds="0, 0, 1, 1" />
</AbsoluteLayout>

Interacción con la escena 3D

En este ejemplo, vamos a utilizar SlideOverKit para añadir un menu lateral deslizante, donde mostrar un listado de colores. La idea es permitir cambiar el color de coche en 3D. Pero para conseguirlo, necesitaremos interaccionar con la escena 3D desde nuestra aplicación Xamarin.Forms, ¿cómo lo hacemos?.

Al seleccionar cualquir color, lanzamos un comando en la ViewModel:

public ICommand ColorTappedCommand => new Command<CustomColor>(ChooseColor);

private void ChooseColor(CustomColor color)
{
     // TODO:
}

Al crear el proyecto Xamarin.Forms desde el editor visual tenemos una clase llamada WaveEngineFacade. Desde esta clase tenemos la opción de acceder a la escena. Creamos un método llamado UpdateColor. En el método debemos acceder a la entidad del coche, en concreto a su material, y modificar el color.

¿Cómo sabemos cual es esa entidad?.

Desde el editor, vemos el desglose de entidades (piezas) que componen al coche. Seleccionamos la carrocería y elegimos la opción Copy EntityPath:

Copy EntityPath

public static void UpdateColor(CustomColor color)
{
     var entity = _scene.EntityManager.Find("car.Plane_036.Plane_041");
     var materialComponent = entity.FindComponent<MaterialComponent>();
     var hex = color.Hex;
     ((StandardMaterial)materialComponent.Material).DiffuseColor = FromHex(hex);
}

NOTA: En la variable _scene tenemos acceso a cualquier elemento de la escena (cámara, luces, entidades, etc.). Utilizamos un método Initialize lanzado en el arranque de la aplicación para establecer el valor de la variable.

Desde el comando sencillamente lanzamos nuestro método:

WaveEngineFacade.UpdateColor(color);

El resultado final:

El resultado

Puedes encontrar el ejemplo realizado en GitHub:

Ver GitHub

Más información

Xamarin Essentials

Introducción

Xamarin permite compartir código de lógica de negocio entre aplicaciones Android y iOS, incluso código relacionado con la interfaz de usuario utilizando Xamarin.Forms. Sin embargo, es habitual requerir acceder a APIs nativas de cada plataforma. En este caso es necesario crear código específico por plataforma. Gracias a la gran comunidad Xamarin existe una enorme variedad de Plugins.

Los Plugins nos facilitan el acceso a funcionalidad específica de cada plataforma sin necesidad de escribir grandes cantidades de código. Instalar un paquete NuGet, seguir documentación para inicialización y con pocas líneas se usa API multiplataforma para por ejemplo, verificar el estado de la red. Sin embargo, para poder hacer uso del Plugin tenemos que conocer el nombre del paquete, en ocasiones hay diferentes paquetes destinados al mismo objetivo, etc.

Xamarin.Essentials

Para hacerlo todo más sencillo, llega Xamarin.Essentials. Estamos ante un paquete oficial que podemos usar en nuestras aplicaciones Xamarin añadiendo acceso a APIs multiplataforma como uso de acelerómeto, red, batería o poder hacer llamadas.

Con soporte tanto a Xamarin tradicional como a Xamarin.Forms, actualmente cuenta con:

  • Accelerometer – Obtiene datos del acelerómetro.
  • App Information – Información de la App.
  • Battery – Detectar estado y nivel de la batería.
  • Clipboard – Copiar y pegar desde el Clipboard.
  • Compass – Monitorear cambios en la brújuja.
  • ConnectivityVerificar el estado de conectividad y detectar cambios.
  • Data Transfer – Enviar información a otras Apps.
  • Device Display InformationObtener las métricas y la orientación de la pantalla del dispositivo.
  • Device Information – Información del dispositivo.
  • Email – Enviar email.
  • File System Helpers – Forma sencilla de almacenar ficheros.
  • Flashlight – Forma sencilla de encender y apagar la linterna.
  • GeocodingGeocodificar direcciones y coordenadas.
  • Geolocation – Obtiene la localización del GPS..
  • GyroscopeRotación alrededor de los tres ejes principales del dispositivo.
  • MagnetometerDetecta la orientación del dispositivo en relación con el campo magnético de la Tierra.
  • Open Browser – Forma sencilla de abrir una web en el navegador.
  • Phone Dialer – Abre la App de teléfono.
  • Preferences – Sistema de preferencias rápido y sencillo.
  • Screen Lock – Mantiene la pantalla del dispositivo activa.
  • Secure Storage – Almacenamiento seguro.
  • SMS – Crea un SMS para enviarlo.
  • Text-to-Speech – Sintetizar texto en voz.
  • Version TrackingSeguimiento de la versión de la aplicación.
  • Vibrate – Hace que el dispositivo vibre.

NOTA: Los Plugins seguirán existiendo y aparecerán nuevos que cubran escenarios no cubiertos por Xamarin.Essentials. Contar con una vía oficial con soporte a las plataformas básicas de APIs fundamentales, es genial, pero no suprime los Plugins.

Las plataformas soportadas (en estos momentos) son:

  • Android 4.4 o superior
  • iOS 10.0 o superior
  • UWP 10.0.6299.0 o superior

Empezar a utilizar Xamarin.Essentials

Pasamos a ver como utilizarlo. Partimos de una aplicación nueva Xamarin.Forms. Vamos a añadir nuevo paquete NuGet:

Xamarin.Essentials NuGet

Buscamos por Xamarin.Essentials e instalamos el paquete en todos los proyectos, tanto librería .NET Standard como en Android, iOS y UWP.

Xamarin.Essentials requiere algo de código de inicialización por cada plataforma.

En Android, en la actividad principal vamos a incializar Xamarin.Essentials en el método OnCreate:

Xamarin.Essentials.Platform.Init(this, bundle);

Para poder gestionar en tiempo de ejecución el acceso a los permisos necesarios, debemos añadir también:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
     Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

     base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

No se requiere código especifico por plataforma en iOS o UWP.

¿Y a continuación?.

A continuación, tenemos todo preparado para tener acceso a cada una de las APIs listadas previamente.

Por ejemplo, para verificar si tenemos acceso a Internet:

using Xamarin.Essentials;

if (Connectivity.NetworkAccess != NetworkAccess.Internet) 
{
     // No internet access 
}

O para enviar un SMS:

using Xamarin.Essentials;

var message = new SmsMessage(messageText, recipient);
await Sms.ComposeAsync(message);

Al igual que Xamarin.Forms u otras grandes piezas relacionadas con Xamarin, Xamarin.Essentials es Open Source. Puedes utilizar GitHub para abrir una Issue o bien, puedes añadir acceso a una nueva API enviando una pull request.

Más información

[Material] “Plugins, Multi-Targeting y NuGets” y “Primer vistazo a novedades de Xamarin.Forms 3.0”

El evento

El pasado 24 de Abril desde CartujaDotNet y SVQXDG, grupo de desarrolladores .NET y Xamarin de Sevilla respectivamente, se organizaba un evento donde vimos por un lado la gestión de código multiplataforma, como crear plugins para Xamarin, paquetes NuGet así como las opciones de MultiTargeting mientras que en otra sesión vimos las principales novedades de Xamarin.Forms 3.0 Preview.

El material

En la primera sesión “Plugins, Multi-Targeting y NuGets” partimos de un caso común de necesidad de acceder a características específicas de cada plataforma. Analizando pros y contras a la hora de compartir y reutilizar fuimos progresando poco a poco hasta ver MultiTargeting, creación de NuGets, etc.

En cuanto a las demos realizadas, se encuentran disponibles en GitHub:

Ver GitHub

Seguimos el evento con la segunda sesión “Primer vistazo a novedades de Xamarin.Forms 3.0”. Dimos un repaso por:

  • FlexLayout
  • VisualStateManager
  • CSS
  • RTL
  • Nuevas plataformas: WPF & GTK
  • Etc

La presentación se encuentra disponible en SlideShare.

En cuanto a las demos realizadas, se encuentran disponibles en GitHub:

Ver GitHubNos vemos en la próxima!

Más información

[Tips and Tricks] Corregir “Xcode license must be accepted in order to be connected…”

El problema

Tras actualizar XCode a una versión posterior y desde entonces al intentar conectar desde Windows utilizando Xamarin Mac Agent…

Oops!

El mensaje de error nos lo deja todo muy claro, debemos abrir XCode y aceptar la neuva licencia. Sin embargo, tras abrir XCode, nunca salta la ventana para poder aceptar la licencia.

¿Qué ocurre?, ¿qué podemos hacer?.

La solución

Encontramos una sencilla solución al poder aceptar la licencia de XCode utilizando la línea de comandos.

Abre XCode y dirígete a Preferences > Locations. Asegúrate de tener establecida a la última versión de XCode la opción Command Line Tools:

Command Line Tools

Todo preparado. Abre una línea de comandos y ejecuta:

sudo xcodebuild -license

Acepta la licencia (agree), vuelve a Visual Studio en Windows e intenta de nuevo establecer una conexión. Todo debería funcionar sin problemas.

Más información

Crear Add-ins para Visual Studio para macOS utilizando Xamarin.Forms

Crear add-ins para Visual Studio macOS

Visual Studio para macOS esta basado en MonoDevelop. Antes de lanzarnos de lleno a crear un Add-in es importante conocer lo que se conoce como el modelo de extensión. La arquitectura de Visual Studio para macOS es extensible. La forma de extender se basa en rutas de extensión que permiten que terceros extiendan el comportamiento. Por ejemplo: para extender la zona de edición de código, se expone /MonoDevelop/SourceEditor2/ContextMenu/Editor permitiendo añadir nuevos comandos en el menu contextual al hacer clic derecho.

AddIn Maker

AddIn Maker es un proyecto Open Source creado por Mikayla Hutchinson que permite el desarrollo y la depuración de add-ins para Visual Studio macOS desde Visual Studio macOS.

Para añadirlo, nos dirimos al menu principal de Visual Studio y pulsamos sobre Addins…

Desde aquí podemos gestionar Addins en Visual Studio.

Crear proyecto de Add-in

Tras instalar AddIn Maker, tenemos accefso a un nuevo tipo de proyecto, Addin.

Seleccionamos la nueva plantilla, asignamos un nombre y continuamos.

Xamarin.Forms GTK

Llegamos a este punto, habitualmente, crearíamos nuestra interfaz de usuario utilizando GTK# o XWT. Cuando hablamos de XWT nos referimos a un tookit cross platform de UI para crear aplicaciones de escritorio con Mono y .NET.

Recientemente, hemos recibido los paquetes NuGet de la versión Preview de Xamarin.Forms 3.o. Entre las diferentes novedades encontramos soporte a Linux. El soporte de Linux se logra con un nuevo backend basado en GTK#.

Por lo que si usamos GTK#, ¿podríamos usar XAML y Xamarin.Forms para definir la UI de add-ins para Visual Studio?.

Es una posibilidad que personalmente he pensado en multitud de ocasiones e incluso lo he llegado a hablar con miembros de la comunidad Xamarin como con Matthew Robbins creador de MFRactor (tuvimos una genial conversación en el pasado MVP Summit).

Manos a la obra!

Comenzamos creando un proyecto de tipo IDE Extension:

IDE Extension

Este proyecto ya cuenta con la referencia a MonoDevelop.Addins, versión 0.4.4 al escribir este artículo. Continuamos añadiendo el paquete NuGet de Xamarin.Forms

Xamarin.Forms.Platform.GTK

Para trabajar con Xamarin.Forms, debemos realizar la inicialización. La mejor opción para realizar esta tarea es realizarla nada más se abra el IDE. Para ello, vamos a crear un comando:

public class InitXamarinFormsCommand : CommandHandler
{
     protected override void Run()
     {
          Forms.Init();
     }
}

Y modificaremos el archivo Manifiest.addin.xml para añadir nuestro comando como punto de extensión en el arranque del IDE.

<Extension path="/MonoDevelop/Ide/StartupHandlers">
      <Class class="LiveXAMLAddin.Commands.InitXamarinFormsCommand"/>
</Extension>

Llega la hora de extender. En nuestro caso, vamos a crear un sencillo Previewer de XAML para Xamarin.Forms.

NOTA: El objetivo de este ejemplo es demostrar como utilizar Xamarin.Forms para definir la UI de extensiones par Visual Studio. No estamos ante un nuevo Previewer de XAML. Aunque el funcionamiento es bastante rápido y correcto, no es el objetivo buscado.

Añadimos otro punto de extensión:

<Extension path = "/MonoDevelop/Ide/MainMenu/Edit">
     <CommandItem id="LiveXAMLAddin.Commands.PreviewXAMLCommand"/>
</Extension>

Fíjate que en esta ocasión, añadiremos un nuevo comando en el menu principal, opción editar.

Veamos la definición del comando:

public class PreviewXAMLCommand : CommandHandler
{
     protected override void Run()
     {
          Pad pad = null;

          var pads = IdeApp.Workbench.Pads;

          foreach (var p in IdeApp.Workbench.Pads)
          {
               if (string.Equals(p.Id, "LiveXAMLAddin.Pads.XAMLPreviewerPad", StringComparison.OrdinalIgnoreCase))
               {
                    pad = p;
               }
          }

          if (pad == null)
          {
               var content = new Pads.XAMLPreviewerPad();

               pad = IdeApp.Workbench.ShowPad(content, "LiveXAMLAddin.Pads.XAMLPreviewerPad", "XAML Previewer", "Right", null);

               if (pad == null)
                    return;
          }

          pad.Sticky = true;
          pad.AutoHide = false;
          pad.BringToFront();
     }

     protected override void Update(CommandInfo info)
     {
          info.Visible = true;

          if (IdeApp.Workbench.ActiveDocument != null && IdeApp.Workbench.ActiveDocument.FileName.ToString().Contains(".xaml"))
          {
               info.Enabled = true;
          }
          else
          {
               info.Enabled = false;
          }
     }
}

Reconoces a un Pad como un panel lateral anclable tanto a izquierda como derecha. En esta ocasión, creamos un nuevo Pad donde mostrar la previsualización de XAML, de título “XAML Previewer” y anclado a la derecha.

Para habilitar la opción de menu, vamos a determinar si el usuario esta editando un archivo XAML. Para ello, utilizamos IdeApp.Workbench.ActiveDocument. Tenemos posibilidad de acceder a toda la información del documento, como su formato o contenido.

Utilizando XAML para definir UI

¿Qué vamos a mostrar en el Pad?

Vamos a utilizar XAML!.  Creamos una nueva ContentPage:

<ContentPage 
     xmlns="http://xamarin.com/schemas/2014/forms" 
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
     x:Class="LiveXAMLAddin.Views.PreviewerView">
     <ContentPage.Content>
          <Grid>
               <ContentView
                    Content="{Binding Preview}" />
          </Grid>
     </ContentPage.Content>
</ContentPage>

Tenemos acceso a todas las opciones disponibles con XAML, entre ellas, sistema de enlace a datos, etc.  Para utilizar la página XAML como contenido del Pad vamos a embeber el contenido:

var page = new PreviewerView();
var pageContainer = page.CreateContainer();

Tenemos disponible el método de extensión CreateContainer de Xamarin.Forms en el backend GTK para obtener la ContentPage como contenido nativo.

Cafa vez que se cambie el texto de la página XAML en el editor de Visual Studio, vamos a actualizar la previsualización XAML:

IdeApp.Workbench.ActiveDocument.Editor.TextChanged += (sender , args) =>
{ 
     PreviewXaml(IdeApp.Workbench.ActiveDocument.Editor.Text);
};

Podemos utilizar MVVM (de hecho en este ejemplo se usa) en combinación con toda la potencia y las opciones de extensión que tenemos.

El resultado:

El resultado

Tienes el código fuente del ejemplo disponible GitHub:

Ver GitHub

¿Qué te parece?. Quizás en un futuro sea una opción a la hora de extender Visual Studio. Ahora que tenemos el IDE en más de un sistema operativo, es hora de pensar en contar con una opción para crear extensiones que compartan la mayor cantidad de código posible.

Más información

[Evento CartujaDotNet] Plugins, Multi-Targeting y NuGets

El evento

En un proyecto multiplataforma, una buena arquitectura y organizar de forma adecuada nuestro código nos permite compartir grandes cantidades de código entre las diferentes plataformas soportadas. Pero…¿y con otros proyectos?, ¿la comunidad?.

En este evento vamos a ver como crear librerías multiplataforma con funcionalidad específica por cada una de ellas utilizando múltiples proyectos así como el Multi-Targeting. Además, vamos a revisar las mejores opciones para compartir con la comunidad así como la creación de paquetes NuGet.

El lugar

El evento se celebrará en la ETS de Ingeniería Informática. Dirección detallada:

E.T.S. Ingeniería Informática – Universidad de Sevilla, Aula B1.32
Av. Reina Mercedes s/n
Sevilla Se 41012

La fecha

Será el próximo Martes, 24 de Abril de 19:00h a 20:30h (GMT+1).

¿Te apuntas?

Más información

[Xamarin.Forms] Creando un Walkthrough usando Lottie

Introducción

A la hora de desarrollar aplicaciones móviles nos encontramos con ciertas necesidades a cubrir. Una bastante habitual es la de ofrecer en una experiencia sencilla y fluida una breve explicación de la propia aplicación, su funcionalidad o características más importantes.

Walkthrough

Para evitar que el usuario acabe “saltando” (Skip) el tutorial, es necesario atraer su atención. En este artículo, vamos a crear un Walkthrough o tutorial donde vamos a utilizar Lottie, animaciones de diferente tipo para conseguir atraer la atención de usuario.

Creando el Carousel

Comenzamos por la parte fundamental, el Carousel. El Carousel es un control que contiene una colección de contenido permitiendo navegar entre el mismo realizando un gesto de deslizamiento lateral.

Entre las diferentes opciones que tenemos disponibles (recuerda que existe paquete oficial para obtener un Carousel) tenemos CarouselView de Alexander Reyes. Es una opción interesante al permitir trabajar con:

  • Indicadores de posición.
  • Orientación: Vertical o Horizontal.
  • Animaciones
  • Control sobre estado, posición, si se muestran flechas para la navegación o no, etc.

CarouselView.FormsPlugin

Para trabajar con este Carousel, tras añadir el paquete NuGet correspondiente, añadimos el siguiente namespace en XAML:

xmlns:carousel="clr-namespace:CarouselView.FormsPlugin.Abstractions;assembly=CarouselView.FormsPlugin.Abstractions"

La definición básica del control es sencilla:

<carousel:CarouselViewControl />

Bien, en nuestro caso, cada paso del tutorial será una ContentView. Podemos gestionar la colección de diferentes formas, una sencilla:

_views = new View[]
{
     new BikingHardView(),
     new AcrobaticsView(),
     new SoExcitedView(),
     new BikingCoolView()
};

Y utilizando la propiedad ItemsSource (se puede utilizar un enlace a datos), establecemos la colección.

Carousel.ItemsSource = _views;

Tenemos lo básico. Continuamos!.

Lottie a escena!

Utilizando páginas estáticas, sin movimiento, podemos conseguir la atención del usuario con una buena combinación de uso de imágenes, fuentes y otros recursos visuales.

Con un poco de “acción” lo tenemos más sencillo. Tenemos la posibilidad de trabajar con Lottie desde Xamarin para Android, iOS, así como en UWP y en Xamarin.Forms gracias a la gran comunidad Xamarin.

¿Qué es Lottie?

Airbnb ha desarrollado una herramienta Open Source con la que facilitar la creación de animaciones móviles. Podemos utilizar animaciones potentes creadas con After Effects y utilizarlas desde nuestras aplicaciones móviles de forma sencilla.

Para trabajar con Lottie en Xamarin.Forms, comenzamos añadiendo un paquete NuGet:

Lottie Xamarin.Forms

Recuerda añadirlo en cada proyecto de plataforma además de en la librería .NET Standard.

Para completar el proceso de preparación de Lottie en nuestro proyecto Xamarin.Forms, necesitamos añadir la siguiente línea tras la inicialización de Xamarin.Forms en cada proyecto nativo:

AnimationViewRenderer.Init();

Todo listo!.

Para mostrar la animación necesitamos un elemento visual que nos permita además realizar una gestión de la misma. Este elemento visual es AnimationView.

Para utilizar AnimationView desde XAML necesitamos utilizar el siguiente espacio de nombres:

xmlns:lottie="clr-namespace:Lottie.Forms;assembly=Lottie.Forms"

La interfaz:

<forms:AnimationView
     Animation="bikingishard.json"
     AutoPlay="true"
     Loop="True"
     Speed="1"
     HorizontalOptions="FillAndExpand"
     VerticalOptions="FillAndExpand" />

Hasta este punto, de forma sencilla, conseguimos un resultado bastante atractivo.

Obtener recursos

Un gran fuente de animaciones es LottieFiles. Puedes encontrar una gran variedad de animaciones listas para utilizar con opciones de búsqueda, etc.

LottieFiles

NOTA: Si usas animaciones de LottieFiles, recuerda otorgar crédito a sus creadores.

Añadimos más animaciones

Podemos continuar mejorando todo. En cada paso del tutorial vamos a añadir información relevante en texto y otros elementos visuales. Vamos a necesitar saber cuando el usuario pasa de un paso a otro.

De forma sencilla, podemos crear una interfaz como la siguiente:

public interface IAnimatedView
{
     void StartAnimation();
}

De modo que, cada vez que el usuario cambie la ContentView seleccionada, si el paso hereda de nuestra interfaz, ejecutamos la implementación de la misma.

var currentView = _views[e.NewValue];

if (currentView is IAnimatedView animatedView)
{
     animatedView.StartAnimation();
}

¿Qué conseguimos con esto?

Vamos a añadir otra dependencia vía NuGet con la librería Xamanimation. Esta pequeña librería añade una gran variedad de animaciones predefinidas además de la posibilidad de crear Storyboards, lanzar animaciones desde XAML, etc.

NOTA: Xamanimation formará parte del bloque de animaciones del Toolkit de Xamarin.Forms.

Añadimos espacio de nombres en XAML:

xmlns:xamanimation="clr-namespace:Xamanimation;assembly=Xamanimation"

Y podemos definir una animación de la siguiente forma:

<xamanimation:StoryBoard
     x:Key="InfoPanelAnimation"
     Target="{x:Reference InfoPanel}">
     <xamanimation:FadeToAnimation
          Duration="50"
          Opacity="1" />
     <xamanimation:TranslateToAnimation
          TranslateY="0"
          Easing="CubicIn"
          Duration="100" />
</xamanimation:StoryBoard>

Esta animación, animará un elemento visual marcado con el nombre InfoPanel, primero la opacidad de su estado inicial, 0, es decir, no visible, a 1 además de realizar una trasladación en el eje Y.

Para lanzarla:

if (Resources["InfoPanelAnimation"] is StoryBoard animation)
{
     animation.Begin();
}

Sencillo, ¿verdad?.

De igual forma, aprovechamos algunas animaciones de la librería para animar el color de fondo al pasar de un paso a otro entre otros detalles.

El resultado:

El resultado

NOTA: Las animaciones de Lottie de este ejemplo corresponden a Yue XI de LottieFiles.

Tienes el código fuente del ejemplo disponible GitHub:

Ver GitHub

Más información