El próximo 12 de septiembre a las 4:00pm estaré en TelmexHub hablando sobre Xamarin y sus ventajas en el desarrollo multiplataforma.
El objetivo de la charla es conocer el porque Xamarin es una excelente herramienta para desarrollar Apps para IOS y Android además de poder utilizar ese mismo código en aplicaciones Windows Phone, Desktop, Web y otras plataformas que usan C# como lenguaje nativo.
Esta platica no será de desarrollar mucho código por lo cual no es necesario asistir con equipo a menos de que quieran realizar el ejemplo, aunque esta es mas una platica para dar a conocer como funciona Xamarin y hablar sobre como es el tema de las licencias y los beneficios que existen actualmente para los estudiantes.
Después de esta platica tengo planeado ofrecer un curso de C# como preparación a un futuro curso de Xamarin Android/IOS y apps para Windows Store.
Hace unos días encontré una etiqueta NFC que tengo desde hace unos años y por curiosidad decidí probar si aun funcionaba. Después de comprobar que aun funciona decidí actualizar mi App, la cual estaba hecha para Windows Phone 8, a Windows Phone 8.1 utilizando la función que sirve para generar una vCard para compartir datos de contacto mediante NFC.
Parte teórica
Elegí esta función sobre otras (escribir un “Hola Mundo” o un enlace a una página web) debido a que el crear una vCard involucra entender de mejor manera un estándar para almacenar datos NFC, voy a tratar de explicarlo de manera muy rápida, dejando algunas fuentes que me sirvieron por si quieren conocer mas a fondo del tema.
El estándar NDEF (Data Exchange Format) creado por el NFC Forum sirve para definir la estructura de datos de aplicación que se transmiten entre dos dispositivos NFC. Por otro lado el NFC Forum también definió el concepto de “NFC Forum Type Tag Operations” el cual sirve para identificar el tipo de operación que va a realizar una TAG NFC.
Ya entrando al tema importante del post, lo primero es tener el formato en que se guardara la información de contacto en la etiqueta NFC, el cual es el siguiente para este ejemplo:
Se pueden agregar mas datos siguiendo el estándar de una vCard, en este caso con la información de Wikipedia es suficiente https://en.wikipedia.org/wiki/VCard
Resumiendo todo lo mencionado anteriormente, lo que se va a hacer el lo que muestra este diagrama tomado del primer pdf sobre NDEF que deje mas arriba
La entrada son los datos que se van a almacenar, en este caso los de la tarjeta de contacto
El mensaje NDEF que encapsula lo anterior. Este mensaje tiene la siguiente estructura:
Parte importante aquí es que el mensaje define el tipo de dato que contiene, en el PDF se encuentra una lista muy completa de los tipos de dato. Algunos ejemplos (incluido el que usaremos)
El NFC Type Tag Platform, para entender mejor esto si hay que leer la especificación del NFC Forum debido a que habla de las especificaciones de las etiquetas como la memoria, velocidad, etc.
Y finalmente la etiqueta donde se va a almacenar esta información.
Parte practica
Ahora si ya viene el código, para empezar definimos la interfaz XAML de nuestra aplicación, la cual simplemente contiene los campos con los datos (Nombre, apellido, teléfono y e-mail)
<Page
x:Class="NfcVCard.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NfcVCard"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contiene el nombre de la aplicación y el título de la página-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="NFC Writer" Style="{StaticResource SubheaderTextBlockStyle}"/>
<TextBlock Text="vcard" Margin="9,-7,0,0" Style="{StaticResource HeaderTextBlockStyle}"/>
</StackPanel>
<!--ContentPanel. Colocar aquí el contenido adicional-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock>Nombre</TextBlock>
<TextBox InputScope="NameOrPhoneNumber" x:Name="txtNombre"></TextBox>
<TextBlock>Apellido</TextBlock>
<TextBox InputScope="NameOrPhoneNumber" x:Name="txtApellido"></TextBox>
<TextBlock>Telefono</TextBlock>
<TextBox InputScope="TelephoneNumber" x:Name="txtTelefono"></TextBox>
<TextBlock>Mail</TextBlock>
<TextBox InputScope="EmailSmtpAddress" x:Name="txtMail"></TextBox>
<Button x:Name="btnEscribir" Click="btnEscribir_Click">Escribir Tag</Button>
</StackPanel>
</Grid>
</Grid>
</Page>
Y el código de funcionalidad es el siguiente:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Networking.Proximity;
using Windows.Storage.Streams;
using Windows.UI.Popups;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=391641
namespace NfcVCard
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
/// <summary>
/// Invoked when this page is about to be displayed in a Frame.
/// </summary>
/// <param name="e">Event data that describes how this page was reached.
/// This parameter is typically used to configure the page.</param>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// TODO: Prepare page for display here.
// TODO: If your application contains multiple pages, ensure that you are
// handling the hardware Back button by registering for the
// Windows.Phone.UI.Input.HardwareButtons.BackPressed event.
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
}
ProximityDevice _device;
private void btnEscribir_Click(object sender, RoutedEventArgs e)
{
StatusBarProgressIndicator progressbar = StatusBar.GetForCurrentView().ProgressIndicator;
progressbar.ShowAsync();
progressbar.Text = "Acerca la etiqueta";
btnEscribir.IsEnabled = false;
string nombreCompleto = txtNombre.Text + " " + txtApellido.Text;
string nombre = txtNombre.Text;
string apellido = txtApellido.Text;
string celular = txtTelefono.Text;
string mail = txtMail.Text;
//Obtenemos el dispositivo NFC del teléfono
_device = ProximityDevice.GetDefault();
//Creamos la tarjeta virtual con el formato que debe ser
var vcard = string.Format("BEGIN:VCARD\nVERSION:2.1\nFN:{0}\nN:{1};{2}\nTEL;CELL:{3}\nEMAIL;INTERNET:{4}\nEND:VCARD", nombreCompleto, apellido, nombre, celular, mail);
//El DataWriter que contiene los datos para escribir el mensaje binario a la etiqueta NFC
var dataWriter = new DataWriter() { UnicodeEncoding = UnicodeEncoding.Utf8 }; dataWriter.WriteString(vcard);
//Publicamos el mensaje binario en la etiqueta NFC, definimos el tipo de mensaje que es y támbien que método se va a ejecutar al finalizar el guardado
_device.PublishBinaryMessage("WindowsMime:WriteTag.text/vcard", dataWriter.DetachBuffer(), MesssageTransmitted);
}
private async void MesssageTransmitted(ProximityDevice sender, long messageId)
{
//Le indicamos al dispositivo que deje de escribir el mensaje
_device.StopPublishingMessage(messageId);
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
StatusBarProgressIndicator progressbar = StatusBar.GetForCurrentView().ProgressIndicator;
progressbar.HideAsync();
btnEscribir.IsEnabled = true;
new MessageDialog("Contenido guardado").ShowAsync();
});
}
}
}
Para que lo anterior funcione de manera correcta hay que hacer dos cosas extra, hay que darle los permisos necesarios a la aplicación para que pueda usar el sensor NFC, de lo contrario obtendremos el error
An exception of type 'System.UnauthorizedAccessException' occurred in NfcVCard.ni.EXE but was not handled in user code
Additional information: Access is denied.
Esto se hace en el Manifiesto en la secciones de “Requirements” y “Capabilities”
En este enlace dejo el código fuente: Proyecto NFC
Aquí también un pequeño video de muestra de como se ve el proyecto en acción y como la etiqueta se puede leer perfectamente desde WP y desde un dispositivo con Android.
Si publicaste una app para Windows Phone antes del día de hoy (17 de agosto de 2015) puedes pedir una licencia de Xamarin IOS y Android gratis la cual incluye el soporte para Visual Studio.
Esta oferta termina el 31 de Agosto para los desarrolladores independientes que quieran una suscripción para uso personal y no aplica para clientes actuales de Xamarin.