Día del maestro – FacultyCol, WebGL Demo 2 parte 3


Para finalizar esta serie de tutoriales concluiré con el último paso de esta demo de poder controlar un Photosynth mediante mi móvil; recapitulando ya tenemos el servidor funcionando, tenemos el bridge entre IE y el server, nos queda hacer la App, la cual para esta usaré Xamarin con C#. En Xamarin Studio crearemos un proyecto nuevo para Android llamado “AndroidAppXamarin”, cuando esté creado iremos a “Resources/layout/Main.axml” el cual es el archivo para nuestra interfaz gráfica, aquí crearemos todos los elementos necesarios para que nuestra App pueda funcionar. Necesitaremos los siguientes controles:

  • 2 TextView.
  • 2 Spinner.
  • 1 SeekBar.
  • 1 Button.
  • 1 LinearLayout con 3 botones.

Y nos quedará una interfaz algo parecida a la siguiente: Por el momento probablemente no se ve así tal cual, pero tranquilos, el código es el siguiente:  

<!--?xml version="1.0" encoding="utf-8"?-->

    
    
    
    
    
    <button>
    
        </button><button>
        </button><button>
        </button><button>
    </button>

Ahora solo nos queda darle funcionalidad a todos los controles; para ello vamos a descargar SocketIO4Net.Client desde CodePlex http://socketio4net.codeplex.com/  el cual compilaremos y nos dará los ensamblados que necesitamos, si no saben o cualquier otra cosa les adjunto los ensamblados necesarios en este link: http://1drv.ms/1k6fiK5, hay que tener en cuenta la fecha de esta publicación porque este proyecto seguirá avanzando y posiblemente aparezcan nuevas características y nuevas cosas. Luego de haber descargado estos ensamblados será igual que en Visual Studio, nos referimos a la carpeta de “References” y los añadimos. Comenzaré por partes y al final mostraré el código completo si queda algo suelto o confuso. Crear las propiedades de la clase las cuales definirán el explorador de Internet, el titulo de la ventana, el tiempo de ejecución y el socket donde nos conectaremos

		string _explorer = "iexplore";
		string _title = "The Monegaw Caves Hideout Out";
		string _time = "1000";

		Client socket;

En el método OnCreate definir los eventos para cada botón (arriba, abajo, derecha o izquierda)

			FindViewById<button> (Resource.Id.upButton).Click += upButton_Click;
			FindViewById</button><button>(Resource.Id.rightButton).Click += rightButton_Click;
			FindViewById</button><button>(Resource.Id.leftButton).Click += leftButton_Click;
			FindViewById</button><button> (Resource.Id.downButton).Click += downButton_Click;

Se define el comportamiento de los Spinner y asignandosele una lista de datos.

			#region Spinners
			Spinner spinnerExplorer = FindViewById (Resource.Id.ExplorerSelect);
			spinnerExplorer.ItemSelected += new EventHandler (spinner_ItemSelected);
			var adapterExplorer = ArrayAdapter.CreateFromResource (this, Resource.Array.Explorers, Android.Resource.Layout.SimpleSpinnerItem);
			adapterExplorer.SetDropDownViewResource (Android.Resource.Layout.SimpleSpinnerDropDownItem);
			spinnerExplorer.Adapter = adapterExplorer;

			Spinner spinnerTitle = FindViewById (Resource.Id.PhotosynthSelect);
			spinnerTitle.ItemSelected += new EventHandler (spinner2_ItemSelected);
			var adapterTitle = ArrayAdapter.CreateFromResource (this, Resource.Array.Titles, Android.Resource.Layout.SimpleSpinnerItem);
			adapterTitle.SetDropDownViewResource (Android.Resource.Layout.SimpleSpinnerDropDownItem);
			spinnerTitle.Adapter = adapterTitle;
			#endregion

Para que la barra de progreso funcione debemos definirle su comportamiento y mostrar el resultado en el TextView correspondiente.

			var _seekBar = FindViewById(Resource.Id.TimeSeek);
			var _textView = FindViewById(Resource.Id.seekValue);

			_seekBar.Progress = 1000;

			_seekBar.ProgressChanged += (object sender, SeekBar.ProgressChangedEventArgs e) =>
			{
				if (e.FromUser)
				{
					_textView.Text = string.Format("{0}", e.Progress);
					_time = e.Progress.ToString();
				}
			};

Conexión al socket y creación de sus eventos necesarios para controlar toda la conexión.

			socket = new Client("http://138.91.126.161:3000/"); // url to nodejs
			socket.Opened += SocketOpened;
			socket.Message += SocketMessage;
			socket.SocketConnectionClosed += SocketConnectionClosed;
			socket.Error += SocketError;

			// Conexión al servidor luego de haber configurado toda conexión.
			socket.Connect ();

			// Por si llega un mensaje de otro cliente.
			socket.On ("message", (data) => {
				Messages part = data.Json.GetFirstArgAs ();
				Android.Widget.Toast.MakeText(this, part.username + ": " + part.message, ToastLength.Long).Show();
			});

Definición de métodos de los eventos de los Spinner creados (acción que hacen cuando un item es seleccionado).

		void spinner2_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
		{
			Spinner spinner = (Spinner)sender;
			_title = (spinner.GetItemAtPosition (e.Position)).ToString();
		}

		void spinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
		{
			Spinner spinner = (Spinner)sender;
			var explorer = (spinner.GetItemAtPosition (e.Position)).ToString();

			if (explorer.Equals("Internet Explorer")) {
				_explorer = "iexplore";
			}
			else if (explorer.Equals ("Chrome")) {
				_explorer = "chrome";
			}
			else if (explorer.Equals("Firefox")) {
				_explorer = "firefox";
			}
		}

Ahora definimos los métodos que se ejecutan cuando se hace click a un botón y envían un mensaje al servidor. En este punto cabe aclarar que en la anterior parte de estos tutoriales podíamos ver que cada comando se hacía un split por el símbolo ‘-‘ y porque desde aquí envío el mensaje con este símbolo como separador.

			void upButton_Click(object sender, EventArgs e)
			{
				Messages newMess = new Messages() { username = "Android", message = "Up-" + _time + "-" + _title + "-" + _explorer };
				socket.Emit ("send", newMess);
			}

			void downButton_Click(object sender, EventArgs e)
			{
				Messages newMess = new Messages() { username = "Android", message = "Down-" + _time + "-" + _title + "-" + _explorer };
				socket.Emit ("send", newMess);
			}

			private void rightButton_Click(object sender, EventArgs e)
			{
				Messages newMess = new Messages() { username = "Android", message = "Right-" + _time + "-" + _title + "-" + _explorer };
				socket.Emit("send", newMess);
			}

			private void leftButton_Click(object sender, EventArgs e)
			{
				Messages newMess = new Messages() { username = "Android", message = "Left-" + _time + "-" + _title + "-" + _explorer };
				socket.Emit("send", newMess);
			}

Por último definimos los métodos necesarios para la conexión, en este caso los dejé vacíos porque en esta demostración no necesitaba hacer ninguna validación más, pero en un caso de la vida real estos métodos proporcionan información vital para nuestra aplicación, así que hay que tenerlos muy presentes.

		void SocketOpened (object sender, EventArgs e){ }

		void SocketMessage (object sender, MessageEventArgs e){ }

		void SocketConnectionClosed (object sender, EventArgs e){ }

		private void SocketError(object sender, ErrorEventArgs e){ }

Finalmente, este es el código completo.

using System;
using System.Collections.Generic;
using System.Collections;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Locations;
using Android.Util;

using System.Threading;
using System.Text;
using System.Linq;
using System.Xml;

using SocketIOClient;

namespace AndroidAppXamarin
{
	[Activity (Label = "AndroidAppXamarin", MainLauncher = true)]
	public class MainActivity : Activity
	{

		string _explorer = "iexplore";
		string _title = "The Monegaw Caves Hideout Out";
        string _time = "1000";

		Client socket;

		protected override void OnCreate (Bundle bundle)
		{
			base.OnCreate (bundle);
			//Log.Debug (tag, "OnCreate called");

			// Set our view from the "main" layout resource
			SetContentView (Resource.Layout.Main);

			FindViewById<button> (Resource.Id.upButton).Click += upButton_Click;
            FindViewById</button><button>(Resource.Id.rightButton).Click += rightButton_Click;
            FindViewById</button><button>(Resource.Id.leftButton).Click += leftButton_Click;
			FindViewById</button><button> (Resource.Id.downButton).Click += downButton_Click;

			Spinners ();

			SeekBar ();

			Socket ();
		}

		void Spinners ()
		{
			#region Spinners
			Spinner spinnerExplorer = FindViewById (Resource.Id.ExplorerSelect);
			spinnerExplorer.ItemSelected += new EventHandler (spinner_ItemSelected);
			var adapterExplorer = ArrayAdapter.CreateFromResource (this, Resource.Array.Explorers, Android.Resource.Layout.SimpleSpinnerItem);
			adapterExplorer.SetDropDownViewResource (Android.Resource.Layout.SimpleSpinnerDropDownItem);
			spinnerExplorer.Adapter = adapterExplorer;
			Spinner spinnerTitle = FindViewById (Resource.Id.PhotosynthSelect);
			spinnerTitle.ItemSelected += new EventHandler (spinner2_ItemSelected);
			var adapterTitle = ArrayAdapter.CreateFromResource (this, Resource.Array.Titles, Android.Resource.Layout.SimpleSpinnerItem);
			adapterTitle.SetDropDownViewResource (Android.Resource.Layout.SimpleSpinnerDropDownItem);
			spinnerTitle.Adapter = adapterTitle;
			#endregion
		}

		void SeekBar ()
		{
			var _seekBar = FindViewById (Resource.Id.TimeSeek);
			var _textView = FindViewById (Resource.Id.seekValue);
			_seekBar.Progress = 1000;
			_seekBar.ProgressChanged += (object sender, SeekBar.ProgressChangedEventArgs e) =>  {
				if (e.FromUser) {
					_textView.Text = string.Format ("{0}", e.Progress);
					_time = e.Progress.ToString ();
				}
			};
		}

		void Socket ()
		{
			socket = new Client ("http://138.91.126.161:3000/");
			// url to nodejs
			socket.Opened += SocketOpened;
			socket.Message += SocketMessage;
			socket.SocketConnectionClosed += SocketConnectionClosed;
			socket.Error += SocketError;
			socket.Connect ();
			socket.On ("message", data =>  {
				Messages part = data.Json.GetFirstArgAs ();
				Android.Widget.Toast.MakeText (this, part.username + ": " + part.message, ToastLength.Long).Show ();
			});
		}

		void spinner2_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
		{
			Spinner spinner = (Spinner)sender;
			_title = (spinner.GetItemAtPosition (e.Position)).ToString();
		}

		void spinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
		{
			Spinner spinner = (Spinner)sender;
			var explorer = (spinner.GetItemAtPosition (e.Position)).ToString();

			if (explorer.Equals("Internet Explorer")) {
				_explorer = "iexplore";
			}
			else if (explorer.Equals ("Chrome")) {
				_explorer = "chrome";
			}
			else if (explorer.Equals("Firefox")) {
				_explorer = "firefox";
			}
		}

		void upButton_Click(object sender, EventArgs e)
		{
            Messages newMess = new Messages() { username = "Android", message = "Up-" + _time + "-" + _title + "-" + _explorer };
			socket.Emit ("send", newMess);
		}
		void downButton_Click(object sender, EventArgs e)
		{
            Messages newMess = new Messages() { username = "Android", message = "Down-" + _time + "-" + _title + "-" + _explorer };
			socket.Emit ("send", newMess);
		}
        private void rightButton_Click(object sender, EventArgs e)
        {
            Messages newMess = new Messages() { username = "Android", message = "Right-" + _time + "-" + _title + "-" + _explorer };
            socket.Emit("send", newMess);
        }
        private void leftButton_Click(object sender, EventArgs e)
        {
            Messages newMess = new Messages() { username = "Android", message = "Left-" + _time + "-" + _title + "-" + _explorer };
            socket.Emit("send", newMess);
        }

		void SocketOpened (object sender, EventArgs e){ }

		void SocketMessage (object sender, MessageEventArgs e){ }

		void SocketConnectionClosed (object sender, EventArgs e){ }

		private void SocketError(object sender, ErrorEventArgs e){ }

}

}

Por último se demuestra en un vídeo el funcionamiento de todo. http://www.youtube.com/watch?v=Mjs_MEfWgsM