h1

Android – Artigos Portal Android

18 de Maio de 2012

Há um tempo atrás publiquei 4 Tutoriais no Portal Android. Um portal para usuários e desenvolvedores Android.

Todos estão tendo bastante acessos, até mesmo tenho recebidos e-mail com perguntas sobre o assunto abordado em cada um deles.

Seguem os links:

h1

OO – Explorando o tipo Enum

28 de Dezembro de 2011

Enum é tipo que possui valores válidos representados com constantes, ou seja, valores fixos, que nunca se alteram.
Os tipos enums mais comuns são os que utilizam valores interiros, conhecido como int enum.

public abstract class TipoTela {
	public static final int GRANDE = 0;
	public static final int MEDIA = 1;
	public static final int PEQUENA = 2;
}

Ao utilizar essa abordagem, temos muitos problemas. Facilmente nossa API pode ser utilizada de forma errada. Se criarmos um étodo para definifir tipo de tela setTipoTela(int tipoTela): ele recebe como argumento um tipo int. Assim poderia utilizar esse método de forma errada: setTipoTela(GRANDE+PEQUENA).
Com isso o programa que estivesse utilizando a nossa API teria um comportamento inesperado.
A partir do Java 1.5, foi introduzido uma alternativa que elimina as deficiências do padrão Enum.

public enum TipoTela {
	GRANDE, MEDIA, PEQUENA
}

A idéia do enum é que ele exporta instâncias simples de uma classe através de atributos publicos final e static, ou seja, não podem ser alterados.
Você não irá conseguir criar uma instância de um enum, o compilador irá reclamar e você verá o erro Cannot instantiate, devido a classe ser gerada pelo compilador,
ser abstrata.
Se desejássemos utilizar esse padrão, com instâncias em versões anteriores ao Java 1.5, teríamos um pouco mais de trabalho.

public abstract class TipoPagamento {
	public static final TipoPagamento A_PRAZO;
	public static final TipoPagamento A_VISTA;
	static {
		A_PRAZO = new TipoPagamento(){
		};
		A_VISTA = new TipoPagamento(){
		};
	}

}

A partir do Java 1.5 esse trabalho já é feito pelo compilador. Com isso podemos explorar ainda mais esses recursos.
Vamos alterar a classe enum para que ela seja capaz de informar qual o tamanho em pixels de cada Tipo de Tela.
Já que a classe gerada pelo compilador é um classe abstrata, podemos então declarar um método abstrato, onde cada instância deverá implementá-lo.
Ao incluir o método pixels o compilador o Eclipse irá sugerar que para implementarmos o método.

public enum TipoTela {
	GRANDE {
		@Override
		public String pixels() {
			return "100 x 100";
		}
	},
	MEDIA {
		@Override
		public String pixels() {
			return "200 x 200";
		}
	},
	PEQUENA {
		@Override
		public String pixels() {
			return "300 x 300";
		}
	};

	public abstract String pixels();
}

Assim, se futuramente aparecer um novo tamanho de tela, ao declará-lo no enum, o compilador irá exigir que informe também seu tamnho,
através da implementação do método pixels.
O enum do Java 1.5, possui ainda alguns métodos úteis. Como values() que retorna um array com os valores do enum, e
valueOf(String), que recebe uma String como argumento e retorna o valor do enum correspondente.
O padrão enum deve ser utilizado sempre que o programador julgar necessário. Em qualquer linguagem de programação é possível tirar proveito desse padrão. No site do próprio Java existem o tutorial Enum Types que possui outros exemplos da utilização de enuns.

Fonte: Enum Types, Effective Java.

h1

Android – Problemas com mudança de orientação de Tela

19 de Novembro de 2011

Existem muitos artigos na Internet explicando como lidar com o “problema” de se mudar a orientação tela de uma aplicação Android, e não perder seu estado.

Em muitos casos usa-se “travar” a tela em um sentido só, através da tag android:screenOrientation, onde dentre outros, pose-se utilizar portrait (em pé) ou landscape (deitado).

<activity android:screenOrientation="portrait" android:name=".ApplicationActivity"></activity>

Nesse caso a Activity ficará com o layout sempre na vertical, não importa o que o usuário faça.
Mas esse não é o método mais adequado de se lidar com isso.
A mudança de orientação do dispositivo Android, é considerada um mudança de configuração, pois o OS sabe que deverá de adequar a essa mudança.
Então a atividade é finalizada e reiniciada por padrão.
Para alterar esse conportamento, deveremos informar ao OS que queremos lidar com essa mudanças, para isso utilizaremos o atributo configChanges, da Activity.

<activity android:configChanges="keyboard|orientation" android:name=".ApplicationActivity"></activity>

Quando declaramos esse atributo em uma Activity estaremos impedindo que a Activity seja reiniciada, em vez disso, a atividade permanece em execução e seu método onConfigurationChanged () é chamado.
Podemos interferir em várias alterações de configuração, como:

  • locale : o local padrão é alterado, quando o usuário seleciona um novo idioma;
  • keyboard : o tipo do teclado é alterado. Como por exemplo, quando o usuário abre o teclado externo do aparelho;
  • orientation : a orientação da tela é alterada. O usuário girou o aparelho;

Na página do Android Developers, podemos conhecer mais tipos de configurações que podem ser interceptadas.

Em nosso exemplo adicionamos keyboard e orientation, ou seja, quando o usuário utilizar um teclado externo ou musar a orientação da tela o método configChanges será chamado. Para isso, basta sobrescrevermos o método em nossa activity, que receberá uma instância da classe Configuration, e através dela, poderemos verificar quais são as configurações alterados e manipulá-las, ou simplemente ignorá-las.
Utilizando essa funcionalidade do Android, temos a oportunidade de lidar com diferentes tipos de alteração no ambiente do Android, em tempo de execução, podendo fazer nossa aplicação funcionar de forma correta em qualquer tipo de situação.

Fonte: Android Developers

h1

HTML 5 – Comunicação bidirecional utilizando WebSocket

27 de Julho de 2011

HTML5 é a mais nova versão da linguagem HTML. Nessa versão passou a possuir vários recursos avançados, alguns antes possíveis somente com  a utilização de outras linguagens.

Apesar de nova, a primeira espeficicação divulgada pelo W3C, consórcio de empresas de tecnologia que coordena os padrões da internet quanto a linguagem, data do início de 2008.

Logo oficial do HTML5

Claro que não são todos navegadores que oferecem suporte ao HTML5. Alguns suportam poucos recursos. No site HTML5Test pode-se testar se o navegador oferece suporte para HTML5. E no HTML5Readiness mostra um gráfico de quais recursos suportados por cada browser.

Vamos demonstrar um recurso interessante dessa nova geração do HTML, a api de WebSockets. O WebSocket é utilizado para comunicação bidirecional, full-duplex, ou seja, onde os dispositivos conectados podem se comunicar um com o outro em ambas direções (Envio/Recebimento).

Analisando o gráfico do HTMLReaddiness, podemos ver que o Chrome, do Google, é o navegador que possui suporte tudo do HTML 5. No dia 9 de Dezembro de 2009, foi divulgado que o Chrome passaria a disponibilizar suporte a WebSockets. Divulgado através do The Chromiun Blog, blog oficial do Chrome.

Para demonstrar o uso do WebSocket , iremos utilizar como navegador o Google Chrome. O Websocket utiliza o WebSocket Protocol para comunicação. E para implementação do servidor, utilizaremos uma biblioteca chamada WebSocket4J, que implementa esse protocolo, de forma bastante simples. Essa biblioteca possui poucas classes, que por traz, utiliza-se da classe ServerSocket do próprio Java, onde interpreta os dados recebidos, e assim não precisamos nos precupar em interpretar o protocolo de comunicação.

Começando com o servidor WebSocket. Criaremos um projeto Java, chamado de WebSocketServer, e em seguida a classe ServerWebSocket.java que irá possuir o método Main.

public class ServerWebSocket {
	public static final int PORTA = 8000;

	public static void main(String[] args) {
		WebServerSocket server = null;
		try {
			server = new WebServerSocket(PORTA);

			System.out.println("--- Servidor Iniciado - Porta " + PORTA + " ---");
			System.out.println("");
			WebSocket socket = server.accept();
			System.out.println("");

			while (true) {
				String message = socket.getMessage();
				System.out.printf("Cliente enviou-> %s\n", message);
				socket.sendMessage("OK;" + new Date());
			}
		} catch (IOException e) {
			System.err.printf("Ocorreu um erro no Servidor. Erro->%s\n", e.getMessage());
		}
	}
}

Essa clase é bem simples, tem um laço infinito onde fica esperando uma conexão ao Servidor de WebSocket. Lembrando que o servidor é Single-thread, ou seja, suporta somente uma conexão por vez. Essa limitação pode ser facilmente contronada alterando a classe. Ao receber uma conexão o servidor faz a leitura da mensagem, escreve ela no console e retorna um OK e data atual separado por “‘;”.

Agora iremos criar um projeto Web. Chamado de WebSocketClient, e a seguir criar um JSP, index.jsp. Que adicionaremos o seguinte código JavaScript, dentro da tag <head>.

	var socket;
	//Conecta ao Socket
	function connect() {
		if (!"WebSocket" in window) {
			$("status").innerHTML = "Browser não possui suporte a WebSockets.";
		} else {
			try {
				socket = new WebSocket("ws://"+$("host").value+":"+$("port").value);
				socket.onopen = function() {
					//Conectou, escreve a Conectou na DIV id status.
					$("status").innerHTML = "Conectado";
					$("host").disabled = true;
					$("port").disabled = true;
				}

				socket.onmessage = function(msg) {
					//Recebeu a mensagem
					var message = msg.data;
					if(message != ""){
						var split = message.split(";");
						if("OK"  == split[0]){
							$("receivedMesages").innerHTML = split[1];
						}
					}
				}

				socket.onclose = function(){
					//Fechou a conexão
				   $("status").innerHTML = "Desconectado";
			    }

			} catch (exception) {
				$("status").style. backgroundColor = "#F00";
				$("status").innerHTML = exception.message;
			}
		}
	}
	//Função utilizada para recuperar elementos pelo seu id
	function $(element){
	   return document.getElementById(element);
	}

	//Disconecta
	function disconnect() {
		socket.close();
		$("host").disabled = false;
		$("port").disabled = false;
	}

	//Envia mensagem
	function sendMessage(message) {
		socket.send($("message").value);
		$("message").value = "";
	}

Nesse trecho de código utilizamos o objeto WebSocket, do JavaScript. Primeiramente verificamos de o nevegador oferece suporte a WebSocket e em seguida montamos a URL de Acesso ao Socket. A figura abaixo ilustra o significado dessa URL.

URL WebSocket

O Objeto WebSocket possui 4 eventos:

  • onopen: ocorre quando um WebSocket é aberto;
  • onmessage: ocorre quando uma mensagem é recebida;
  • onclose: ocorre quando o WebSocket fecha sua conexão;
  • onerror: ocorre quando acontece um erro na comunicação;

Agora podemos executar o projeto WebSocketServer.

Console Eclipse - Aguardando conexão de Cliente

Neste ponto nosso servidor está esperando a conexão de algum cliente. Agora vamos iniciar projeto WebSocketClient.

Cliente WebSocket

Essa tela foi desenvolvida para dispara as funcões JavaScript. Ao clicar em conectar o Status do cliente irá mudar para Conectado, e assim poderemos escrever a mensagem para envioa ao servidor. E ao clicar em Enviar, poderemos visualizar a mengam no console do Eclipse, que está executando nosso servidor.

O codigo fonte dos projetos estão disponívies para download nesse link.

O HTML5, talvez ainda não seja uma tecnologia muito utilizada,  por enquanto, mas com esse simples exemplo podemos demonstrar um pouco do seu poder.

Vale destacar que grandes empresas já manifestaram seu interesse pela tecologia. Steve Jobs publicou uma carta, intitulada Toughts on Flash explicando o porque de seus aparalhos não oferecerem suporte ao Adobe Flash, que em um trecho diz “Nós realmente acreditamos que todos os padrões pertencentes à web deveriam ser abertos. Em vez de usar Flash, a Apple adotou o HTML5, CSS e JavaScript – todos padrões abertos.”. O Youtube  também já possui sua versão em HTML5. Para ficar em apenas dois exemplos.

Fonte: Nettuts+ – Start Using HTML5 WebSockets Today, WebSocket4J

Download do exemplo

Outros exemplos: HTML5 Demos and Examples.

** Atualização

Fernando Farias postou um comentário no tópico informando que estava ocorrendo um erro no Projeto de exemplo do tópico. O erro em questão era um Handshake failed, que ocorria em tempo de execução. Isso logo após o cliente solicitar a conexão com o WebSocketServer.

A causa disso é um problema com o Hanshakedo webSocket. Handshake é uma espécie de autorização que o cliente, ao solicitar uma conexão com Servidor WebSocket, envia ao Servidor e por sua vez valida essa autorização. Também é utilizado em várias protocolos da web como: FTP, TCP, HTTP, etc.

O que acontecia aqui é que o Handshake enviado ao servidor não era válido. Pelo menos do ponto de visto do WebSocket4J. Cheguei até a criar um tópico no site da Launchpad descrevendo o erro, mas pelo menos até hoje (19/03/2012) não tinha sido respondido.

Muito provavelmente o projeto parou e/ou não acompanhou a evolução da espeficicação do WebSocket. Ja que o Google Chrome, browser utilizado, teve várias atualizações.

Por isso agora na segunda versão passei a utilizar TooTallNate WebSocket, e a versão 17.0.963.79 m (mais atual, até o momento) do Chrome e funcionou perfeitamente.

Basta executar a classe ServerWebSocket2. Ela estende a classe WebSocketServer, assim basta implementar os métodos onOpen, onClose, onError, onMessage (esse possui duas versões: uma que recebe String e outra um array de byte[]), semelhante aos métodos implementados no Cliente.

public class ServerWebSocket2 extends WebSocketServer {
(...)
@Override
	public void onOpen(WebSocket conn, ClientHandshake handshake) {
		System.out.println("");
	}

	@Override
	public void onClose(WebSocket conn, int code, String reason, boolean remote) {
		System.out.println("");
	}

	@Override
	public void onError(WebSocket conn, Exception ex) {
		System.err.printf("Ocorreu um erro no Servidor. Erro->%s\n",
				ex.getMessage());
	}

	@Override
	public void onMessage(WebSocket conn, String message) {
		try {
			System.out.printf("Cliente enviou-> %s\n", message);
			conn.send("OK;" + new Date());
		} catch (InterruptedException e) {
			onError(conn, e);
		}
	}

	@Override
	public void onMessage(WebSocket conn, byte[] blob) {
		try {
			conn.send(blob);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
(...)

Download da versão 2 do Projeto.

h1

OO – Perigos da Herança

25 de Junho de 2011

Ao iniciarmos no Mundo OO, e deparamos com a possiblidade de utilizarmos herança como recurso. É normal começarmos a utilizá-la indiscriminadamente, por várias motivos. Pensamos: “Por que vou perder tempo escrevendo o método se já fizeram isso para mim ?”.

Por exemplo: existem desenvolvedores, que implementam clsses herdando algum tipo de Collection. Para simplesmente ter um comportamente de lista, com métodos para adicionar, recuperar, remover objetos.

Isso é conhecido como um Anti-pattern, chamado BaseBean.

No póprio Java existem algunas exemplos desses “erros”. A classe Properties, é um desses exemplos. Olhando sua documentação notamos que ela herda de Hashtable, simplesmente para termos a possibilidade de mapearmos propriedades através do metodo setProperty(String key, String value). Mas ao herdar de HashTable também teremos acesso ao método put(Object, Object). Então, poderíamos concluir que Properties aceitaria um objeto como chave, e o resultado não seria o esperado. Ou então utilizar o o método putAll(Map t), assim adicionarmos outra lista de properties de uma vez só.

Como isso poderia ser resolvido em novas versões, sem perder a compatibilidade? A saída encontrada foi adicionar ao Javadoc uma advertência:

Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a “compromised” Properties object that contains a non-String key or value, the call will fail.

Ou seja no Javadoc, diz que o uso dos métodos put e putAll, é fortemente desaconselhável. Isso foi necessário devido Properties herdar de HasTable. Sendo que o métdo a ser utilizado é setProperty(String key, String value), que não permite adicionar outro tipo de Objeto a não ser uma String.

No Effective Java Joshua Bloch diz, com todas as palavras “prefira Composição à Herança” e ainda, “herança quebra o encapsulamento”. Uma das justificativas é de que as classes devem evoluir juntas e sem interferir uma na outras. Utilizando herança as subclasses necessitam conhecer detalhes da implementação da classe Pai. Não é dificil imaginar que ao alterar uma superclasse, suas subclasses fiquem invalidadas.

Vamos serguir o exemplo da classe Properties, como poderia ser implementado corretamente eliminando a herança ?

Nossa classe Properties,irá  possuir um atributo props, que é um Hashtable. Assim teremos uma Composição.

Properties.java

public class Properties {
private Hashtable props = new Hashtable();

public void setProperty(String key, String value) {
this.props.put(key, value);
}

public String getProperty(String key) {
return this.getProperty(key);
}

// outros métodos
}

O método setProperty da classe Properties, é tipado com Strings, não aceitando outro tipo de argumento. Por sua vez esse método delega a chamada para o método put do Hashtable.
Com isso limitados o uso do Hashtable, e podemos expor somente os métodos necessários.

No Blog da Caelum, Paulo Silveira, também abordou o assunto no post Como não aprender orientação a objetos: Herança e deu um exemplo bem prático:

Se um gato possui raça e patas, e um cachorro possui raça, patas e tipoDoPelo, logo Cachorro extends Gato?

Herança é um recurso que deve ser usado moderadamente. É difícil julgar se uma classe precisará ser projetada para Herança ou não. Isso vai de cada desenvolvedor. Usar herança em classes, à nivel de pacote (defatulf, protected) onde você tem total controle sobre ela, é considerado uma boa prática, já que, se for necessário alguma alteração drástica não irá afetar a “API exportada”.

Fonte: Effective Java, AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis.

h1

Android – Ativar suporte para grandes telas Tablet

22 de Junho de 2011

Após algum tempo de desenvolvimento para Android, fiquei entusiasmado com a possibilidade de ter a aplicação rodando em um Tablet.

A aplicação estava funcionando utilizando a versão 3 do Android SDK (ou 1.5). Mas ao compilar e testar a aplicacão, ela aparece pequena na tela.

Isso acontece porque a aplicação foi feita para a plataforma 3, e por padrão ela vem somente com suporte para telas “normais” ativado.

A partir da versão 4, outros tipos de telas são suportadas por padrão. Mas você deve especificar no AndroidManifes.xml qual é o API mínima suportada:

<uses-sdk android:minSdkVersion="4" />

ou

<uses-sdk android:targetSdkVersion="4"/>

e também assim

<uses-sdk android:targetSdkVersion="4" android:minSdkVersion="4"/>

Não esqueça de alterar a versão de compilação do seu SDK antes de alterar o minsdkVersion. Se não terá um erro no AndroidManifest.xml, e o programa não irá compilar.

Então vamos ao o que interessa. Você deve incluir no seu AndroidManifest.xml, como tag filha de <manifest> o seguinte:

<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" />

Aqui eu ativei todos os suportes.

  • android:resizeable: indica se a aplicação é redimensionável para diferentes tamanhos de tela.
  • android:smallScreens: indica se a aplicação possui suporte telas pequenas (HVGA, tradicional).
  • android:normalScreens: indica se a aplicação possui suporte telas “normais” .
  • android:largeScreens: indica se a aplicação possui suporte telas grandes.
  • android:xlargeScreens: indica se a aplicação possui suporte telas gigantes. O Tablet é considerado um dispositivo de tela gigante.
  • android:anyDensity: indica se a aplicação inclui recursos para qualquer densidade de tela.

Lembrando que ao definir minSdkVersion ou targetSdkVersion para a API 4, os valores dos atributos são true por padrão.

Fonte: Android Developer