Conectarse a socket.io de Nodejs con Android (parte 1)

logo android

Voy a separar este post en dos partes, la primera es simplemente la implementación de la librería en nuestro proyecto, y en la segunda crearemos un chat y un pequeño servidor para probar como funciona.
Lo primero es agregar la dependencia de la librería a nuestro archivo grade en nuestro proyecto en Android Studio.

compile 'com.github.nkzawa:socket.io-client:0.4.0'

Así en la actividad que queramos utilizar el socket creamos el objeto Socket.

Socket socket;

y algunas constantes que utilizaremos en nuestro código.

final static String URL_SOCKET = "http://localhost";
final static String MY_EVENT = "my event";
final static String PARAM_NAME = "name";
final static String PARAM_IMAGE = "image";

Instanciamos nuestra conexión al servidor pasando como parámetro la url de este mismo.

try{
  /* Instance object socket */
  socket = IO.socket(URL_SOCKET);
}catch (URISyntaxException e){
  e.printStackTrace();
}

Podemos instanciar el objecto con opciones predeterminadas para que se reconecte el socket.

IO.Options opts = new IO.Options();
opts.forceNew = true;
opts.reconnection = false;
try{
  /* Instance object socket */
  socket = IO.socket(URL_SOCKET, opts);
}catch (URISyntaxException e){
  e.printStackTrace();
}

O para utilizar conexiones SSL por defecto o como parámetro al instanciar el objeto

/* Default SSLContext for all sockets */
IO.setDefaultSSLContext(mySSLContext);

/* Set as an option */
opts = new IO.Options();
opts.sslContext = mySSLContext;
try{
  /* Instance object socket */
  socket = IO.socket(URL_SOCKET, opts);
}catch (URISyntaxException e){
  e.printStackTrace();
}

Luego creamos los eventos principales de nuestro socket: EVENT_CONNECT y EVENT_DISCONNECT, estos son los que recibirán las emisiones desde el servidor.

socket.on(Socket.EVENT_CONNECT, new Emitter.Listener(){
  @Override
  public void call(Object... args) {
    /* Our code */
  }
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener(){
  @Override
  public void call(Object... args) {
    /* Our code */      
  }
});

Y crear nuestros propios eventos listener

socket.on(MY_EVENT, new Emitter.Listener(){
  @Override
  public void call(Object... args) {
    /* Our code */      
  }
});

Con esto ya podemos abrir la conexión

socket.connect();

Además disponemos de otras funciones como para verificar el estado de la conexión.

socket.connected()

Para desconectar nuestro socket.

socket.disconnect()

Si lo que queremos es emitir eventos por nuestro socket utilizamos, enviando cadenas de texto o también datos binarios.

JSONObject obj = new JSONObject();
obj.put(PARAM_NAME, "Pablo");
obj.put(PARAM_IMAGE, new byte[42]);

/* Emit event */
socket.emit(MY_EVENT, obj)

También podemos capturar el callback que retorna el servidor

socket.emit(MY_EVENT, obj, new Ack() {
  @Override
  public void call(Object... args) {
    /* Our code */
  }
});

Y eso es todo, en el próximo post haré un pequeño chat para que probemos como funciona.
Saludos!

Cambiar el tema de un fragment en Android

logo androidEstoy programando mucho en Android, pero no he subido nada al respecto, por lo que iré compartiendo pequeños códigos para hacer cosas especificas, que también claro, servirán para anotaciones personales mias.
Los fragment estan inmersos en las actividades que los contienen, por lo que no podemos cambiarlos directamente en el archivo AndroidManifest.xml, así que heredan los estilos que las actividades tengan definidas, y si estas últimas no tienen ningún tema definido heredan el que tenga la aplicación. Pero podemos cambiar esto utilizando las siguientes 3 lineas dentro de la función onCreateView de nuestro fragment.
Primero traemos el tema que queremos aplicar al fragment creando un objeto de contexto. Deben reemplazar MyAppTheme por su tema.

final Context themeWrapper = 
	new ContextThemeWrapper(getActivity(), R.style.MyAppTheme);

Luego definimos un LayoutInflater al cuál le aplicamos nuestro contexto anterior.

LayoutInflater cloneInflate = 
	inflater.cloneInContext(themeWrapper);

Y finalmente inflamos el layout de nuestro fragment utilizando el layout inflate definido anteriormente. Recuerden que deben reemplazar fragment_layout por el que corresponda con su fragment, y que será el que finalmente retornaremos en la función.

View view = 
	cloneInflate.inflate(R.layout.fragment_layout, container, false);

Eso es todo! Saludos!

Matemáticas, física y animación con Canvas html5 – parte 2

canvas
Estimados! Disculpen por dejar tanto tiempo el blog botado, ahora continuaré con los ejercicios de canvas. Este post es la continuación de Matemáticas, física y animación con Canvas html5 – parte 1. Para esta ocación no profundizaré tanto en puntos matemáticos como lo hice en la primera parte, por lo que recomiendo que si no la han leído lo hagan y luego continuen con esta.
Para este ejercicio vamos a crear muchas pelotas chocando con las paredes (no entre si) y moviendose a diferentes velocidades según el tamaño de cada una.
Si quieren ver el resultado bajen al final de este post
Al igual que el post anterior, comenzaré pegando todo el código para que lo vean y luego explicando cada uno de los puntos relevantes.
Comenzamos importando nuestra librería modernizr entre las etiquetas “head” de nuestro HTML para garantizar la compatibilidad de nuestro canvas con todos los navegadores.

<script src="http://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.1/modernizr.min.js"></script>

y dentro de nuestras etiquetas body creamos el canvas donde se dibujará nuestro script.

<div>
	<canvas id="canvasTwo" width="600" height="300"> 
		Cambiate de navegador!
	</canvas>
</div>

Ahora el código completo de nuestro javascript

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  canvasAppPartTwo();
}
function canvasSupport(){
  return Modernizr.canvas;
}
function canvasAppPartTwo(){
  if(!canvasSupport()){
    return;
  }

  function drawScreen(){
    context.fillStyle = '#EEEEEE';
    context.fillRect(0, 0, theCanvas.width, theCanvas.height);
    context.strokeStyle = '#000000';
    context.strokeRect(1, 1, theCanvas.width-2, theCanvas.height-2);
    
    var ball;
	for(var i = 0; i < balls.length; i++){
      ball = balls[i];
      context.fillStyle = ball.color;
      ball.x += ball.xunits;
      ball.y += ball.yunits;

      context.beginPath();
      context.arc(ball.x, ball.y, ball.radius, 0, Math.PI*2, true);
      context.closePath();
      context.fill();

	  if((ball.x+ball.radius) > theCanvas.width || ball.x < 0){       
        ball.angle = 180 - ball.angle;       
        updateBall(ball);     
      }else if((ball.y+ball.radius) > theCanvas.height || ball.y < 0){
        ball.angle = 360 - ball.angle;
        updateBall(ball);
      }
	}
  }
  function updateBall(ball){
	ball.radians = ball.angle * Math.PI/ 180;
    ball.xunits = Math.cos(ball.radians) * ball.speed;
    ball.yunits = Math.sin(ball.radians) * ball.speed;
  }

  var numBalls = 1000;
  var maxSize = 8;
  var minSize = 5;
  var maxSpeed = maxSize + 5;
  var balls = new Array();
  var tempBall;
  var tempX;
  var tempY;
  var tempSpeed;
  var tempAngle;
  var tempRadius;
  var tempRadians;
  var tempXunits;
  var tempYunits;
  var tempColor;

  theCanvas = document.getElementById('canvasTwo');
  context = theCanvas.getContext('2d');

  for(var i = 0; i < numBalls; i++){
    tempRadius = Math.floor(Math.random()*maxSize)+minSize;
    tempX = tempRadius*2 + (Math.floor(Math.random()*theCanvas.width)-tempRadius*2);
    tempY = tempRadius*2 + (Math.floor(Math.random()*theCanvas.height)-tempRadius*2);
    tempSpeed = maxSpeed-tempRadius;
    tempAngle = Math.floor(Math.random()*360);
    tempRadians = tempAngle * Math.PI/ 180;
    tempXunits = Math.cos(tempRadians) * tempSpeed;
    tempYunits = Math.sin(tempRadians) * tempSpeed;
    tempColor = '#'+Math.floor(Math.random()*16777215).toString(16);
    tempBall = {
      x: tempX,
      y: tempY,
      radius: tempRadius,
      speed: tempSpeed,
      angle: tempAngle,
      xunits: tempXunits,
      yunits: tempYunits,
      color: tempColor
    }
    balls.push(tempBall);
  }
  setInterval(drawScreen, 33);
}

Ahora explicaré las cambios. Los primero es determinar la función que se ejecutará al momento que se cargue el javascript.

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  canvasAppPartTwo();
}

Definimos un intervalo para ir ejecutando el canvas.

setInterval(drawScreen, 33);

Entonces en orden de ejecución debemos definir las variables que utilizares. Solo comentaré las nuevas que agregé a este ejemplo. Las demás son variables que utilizaremos de forma temporal.

var numBalls = 1000; // Numero de bolas
var maxSize = 8; // Tamaño máximo que pueden tener
var minSize = 5; // Tamaño minimo
var maxSpeed = maxSize + 5; // Velocidad máxima
var balls = new Array(); // Arreglo que contendrá las bolas que creemos.

Rerefenciamos el canvas en el contexto de nuestro script

theCanvas = document.getElementById('canvasTwo');
context = theCanvas.getContext('2d');

Lo siguiente es hacer un “for” que recorrerá para crear cada una de las pelotas, para este ejemplo serán 1000 (pueden poner el número que quieran, solo sean considerados con su máquina).

for(var i = 0; i < numBalls; i++){

}

Con esto vamos creando lo valores temprales de nuestras bolas. No me detendré en este punto porque ya está explicado en el primero post como voy sacando los cálculos, la única diferencia es que voy jugando con valores random.
Así encontes calculamos el radio entre el tamaño minimo que determinamos y el máximo.

tempRadius = Math.floor(Math.random()*maxSize)+minSize;

Luego calculamos la posición de la bola dentro del canvas, el valor random es el tamaño del canvas menos su radio al cuadrado.

tempX = tempRadius*2 + (Math.floor(Math.random()*theCanvas.width)-tempRadius*2);
tempY = tempRadius*2 + (Math.floor(Math.random()*theCanvas.height)-tempRadius*2);

La velocidad que está directamente relacionada con el tamaño de la bola, ya que mientras más grande sea, más lento debe moverse.

tempSpeed = maxSpeed-tempRadius;

Y los cambios de angulos en la dirección de nuestra bola.

tempAngle = Math.floor(Math.random()*360);
tempRadians = tempAngle * Math.PI/ 180;
tempXunits = Math.cos(tempRadians) * tempSpeed;
tempYunits = Math.sin(tempRadians) * tempSpeed;

FinaLmente le damos un color random a la pelota para poder diferenciarlas unas de otras.

tempColor = '#'+Math.floor(Math.random()*16777215).toString(16);

Ya teniendo todos los valores, agregamos la pelota a nuestro arreglo de bolas.

tempBall = {
	x: tempX,
    y: tempY,
    radius: tempRadius,
    speed: tempSpeed,
    angle: tempAngle,
    xunits: tempXunits,
    yunits: tempYunits,
    color: tempColor
}
balls.push(tempBall);				

Ya dentro de la función drawScreen dibujamos el contenedor de nuestro canvas.

context.fillStyle = '#EEEEEE';
context.fillRect(0, 0, theCanvas.width, theCanvas.height);
context.strokeStyle = '#000000';
context.strokeRect(1, 1, theCanvas.width-2, theCanvas.height-2);

Y volvemos a recorrer el arreglo de bolas para id dibujandolas dentro de nuestro canvas. Utilizaré la variable auxiliar ball donde iré referenciando cada bola.

var ball;
for(var i = 0; i < balls.length; i++){
								
}

Referenciamos los valores.

ball = balls[i];
ball.x += ball.xunits;
ball.y += ball.yunits;					

Y dibujamos la bola con su respectivo color y tamaño.

context.fillStyle = ball.color;
context.beginPath();
context.arc(ball.x, ball.y, ball.radius, 0, Math.PI*2, true);
context.closePath();
context.fill();

Ahora capturo el momento en donde la bola debe cambiar su dirección para no salir del canvas. Llamando a la función updateBall.

if((ball.x+ball.radius) > theCanvas.width || ball.x < 0){       
	ball.angle = 180 - ball.angle;       
    updateBall(ball);     
}else if((ball.y+ball.radius) > theCanvas.height || ball.y < 0){
	ball.angle = 360 - ball.angle;
    updateBall(ball);
}

Al comienzo del for definimos una variable auxiliar que ahora utilizamos para poder actualizar la bola fuera del for.

function updateBall(ball){
	ball.radians = ball.angle * Math.PI/ 180;
    ball.xunits = Math.cos(ball.radians) * ball.speed;
    ball.yunits = Math.sin(ball.radians) * ball.speed;
}													

Y por fin el resultado final! Hay varias cosas que podemos mejorar, como por ejemplo que las pelotas choquen entre ellas. Haré una tercera parte para eso.
Gracias por su tiempo y por espero que el tutorial les haya gustado.

Actualiza tu browser por la chucha!

Ya está disponible la versión beta de Jaampr

jaampr_logo

Jaampr es un proyecto de red social para Android (por ahora) en el cual llevo un tiempo trabajando. Consiste en una red social de actividades georeferenciada donde las personas pueden compartir lo que hacen y otras pueden unirse o interactuar con ellas. Ahora está en un proceso de beta así que sería de gran ayuda si mandan su feedback o reportar errores. Gracias!

Canvas y WebGL usando Three.js

canvas
Siguiendo con los post de Canvas. Les mostraré un pequeño ejemplo de la utilización de Three.js, una librería de Canvas y WebGL muy sencilla de implementar.
Lo primero como siempre es importarla entre nuestras etiquetas head de nuestro html.

http://ajax.googleapis.com/ajax/libs/threejs/r67/three.min.js

Y creamos un div dentro de las etiquetas body del html con el id basicMoveWithThree donde se creará nuestro canvas. Además yo le especifiqué un ancho y un alto: style=”width: 600px; height: 400px;”.
Pegaré todo el código de este ejemplo y luego lo explicaré. Lo que haremos será crear un cubo con WebGL el cuál rotará sobre su mismo eje. Este es un ejemplo bastante sencillo, la idea es solo mostrar lo fácil que es utilizar esta librería.

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  basicMoveWithThree();
}
function basicMoveWithThree(){
  var scene = new THREE.Scene();
  var camera = new THREE.PerspectiveCamera(25, window.innerWidth/window.innerHeight, 0.1, 1000);
  camera.position.z = 5;

  var renderer = new THREE.WebGLRenderer();
  renderer.setSize(600, 400);
  renderer.setClearColor('#f7f7f7', 1);
  document.getElementById('basicMoveWithThree').appendChild(renderer.domElement);

  var geometry = new THREE.BoxGeometry(1,1,1);
  var material = new THREE.MeshLambertMaterial({color: 'blue'});
  var cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  var ambientLight = new THREE.AmbientLight(0x000044);
  scene.add(ambientLight);      

  var directionalLight = new THREE.DirectionalLight(0xffffff);
  directionalLight.position.set(1, 1, 1).normalize();
  scene.add(directionalLight);

  var angularSpeed = 0.2; 
  var lastTime = 0;
  var render = function(){
    var time = (new Date()).getTime();
    var timeDiff = time - lastTime;
    var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000;        
    cube.rotation.x += angleChange;
    cube.rotation.y += angleChange;
    lastTime = time;
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  };

  render();
}

En la primera parte del código cargo la función que contendrá mi script (esto es rutinario de javascript) y llamo a la función basicMoveWithThree declarada más abajo.

window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded(){
  basicMoveWithThree();
}

Ahora ya la parte entretenida. Lo primero que debo hacer es crear una Escena donde si visualizará mi WebGL y es a esta donde se cargarán todos los elementos que vaya creando más adelante, y a su vez crear una cámara que será la perspectiva con la que veré la escena. Hay 3 tipos de cámaras: Camera, OrthographicCamera y PerspectiveCamera. Para este ejemplo usarémos la última, que recibe 4 parámetros:
– El campo de visión vertital de abajo hacia arriba en grados.
– Relación del aspecto del ancho dividido por la altura.
– Plano cercano.
– Plano lejano.
Y luego determino la posición de la cámara en grados.

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(25, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 5;

El paso siguiente es determinar la forma en que se renderizará el Canvas o el WebGL (para este caso será con WebGL), el tamaño del canvas, el color de fondo, la profundidad, la sombra, la gama, etc.
Hay 4 formas de renderizar: CanvasRenderer, WebGLRenderer, WebGLRenderTarget y WebGLRenderTargetCube.
Pero para este caso usaremos WebGLRenderer, con un tamaño de 600 de ancho y 400 de alto, y usé el color de fondo de mi blog #f7f7f7 (por defecto es negro).

var renderer = new THREE.WebGLRenderer();
renderer.setSize(600, 400);
renderer.setClearColor('#f7f7f7', 1);

Junto a crear la forma de renderizar debo especificar donde lo aplicaré, en este caso será a un div con id ‘basicMoveWithThree’.

document.getElementById('basicMoveWithThree').appendChild(renderer.domElement);

Ahora crearemos el cubo. Debemos especificar el tipo de figura que usaremos, estas pueden ser figuras geométricas o curvas. Geométricas pueden ser: BoxGeometry, CircleGeometry, CubeGeometry, CylinderGeometry, ExtrudeGeometry, IcosahedronGeometry, LatheGeometry, OctahedronGeometry, ParametricGeometry, PlaneGeometry, PolyhedronGeometry, RingGeometry, ShapeGeometry, SphereGeometry, TetrahedronGeometry, TextGeometry, TorusGeometry, TorusKnotGeometry y TubeGeometry.
Y los tipos de curvas pueden ser: ArcCurve, ClosedSplineCurve3, CubicBezierCurve, CubicBezierCurve3, EllipseCurve, LineCurve, LineCurve3, QuadraticBezierCurve, QuadraticBezierCurve3, SplineCurve y SplineCurve3.
Y así ya podemos espeficiar el tipo de material (o superficie) del cuál estará compuesto nuestro cubo. Estos pueden ser: LineBasicMaterial, LineDashedMaterial, Material, MeshBasicMaterial, MeshDepthMaterial, MeshFaceMaterial, MeshLambertMaterial, MeshNormalMaterial, MeshPhongMaterial, PointCloudMaterial, RawShaderMaterial, ShaderMaterial, SpriteCanvasMaterial y SpriteMaterial.
Es importante elegir bien el tipo de material de nuestros objetos ya que esto influirá si aplicamos otros aspectos al escenario como la luz. Para este ejemplo usaré MeshLambertMaterial y le pasaré el color azul como parámetro, la clase MeshLambertMaterial puede recibir varios parámetros como intensidad de la luz o la refracción.
Luego creamos el elemento pasandole el elemento geométrico y el material del cuál estará compuesto, para luego agregarlo al escenario definido anteriormente con la función ‘add’.

var geometry = new THREE.BoxGeometry(1,1,1);
var material = new THREE.MeshLambertMaterial({color: 'blue'});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

También podemos trabajar con la luz y su dirección en el escenario. Los tipos de luz que podemos utilizar son: AmbientLight, AreaLight, DirectionalLight, HemisphereLight, Light, PointLight y SpotLight.
Para este ejemplo usaremos AmbientLight recibiendo como parámetro el color de la luz.

var ambientLight = new THREE.AmbientLight(0x000044);
scene.add(ambientLight);  

Y luego especificamos la dirección que tendrá la luz en la escena, también recibiendo el color de la luz.

var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);

El paso final es ejecutar la renderización, y especificar los movientos que queramos realizar sobre los objetos que agregamos a la escena. Podemos utilizar la diferencia del tiempo actual para controlar las revoluciones de rotación de los elementos (en mi caso del cubo). Y luego es importante ejecutar requestAnimationFrame(render); para que el Canvas o WebGL se aplique en forma de frames (se vuelva a llamar).

var angularSpeed = 0.2; 
var lastTime = 0;
var render = function () {
  var time = (new Date()).getTime();
  var timeDiff = time - lastTime;
  var angleChange = angularSpeed * timeDiff * 2 * Math.PI / 1000;        
  cube.rotation.x += angleChange;
  cube.rotation.y += angleChange;
  lastTime = time;
  renderer.render(scene, camera);
  requestAnimationFrame(render);
};
render();

Y así finalmente nuestro WebGL se vería así!

Recuerden que pueden consultar toda la información de la librería en la página oficial y si tienen alguna observación o mejora del ejemplo no duden en comentarla. Saludos!