quinta-feira, março 26, 2009

Tamanho das janelas no MIDP1 e MIDP2

Na empresa que trabalho nós fizemos um software que deveria rodar em celulares. Havia duas restrições:

- uma delas é que o código deveria rodar em celulares com MIDP1 e MIDP2. A outra é que o código deveria ser único para ambas as especificações.

No desenvolvimento do programa nós usamos Canvas para criar as nossas próprias telas, pois isso nos dá mais flexibilidade quanto ao layout do aplicativo.

Para que os componentes sempre sejam desenhados proporcionalmente ao tamanho da tela do celular (que varia muito de modelo para modelo), nós usamos duas funções da API para obtermos a largura e a altura da tela: getWidth() e GetHeight().

Ok. Testamos em vários aparelhos e nos aparelhos MIDP1 o aplicativo gerava a exceção

No such method getWidth() (e pode gerar, dependendo de quem é chamado primeiro, o erro No such method getHeight()) e morria: Os métodos getWidth() e getHeight() não existiam.

Como não? Estes métodos estão nas duas especificações. Fui examinar as APIs e descobri que, apesar de existirem, elas ficavam em hierarquias diferentes, dependendo da especificação.
java.lang.Object
extended by javax.microedition.lcdui.Displayable
extended by javax.microedition.lcdui.Canvas
Figura 1 - Hierarquia das classes Displayable e Canvas

No MIDP1, os métodos estão na classe Canvas e no MIDP2 estão em em Displayable.

Quando compilas usando as bibliotecas do MIDP2, o compilador automaticamente chama os métodos getWidth() e getHeight() de Displayable. Daí, ao rodarmos o aplicativo no celular com MIDP1, a JVM procura pelos métodos em Canvas, não os encontra e o aplicativo morre.

Agora a dúvida: como resolver isso?

Nossa classe base de desenho de telas (herda de Canvas) chama-se FormBase. Nela nós criamos os métodos


public int getWidth() {
return super.getWidth();
}

public int getHeight() {
return super.getWidth();
}
Isso obriga o compilador a chamar o método Canvas.getWidth() e Canvas.getHeight().

E como isto resolve o problema?

Quando estiver executando o aplicativo em um celular MIDP1, Canvas possui os métodos acima. Quando o aplicativo estiver executando em um celular MIDP2, Canvas não os possuirá. Aí serão chamados os métodos públicos herdados de Displayable.

Voilà! Resolvido o nosso problema de compatibilidade.

A hierarquia de classes do nosso programa é o mostrada na figura 2.

Eu recomendo que tu leias pelo menos um destes dois livros:
Espero que ajude.

Figura 2 - Hierarquia do programa para rodar em MIDP1 e MIDP2

Um comentário:

Anônimo disse...

Genial! Muito bem pensado. Imagino que essa ideia possa ser aplicada inclusive em soluções C++, caso alguma interface desse tipo "evolua" com mais métodos.

[]s