Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

Como utilizar uma API opcional em Java ME

From Wiki
Jump to: navigation, search
Article Metadata

Artigo
Tradução:
Por thiagobrunoms
Última alteração feita por lpvalente em 09 Nov 2013

Este artigo demonstra como detectar a presença de uma API opcional (como a API Location) em tempo de execução, e usá-lo somente se ele estiver disponível. Por exemplo, para desenvolver um aplicativo que funciona no dispositivo sem a Location API, mas pode tornar-se consciente de localização em dispositivos que têm a API Location, sem a necessidade de várias compilações.

Este exemplo fará referência para a API Location, mas se aplica igualmente a outras APIs.

Contents

Advertência

Esta técnica deve funcionar em toda a máquina virtual Java compatível com a especificação VM incluindo a especificação CLDC. No entanto, pode haver algumas VMs que realizam algum tipo de instalação de verificação do tempo, ou otimização de re-compilação do bytecode Java, que impedem que esta técnica funcione. Não funciona no modelo Motorola T720 (dispositivo MIDP-1). search

Teoria

A fim de executar o código em uma classe Java, cinco etapas devem ser concluídas.

  1. Carregamento. O arquivo de classe é localizado e carregado na memória heap do Java. Isto acontece quando a classe é necessária para o carregamento de outra classe, ou quando Class.forName () é invocado.
  2. Verificação. O byte-code é verificado para garantir que representa um programa em Java correto e válido. Isso sempre ocorre antes da preparação
  3. Preparação. A memória é alocada para os campos estáticos da classe, e inicializado com valores padrão (0, 0,0, '\ 0', falso ou nulo). Isso sempre ocorre antes da resolução.
  4. Resolução. Qualquer outra classe referenciada por esta classe são localizadas e carregadas.
  5. Inicialização. A classe de inicialização é executada. Isto inclui qualquer bloco static{} na definição da classe, e qualquer código utilizado para inicialização de campos estáticos (statics). Este passo é disparado na primeira tentativa de criar a instância da classe, para acessar algum dos campos estáticos, ou para invocar algum dos métodos estáticos.

Resolução é o passo chave. Se usarmos uma classe que faz referência a uma API inexistente, este é o ponto onde o código não irá funcionar. Precisamos ter certeza de que este processo só ocorre se a API está presente.

Eu não expliquei quando o processo de resolução irá funcionar. Isto porque varia entre diferentes implementações da JVM. Diferentes implementações da JVM executam este passo em tempos diferentes. Aqui encontram-se dois exemplos:

  • Mais cedo: A VM realiza verificação, preparação e resolução completa da classe imediatamente após o carregamento. Isso normalmente resulta em um conjunto de classes que estão sendo carregados e resolvido, muitas vezes a aplicação inteira.
  • Mais tarde: A VM pode esperar até que as referências da classe externa precisam ser resolvidas, a fim de executar código na classe.

E existem variações entre os dois.

Em VMs que a resolução de uso final, pode ser o suficiente para não executar qualquer código que se refere à API em falta. No entanto, esse código pode quebrar em VMs que a resolução de uso mais cedo.

Para ter certeza que o nosso código irá funcionar, precisamos ter certeza de que nenhuma classe é sempre carregada que refere-se a API opcional, a menos que a API está presente.

Técnica

Criar um pacote separado

Isto é opcional, mas torna a técnica "mais seguro". Vamos dizer que a nossa aplicação está no pacote:

com.mycompany.myapplication pacote;

Nenhuma classe neste pacote terá qualquer referência à localização da API. Nós vamos colocar todos os serviços de localização de código em um pacote separado:

com.mycompany.locationservices pacote;

Ao fazer isso, nós podemos parar de codificar na aplicação do código de acesso local diretamente, usando pacote de privacidade. Isto fará mais sentido depois.

Crie uma classe abstrata

Nós precisamos criar uma classe abstrata no pacote de serviços de localização. Esta será a única classe pública em que o pacote, e é o único que não deve utilizar uma parte do local da API. Ele irá definir uma interface através da qual vamos utilizar serviços de localização.

package com.mycompany.locationservices;
 
public abstract class LocationProvider {
// define a interface através da qual iremos accessar as informações de localização
public abstract double getLatitude();
public abstract double getLongitude();
 
/**
* este método será utilizado para obter informações da classe LocationProvider
*/
public static LocationProvider getProvider() throws ClassNotFoundException {
LocationProvider provider;
try {
// Este trecho irá lançar se a JSR-179 não estiver disponível
Class.forName("javax.microedition.location.Location");
 
// mais sobre esta classe depois!
Class c = Class.forName("com.mycompany.locationservices.LocationImplementation");
provider = (LocationProvider)(c.newInstance());
} catch (Exception e) {
throw new ClassNotFoundExcepion("API Location não encontrada!");
}
return provider;
}
}

Esta classe não faz referência a classes em JSR-179, nem a qualquer outra classe do pacote locationservices, excetopara referências em Strings em chamadas para Class.forName (). Estes não fará com que as classes sejam carregadas até que sejam executadas, e então eles vão lançar exceções (que podem ser capturadas e manipuladas), se existir um problema.

Uma vez que esta será a única classe pública no pacote, ela será a única classe que pode referir-se a partir da aplicação principal. Porque ele não faz referência a quaisquer categorias de localização, é seguro fazer referência a ela.

A classe LocationImplementation não será pública, e por isso deve estar no mesmo pacote que LocationProvider para evitar uma exceção do tipo IllegalAccessError.

Criando uma Implementação

Agora nós precisamos da classe LocationImplementation discutida anteriormente.

package com.mycompany.locationservices;
 
import javax.microedition.location.*;
 
class LocationImplementation extends LocationProvider {
 
LocationImplementation() {
/*
Nós devemos ter um construtor sem parâmetros, ou a chamada a Class.newInstance() não pode
criar uma instância desta classe.
*/
}
 
// implemente os métodos abstratos de LocationProvider
 
public double getLatitude() {
// fazer qualquer coisa!
}
 
public double getLongitude() {
// fazer qualquer coisa!
}
}

Note que essa classe não é pública. Isso impede que as classes fora deste pacote use-a, e é um protetor seguro contra acessos em outro lugar (e arruinando o nosso plano de esperteza).

Quaisquer outras classes necessárias para apoiar este pode ser criado neste pacote, mas torne-os pacotes privados (não público) também.

Utilizando o LocationProvider

Para utilizar isto na aplicação é muito fácil agora.

try {
LocationProvider provider = LocationProvider.getProvider();
double latitude = provider.getLatitude();
double longitude = provider.getLongitude();
} catch (ClassNotFoundException cnfe) {
// não está disponível a API Location neste dispositivo
}
This page was last modified on 9 November 2013, at 22:51.
176 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×