Titanium, criando uma intent no OS Android

Pessoal, nesse tutorial vou mostrar como é simples criar uma “intent” do Android pelo Titanium e iniciar a “activity” através da “intent“.

Vamos supor que eu preciso acessar o recurso de geolocalização do device do usuário. Para acessar esse recurso pelo Titanium é bem simples, basta verificar se o serviço de geolocalização esta ativa no device acessando a propriedade: Ti.Geolocation.locationServicesEnabled. Para saber mais acesse aqui.
Ao verificar a propriedade, se ela estiver desativada retornando “false“, você não vai conseguir capturar a latitude e a longitude referente a posição do device. Como o serviço esta desativado, você pode informar o usuário através de um “alert“, para que ele ative o serviço de geolocalização e volte ao app. Mas lidar com o usuário é complicado, pois alguns não vão nem saber como habilitar esse serviço e você como desenvolvedor tem que tentar facilitar esse trabalho ao máximo no aplicativo que você estiver desenvolvendo.

Hora de botar a mão na massa! Criei um projeto clássico no Titanium apenas com foco no Android. No arquivo “app.js”, vamos criar uma window e um button, no button vou adicionar um evento de “click” para verificar se a geolocalização esta ativa. Se estiver ativa vou mostar a latitude e a longitude onde o device se encontra, senão, por agora vou exibir um alerta informando o usuário que a geolocalização está desativada.

//criando uma função anônima
( function(){
    var win = Ti.UI.createWindow({
		backgroundColor:'#fff'
	});

	var buttonShowLocation = Ti.UI.createButton({
		title:'show location',
		width:140,
		height:80
	});
	win.add( buttonShowLocation );

        buttonShowLocation.addEventListener( 'click', clickButtonShowLocation );
	function clickButtonShowLocation (e)
	{
		// verificando se geolocalização está ativa
		if( Ti.Geolocation.locationServicesEnabled )
		{
                        //define a precisão requerida da geolocalização
			Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;

			// caso a geolocalização esteja ativa tente capturar a posição do device
			// o método getCurrentPosition, recebe como parâmetro uma função de callback
			// Caso "e.success" seja verdadeiro é mostrado um alerta com a latitude e longitude
			// que o device se encontra. Senão, é exibido um alerta para o usuário sobre o erro ocorrido
			Ti.Geolocation.getCurrentPosition( function( e ){
				if ( e.success )
				{
					alert( 'latitude: ' + e.coords.latitude + ' longitude: ' + e.coords.longitude );
				}
				else
				{
					alert( 'Error get current position:' + e.error );
				}
			});
		}
		else
		{
			alert( 'GPS disabled.' );
		}

	}

} )();

Vou executar esse exemplo direto no meu nexus e printar aqui os resultados com a geolocalização ativada e desativada.

GPS desativado

GPS desativado

GPS ativado

GPS ativado

Agora, ao invés de mostar um “alert” ao usuário que o serviço de geolocalização está desativado, vamos abrir a tela específica do Android para que ele consiga habilitar o serviço de GPS.

Basta comentar a linha 40 e adicionar o seguinte trecho de código.

var intent = Ti.Android.createIntent({
	action:"android.settings.LOCATION_SOURCE_SETTINGS"
});
Ti.Android.currentActivity.startActivity( intent );

Ao testar o exemplo e ele estiver com o gps desativado, e você clicar no botão, a tela que deve aparecer deve ser semelhante ao print abaixo.
IMG_20140413_224834

Segue o código completo.


( function(){

	var win = Ti.UI.createWindow({
		backgroundColor:'#fff'
	});

	var buttonShowLocation = Ti.UI.createButton({
		title:'show location',
		width:140,
		height:80
	});
	win.add( buttonShowLocation );

	buttonShowLocation.addEventListener( 'click', clickButtonShowLocation );

	function clickButtonShowLocation (e)
	{
		// verificando se geolocalização está ativa
		if( Ti.Geolocation.locationServicesEnabled )
		{
                        //define a precisão requerida da geolocalização
			Ti.Geolocation.accuracy = Ti.Geolocation.ACCURACY_BEST;
			// caso a geolocalização esteja ativa tenta capturar a posição do device
			// o método getCurrentPosition, recebe como parâmetro uma função de callback
			// Caso "e.success" seja verdadeiro é mostrado um alerta com a latitude e longitude
			// que o device se encontra. Senão, é exibido um alerta o usuário sobre o erro ocorrido
			Ti.Geolocation.getCurrentPosition( function( e ){
				if ( e.success )
				{
					alert( 'latitude: ' + e.coords.latitude + ' longitude: ' + e.coords.longitude );
				}
				else
				{
					alert( 'Error get current position:' + e.error );
				}
			});
		}
		else
		{
			//alert( 'GPS disabled.' );

			var intent = Ti.Android.createIntent({
				action:"android.settings.LOCATION_SOURCE_SETTINGS"
			});
			Ti.Android.currentActivity.startActivity( intent );

		}

	}

	//open window
	win.open();

} )();

Você pode abrir qualquer janela do OS Android, basta definir a “action” certa. Para abrir as definições de rede wifi, altere a “action” do nosso exemplo para a linha abaixo.

action:"android.settings.WIFI_SETTINGS"

Veja o vídeo de exemplo que demonstra o código desse exemplo em execução.

Qualquer dúvida ou sugestão, poste um comentário.

EaselJS parte 1

Nesse tutorial vamos criar uma interatividade básica com JavaScript sobre a tag canvas do HTML5 usando o framework EaselJS. Para quem não conhece esse framework, ele é inspirando no ActionScript3 a linguagem de programação mais atual do plugin FlashPlayer.

O EaselJS faz parte de um conjunto de frameworks escrito em JavaScript do pacote CreateJS, faz parte também dessa família os frameworks TweenJS, PreloadJS e SoundJS. Os principais patrocinadores dessas ferramentas são: Adobe, Microsoft, AOL e GSkinner. Ano passado (2012) a GSkinner reescreveu uma série de games criado pela ATARI no passado, usando CreateJS, você pode conferir aqui.

Então chega de blablabla e vamos ao que interessa.

Primeiro, aconselho que vocês naveguem no site da CreateJS, vejam os trabalhos já publicados, teste os vários exemplos que tem disponíveis, aproveite também e espie a documentação, pois ela vai atender suas necessidades. Logo em seguida, baixe todo o pacote da CreateJS ou se preferir, apenas o EaselJS.

Após baixar o(s) pacote(s), crie um simples arquivo html, como abaixo, e salve com um nome de sua preferência.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title> TEST with JavaScript </title>
	</head>

	<body onload="Main();">
		<h3> CLICK TO DRAW </h3>
    	<canvas id="canvas" width="550" height="550">
        </canvas>

        <!-- imports js -->
        <script src="js/easeljs-0.6.0.min.js"></script>
        <script src="js/Main.js"></script>
	</body>
</html>

Nessa estrutura básica de html, temos um elemento canvas onde acontecerão nossas interações, arquivos javascripts onde na linha 11 e a referência para o framework EaselJs baixado, a linha 12 está configurada para o arquivo “Main.js” que criaremos logo em seguida.

Observe que a tag body tem a propriedade “onload” que recebe como parâmetro uma função JavaScript.

Crie um arquivo Javascript como abaixo, salve-o com o nome “Main.js”. Se salvar com um nome diferente, não se esqueça de alterar esse nome no html.


var canvas;
var stage;
var containerBalls;
var containerLines;
var shapeLines;
var graphicsLines;

 function Main()
{
	// canvas
	canvas = document.getElementById('canvas');
	stage = new createjs.Stage( canvas );
 	// enabled interaction
	stage.mouseEventsEnabled = true;

 	// container
	containerBall = new createjs.Container();
	containerLines = new createjs.Container();

 	//lines
	shapeLines = new createjs.Shape();
 	graphicsLines = new createjs.Graphics();

 	//background black
	var g = new createjs.Graphics();
	g.beginFill( "#000000");
	g.drawRect(0,0, canvas.width, canvas.height);
 	var s = new createjs.Shape(g);
	s.x = 0;
	s.y = 0;

	stage.addChild(s);

 	//add elements
	containerLines.addChild(shapeLines);
	stage.addChild(containerLines);
	stage.addChild(containerBall);

 	stage.addEventListener( 'click', onClickStage );
}

function onClickStage( e )
{
	var ball = createBall(8);
	ball.x = stage.mouseX;
	ball.y = stage.mouseY;
	containerBall.addChild(ball);

	stage.update();
	debug( "stage-click => x "+ ball.x + " y => " + ball.y );
}

function createBall( raio )
{
	var g = new createjs.Graphics();
	g.beginFill('red');
	g.drawCircle(0, 0, raio);
	var s = new createjs.Shape(g);

	return s;
}

function debug( s )
{
	console.log( s );
}

Segue abaixo fluxo do algoritmo.

Figura 1.

Figura 1.

Observe: sempre que adicionarmos uma bola ao palco é necessário fazer uma atualização do mesmo. Caso você se esqueça de fazer essa atualização, não conseguirá visualizar as alterações ocorridas.

Até o momento, nosso experimento está adicionando uma bola vermelha ao clicar no palco. Que deve estar parecido com esse abaixo.

Figura 2.

Figura 2.

Até o momento estamos conseguindo visualizar apenas as bolas, mas calma, vamos implementar agora o desenho das linhas. Basta alterar a função “onClickStage”, como abaixo, e todas as bolas estarão conectadas umas com as outras.


function onClickStage( e )
{
	var ball = createBall(8);
	ball.x = stage.mouseX;
	ball.y = stage.mouseY;
	containerBall.addChild(ball);

	debug( "stage-click => x "+ ball.x + " y => " + ball.y );

	var len = containerBall.getNumChildren()-1;
	for (var i = 0; i < len; i++)
	{
		//debug("filhos: ", i);
		var l = containerBall.getNumChildren();
		for (var j = i+1; j < l ; j++)
		{
			//captura bola i
			var dObj1 = containerBall.getChildAt(i);
			//captura bola j
			var dObj2 = containerBall.getChildAt(j);
			//inicia define cor da linha em hexa
			graphicsLines.beginStroke("#ffffff");
			//início da linha, como se movesse a caneta para cima da bola i
			graphicsLines.moveTo(dObj1.x, dObj1.y);
			//como se riscasse um traço da bola i em direção a bola j
			graphicsLines.lineTo(dObj2.x, dObj2.y);
			//finaliza linha
			graphicsLines.endStroke();

			//debug("container I: ", dObj1, " container J: ", dObj2);
		}

	}

	//apenas atualiza a propriedade graphics.
	//containerLines.removeChild(shapeLines);
	//shapeLines = new createjs.Shape(graphicsLines);
	shapeLines.graphics = graphicsLines;
	// containerLines.addChild(shapeLines);

	stage.update();
}

O segredo está nessa estrutura de repetição. Então vou detalhar todo o processo.

Cada bola deve estar conectada uma com a outra e cada bola estará adicionada no container “containerBall“. Com o método “getNumChildren() eu consigo saber quantos filhos tem dentro do container. Agora faremos uma simulação de três bolas para ficar mais fácil o entendimento.

Vamos supor que tenho 3 bolas dentro do container, essas bolas devem estar conectadas entre si. A bola 1 deve estar conectada com a bola 2 e 3. A bola 2 tem que se conectar apenas com a bola 3, já que temos uma conexão da bola 1 com a bola 2. Então, não é nessário repetir a conexão da bola 2 com a 1, concorda? Já a bola 3 não precisa ter nenhuma conexão, pois as bolas 1 e 2 já fazem conexão com ela.

Veja o um exemplo com 4 bolas.

Figura 3

Figura 3

O código está bem comentado e simples, mas caso você tenha alguma dúvida, não deixe de perguntar.

Você pode baixar o código fonte aqui.

Você pode visualizar o resultado final aqui.

Obrigado.