You are on page 1of 6

JSR 211

A API J2ME para gerenciamento de conteúdo


HERVAL FREIRE
Lançada para revisão pública no mês de Julho, a JSR 211 - Content Handler API (também
chamada de CHAPI) destaca-se como uma das mais inovadoras e úteis APIs do universo J2ME. Em
linhas gerais, a API define um modelo de comunicação entre aplicações (tanto nativas quanto
Java/J2ME), de forma a permitir que MIDlets sejam designados como manipuladores de conteúdo
para um ou mais tipos de arquivos específicos. Se uma das maiores barreiras para o
desenvolvimento de aplicativos J2ME realmente úteis e integrados com a plataforma de hardware
era a dificuldade de intercomunicação entre aplicações, é este justamente o ponto atacado pela API.
Content Handlers
Toda a idéia por trás da JSR 211 baseia-se no conceito de Content Handlers. De acordo com este
modelo de execução, um MIDlet hipotético poderia registrar-se junto ao Sistema Operacional do
dispositivo para manipular arquivos que pertençam ao tipo MIME image/png, e determinar que é
responsável apenas pela visualização deste tipo de arquivo, tornando-se assim o Content Handler
registrado para visualização do referido Content Type. A partir deste momento, quaisquer
requisições que solicitassem a visualização de um arquivo do tipo image/png (sejam elas solicitadas
por outros aplicativos Java ou por aplicações nativas) ativariam o MIDlet registrado
automaticamente.
O conceito de registro de associação de arquivos a aplicações através de um registro é comumente
encontrado em diversos sistemas operacionais (inclusive de dispositivos móveis, como os telefones
celulares), e possibilita a livre associação de aplicações responsáveis pela manipulação e tipos de
arquivos específicos.
O mecanismo de invocação de content handlers baseia-se na utilização de URIs, de forma que o
MIDlet que realiza uma invocação não indica explicitamente qual aplicação está chamando – ele
apenas informa (1) o conteúdo que deseja manipular (através de uma URI, de modo similar ao
método platformRequest da classe MIDlet), (2) a operação que será realizada (edição,
alteração, salvamento, etc) e (3) quaisquer outros parâmetros cabíveis à execução.

Nota:
Em casos onde exista mais de um Content Handler para um tipo específico de arquivo (por
exemplo, havendo dois players de MP3 instalados em um dispositivo), a aplicação invocadora
pode indicar a aplicação que deseja executar através de um ID.

A especificação deixa claro que podem existir dois modos de execução do processo de
manipulação de conteúdo (content handling), dependendo das capacidades de processamento em
paralelo do dispositivo. Em aparelhos onde a execução simultânea de mais de um aplicativo é
possível, a API determina que o manipulador do conteúdo pode ser executado em paralelo e
devolver uma resposta à aplicação invocadora sem que esta tenha que ser finalizada. Em casos onde
somente uma aplicação pode ser executada por vez, a aplicação invocadora deve ser fechada antes
que o conteúdo possa ser devidamente manipulado.
O pacote javax.microedition.content
A CHAPI é uma API pequena: composta de apenas sete classes (incluindo uma classe de exceção
genérica), ela resume todos os mecanismos necessários para invocar um content handler e obter
uma resposta, registrar e desregistrar um content handler, pesquisar por content handlers instalados
e responder a invocações. A Tabela 1 resume estas classes.
Classe Descrição
Registry Responsável por invocar, registrar, desregistrar e iniciar
invocações de content handlers.
ContentHandler Provê os detalhes sobre um handler registrado no aparelho: Id,
autorizações de acesso, nome da aplicação, content types etc.
Invocation Contém os parâmetros passados e retornados para o
ContentHandler durante uma requisição.
ContentListener Listener que notifica a aplicação sobre requisições ou respostas de
requisições pendentes.
ContentHandlerServer Permite o processamento de requisições e sua finalização.
ActionNameMap Mapeia ações para nomes (descritivos).
ContentHandlerException Classe genérica de erros em uma manipulação de conteúdo.
Tabela 1. Classes da CHAPI

Invocando um Content Handler


A invocação de um Content Handler é uma atividade bastante simples, exemplificada na listagem
1. No trecho de código mostrado, a aplicação requisita (através de um objeto Invocation) que a
aplicação manipuladora para arquivos do tipo vcard seja ativada, e fornece a URI do objeto que
deseja que seja manipulado. Além disso, a invocação especifica ainda que a operação de abertura de
arquivo (ContentHandler.ACTION_OPEN), e fornece um parâmetro (argumento), que
pode ser usando na aplicação manipuladora para executar alguma lógica de negócio específica.

Atenção
O único modelo de conexão implementado obrigatoriamente no MIDP 2.0 é o HttpConnection. No
entanto, dispositivos que disponham de outros modelos de conectividade podem fornecer conteúdo
para content handlers utilizando quaisquer protocolos disponíveis. Um dispositivo que disponha de
sistema de arquivos, por exemplo, pode fornecer a URI de um arquivo em seu filesystem
(“file:///drive:/meuarquivo.gif”, por exemplo) no ato de criação do objeto Invocation.

A invocação de um manipulador de conteúdo é feita através do método Registry.invoke(). O


método retorna um valor boolean, que indica se a aplicação atual deve ser fechada antes do
manipulador ser ativado ou não.
O nosso exemplo inclui ainda o tratamento de uma resposta: através da chamada ao método
Registry.getResponse(), é possível recuperar um objeto Invocation contendo o
resultado do processamento por parte do Content Handler. Todos os atributos do objeto
Invocation (action, args, url, status, etc.) podem ser livremente acessados, tornando o
tratamento da resposta igualmente simples.
Construindo um Content Handler
O tratamento de uma requisição também é uma atividade fácil. A listagem 2 mostra uma aplicação
capaz de tratar nossa requisição do exemplo anterior e retornar um resultado uma vez que o usuário
confirme que a visualização acabou. Durante a inicialização da classe, a chamada ao método
Registry.forClass() retorna a instância de um objeto ContentHandler associada a nosso
MIDlet (esta instância é relacionada ao MIDlet no momento em que este é registrado como um
Content Handler. Falaremos melhor a respeito desta atividade a seguir). Através desta instância,
podemos acessar as requisições realizadas para o manipulador de conteúdo e processá-las de acordo
com a necessidade. O MIDlet é notificado de requisições pendentes através do método
invocationNotify() da classe ContentListener (seguindo um modelo de resposta a
requisições similar ao utilizado em aplicações que utilizam a Wireless Messaging API para receber
mensagens assincronamente, por exemplo), e pode retornar os dados da invocação através de uma
chamada ao método getRequest().
Uma vez que o objeto Invocation seja acessado, pode-se recuperar o conteúdo referenciado
utilizando o Generic Connection Framework, na forma de um streaming de dados. O objeto
também garante acesso a todos os atributos que foram configurados no momento da requisição:
action, arguments, status, etc.
Uma vez que o usuário decide por encerrar a manipulação do conteúdo (no exemplo, quando o
usuário pressionar a tecla ‘OK’, e desta forma ativar o método commandAction()), o método
ContentHandler.finish() é invocado e a aplicação invocadora é automaticamente notificada
(se estiver ativa). O funcionamento do finish() é similar ao do invoke(): dependendo da
implementação, o content handler tem que ser finalizado para que a aplicação invocadora retorne ao
primeiro plano ou não.
Handlers Registrados
Os diversos métodos da classe Registry permitem descobrir quais são os manipuladores
responsáveis pelo tratamento de content types diversos. Dentre os métodos, é possível saber quais
os manipuladores existentes para uma dada ação (delete, open, rename, etc), para um dado
sufixo/tipo de arquivo (.png, .vcard, .mid, etc), para um MIME type específico (text/html, image/gif,
etc) e finalmente, localizar os content handlers identificados por um Id específico.
Registrando um Content Handler
Para que nosso MIDlet VCardViewer seja reconhecido como um Content Handler, o mesmo deve
ser registrado junto à VM. A modalidade mais comum de registro é o registro estático: nela, o
MIDlet declara seus atributos de content handling em seu descritor (.jad), e é automaticamente
registrado durante sua instalação. A listagem 3 mostra o descritor de nosso aplicativo de exemplo.

Atenção
Por tratar-se de um recurso facilmente mal utilizado, a declaração de MIDlets como Content Handler
requer que os mesmos sejam assinados ou autorizados pelo usuário. MIDlets projetados para funcionar
como Content Handlers devem fazer parte do domínio de segurança
javax.microedition.content.ContentHandler.

Dos atributos do descritor, apenas os atributos iniciados por MicroEdition-Handler merecem uma
explicação detalhada:
MicroEdition-Handler-<número>: estes atributos descrevem os manipuladores incluídos no Midlet
Suite. Os argumentos do parâmetro são o nome da classe responsável pela manipulação de conteúdo
(no nosso caso VcardViewer e VCardEditor), os MIME types tratados, as operação suportadas pelo
manipulador (no nosso caso, apenas open e edit) e a extensão (sufixos) dos arquivos tratados pelo
content handler.
MicroEdition-Handler-<número>-<locale>: armazena os nomes descritivos de ações. Estes nomes
podem ser recuperados utilizando-se a classe ActionNameMap, para exibição na tela, por
exemplo, e podem ser internacionalizados.
MicroEdition-Handler-ID: o identificador único deste pacote de content handlers no aparelho. Este
identificador não precisa ser fornecido no descritor (a implementação pode gerar um ID
automaticamente).

Registrando um Content Handler Dinamicamente


Apesar de menos comum, o registro de um manipulador de conteúdo também pode ser feito
dinamicamente, através de código. O trecho da listagem 4 registra um content handler para arquivos
do tipo image/png e define que o MIDlet será responsável apenas pela ação de abertura
(ContentHandler.ACTION_OPEN) para este tipo de arquivo. O registro fica por cont da
chamada ao método Registry.register(). De forma complementar, o método
Registry.unregister() permite desregistrar uma aplicação previamente registrada a qualquer
momento. O desregistro de um MIDlet como content handler também acontece automaticamente
quando o mesmo é removido do dispositivo.
Content Handlers Padrão
O JSR 211 determina que alguns MIME types possuem pelo menos um manipulador padrão na
implementação do dispositivo, mesmo que nenhum outro seja especificado. O MIME type
application/jar-archive deve obrigatoriamente referenciar a aplicação responsável por instalar
novos MIDlets – o mesmo se aplica aos tipos application/java-archive e
text/vnd.sun.j2me.appdescriptor. Conteúdos do tipo text/html também contarão geralmente com um
manipulador padrão na maioria dos casos, o browser WAP do dispositivo.
Conclusões
A CHAPI é um pacote opcional, e sua especificação estará disponível em versão final em meados
de Agosto. Devido a sua extrema utilidade e ao novo grau de interação com a arquitetura dos
dispositivos alcançados com a sua utilização, é provável que diversos fabricantes incluam
implementações desta JSR em seus aparelhos em pouco tempo.

Listagem 1. Invocando um Content Handler


// Invoke based on a URL
try {
String url = “http://host/jones.vcard”;
Invocation invoc = new Invocation(url);
invoc.setAction(ContentHandler.ACTION_OPEN);
invoc.setArgs(new String[] {"debug"});
if (Registry.invoke(invoc, this)) {
// App must exit before invoked application can run
notifyDestroyed(); // inform the application manager
} else {
// Application does not need to exit

Invocation ret = Registry.getResponse(this, 1000);


// handle the returned invocation result here!
Alert alert = new Alert(“”, “Content handling status: ” + ret.getStatus() + " for content " +
ret.getUrl(),

null, null);
display.setCurrent(alert);
}
} catch (IOException ex) {
Alert alert = new Alert(“”, “Could not go there”, null, null);
display.setCurrent(alert);
}

Listagem 2. Respondendo a uma Invocação de manipulação de conteúdo


public class VCardViewer extends MIDlet
implements ContentListener, CommandListener
{
Invocation invoc;
ContentHandler handler;

public VCardViewer() {
// Register the listener to be notified of new requests
handler = Registry.forClass(this.getClass().getName());
handler.setListener(this);
}

// Process a queued Invocation.


public void invocationNotify() {
// Dequeue the next invocation
invoc = handler.getRequest(0L);
if (invoc!= null) {
// Display the content of the VCard
displayVCard(invoc);
}
}

public void commandAction(Command c, Displayable s) {


if (c == okCommand) {
if (invoc!= null) {
if (handler.finish(invoc, Invocation.OK)) {
notifyDestroyed(); // inform the application manager
}
invoc = null;
}
}
}

void displayVCard(Invocation invoc) throws Exception {


HttpConnection conn = (HttpConnection)invoc.open(false);
VCard vcard = parseVCard(conn.getInputStream());
...
// Display the content based on the action
String action = invoc.getAction();
if (ContentHandler.ACTION_OPEN.equals(action)) {
showView(vcard);
}
if (action.getArgs()!= null && action.getArgs()[0].equals("debug")) {
System.out.println("Application on debug mode!");
}
}
}

Listagem 3. Descritor de um Content Handler registrado estaticamente

MIDlet-1: VCardViewer, /icons/vcard.png, example.VCardViewer


MicroEdition-Handler-1: example.VCardViewer, text/vcard, open, .vcard
MicroEdition-Handler-1-en-US: View
MicroEdition-Handler-1-br-PT: Visualizar
MicroEdition-Handler-2: example.VCardEditor, text/vcard, edit, .vcard
MicroEdition-Handler-2-en-US: Edit
MicroEdition-Handler-2-br-PT: Editar
MicroEdition-Handler-ID: http://jsr-211.java.net/vcardhandler
MIDlet-Jar-Size: 2751
MIDlet-Jar-URL: http://java.net/example/jarFileName.jar
MIDlet-Name: Example Content Handlers
MIDlet-Vendor: Sun Microsystems, Inc.
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile: MIDP-2.0
MIDlet-permissions: javax.microedition.content.ContentHandler

Listagem 4. Registrando um Content Handler dinamicamente


try {
// Create a content handler instance for our Generic PNG Handler
String[] chTypes = { “image/png” };
String[] chSuffixes = { “.png” };
String[] chActions = { ContentHandler.ACTION_OPEN };
String chClassname = “example.content.PNGHandler”;
ContentHandler handler =
Registry.register(chClassname, chTypes, chSuffixes, chActions);
} catch (ContentHandlerException ex) {
// Handle exception
}

Links
JSR 211 – Content Handler API
Página oficial do JSR, onde podem ser encontrados a especificação e o Javadoc mais atual.

Herval Freire (herval@sollipsis.com) é Sun Certified Java Programmer (SCJP), Web Components
Developer (SCWCD) e Micro Application Developer (SCMAD). Atua como consultor em projetos de
mobilidade e aplicações wireless, e nas horas vagas é mochileiro intergalático.

You might also like