LBS e a API Location - Exemplo

Java

12/09/2007

Eterna orientadora: Drª Thienne Mesquita Johnson (thienne@ieee.org) Contribuição: Portal jmebrasil.org e j2me-list-subscribe@soujava.dev.java.net
Centro: CCET - Centro de Ciências Exatas e Tecnologia
Site: www.cci.unama.br
Artigo: www.devmedia.com.br/articles/viewcomp.asp?comp=5356

Serviços Baseados em Localização (LBS) utilizando dados (dados geométricos de lattitude-longitude-altura) do dispositivo GPS (fonte gratis) ou qualquer outra fonte disponibilizada pela operadora de telefonia celular (triangulação de antenas, cell-id...) e a classe javax.microedition.location de J2ME (JSR 179 ou API Location).
Como é um assunto pouco discutido, queria amostrar um exemplo.

ilustração da posição física do dispositivo móvel.

para dispositivos móveis (ex. celulares)


// classes de uso do j2me
 import javax.microedition.midlet.*;
 import javax.microedition.lcdui.*;
 import javax.microedition.location.*;
 import LandmarkEditor;
 
 public class locationMidlet extends Midlet implements CommandListener {
     private Form form = null;
     private static Display display = null;
     // criação dos comandos
     private Command cmdExit;
     private Command cmdPesquisar;
     private Command cmdEditorPOI;
     // campos de latitude, longitude, altura e método usado
     private String lat = "", long = "", alt = "", meth = "";
     // provedor de locazação
     private LocationProvider provedor = null;
     // criterios p/ localização
     private Criteria cr = null;
     // referencia ao Editor de Marcos 
     private LandmarkEditor editorPOI = null;
     // permite saber se o aplicativo iniciou
     boolean inicializado = false;
     // itens do formulário dos informações
     private StringItem siLocalidade;
     private StringItem ErroMsg;
     private StringItem lat;
     private StringItem long;
     private StringItem alt;
     private StringItem meth;
     private static locationMidlet INSTANCIA = null;
     public Alert alert = null;

     private Form myForm;
     private boolean isInitialized;
     private boolean splashIsShown;


     // Main Location MIDlet
     public locationMidlet (){
        if( display == null ){
           // 1ª chamada do MIDlet
           initMIDlet();
        }

          display = Display.getDisplay(this);
          // criação do formulário com titulo
          form = new Form("LBS");
          // subtitulo
          form.append(new StringItem(null, "Localização!"));
          // criação dos comandos
          cmdExit = new Command("Sair", Command.EXIT, 0);
          cmdPesquisar = new Command("Pesquisar", Command.SCREEN, 1);
          cmdEditorPOI = new Command("Editor", Command.STOP, 2);
          // adiciona os comandos ao formulário
          form.addCommand(cmdExit); 
          form.addCommand(cmdPesquisar); 
          form.addCommand(cmdEditorPOI);
          // gerenciador de comandos 
          form.setCommandListener(this);
          editorPOI = new LandmarkEditor(this, data);
          criarProvedor();
          INSTANCIA = this;
     }

     // padrão Singleton p/ o método getInstance
     public static locationMidlet getInstance() {
          if (INSTANCIA == null) {
             INSTANCIA = new locationMidlet();
          }
          return INSTANCIA;
     }

     protected void startApp() throws MIDletStateChangeException{
          if ((display.getCurrent() == null) || (!inicializado)) {
          display.setCurrent(form);

          // amostrará o resultado da consulta do servlet LBS 
          siLocalidade = new StringItem("", "");
          ErroMsg = new String("");
          lat = new String("");
          long = new String("");
          alt = new String("");
          meth = new String("");

          display.setCurrent(form);

          thread tGetLocation = new thread(){
             public void run(){
                while(!splashIsShown){
                  Thread.yield();
                }

                doTimeConsumingInit();
        
                while(true){
                  // loop           
                  Thread.yield();
                }

                try{
   // obtêm uma instância da classe Location
                   LocationProvider provedor=LocationProvider.getInstance(cr);
                   // pega a localização com tempo limite de 60s
                   Location loc=provedor.getLocation(60);
                }
                catch(LocationException e){
                   Alert alert = new Alert("Information", "Dados de localização inválidos", null, AlertType.INFO);
                   display.setCurrent(alert);                
                }
                catch(InterruptedException e){
                   Alert alert = new Alert("Information", "Parada inexperada", null, AlertType.INFO);
                   display.setCurrent(alert);
                }
             }
          }; 

         try {
             tGetLocation.start();
             tGetLocation.join();
             f.append(found(loc)+"location");
             // obtêm uma instancia um QualifiedCoordinates que representa as coordenadas 
             QualifiedCoordinates qc=loc.getQualifiedCoordinates();
             // uso das informações de coordenadas, vincula (exibição) ao formulario (display)
             // Caso haja coordenadas de localização
             coordenadas();
         } 
         catch(Exception e) {
            // tratamento de erro, 
            Alert alert = new Alert("Information", "Dados de localização invalidos", null, AlertType.INFO);
            display.setCurrent(alert);
         }
     }

     // passa o objeto de exibição (Display) do MIDlet e passa a proxima tela depois da exibição do splash screen

     private void initMIDlet(){
        Thread splashScreen = new Thread(new SplashScreenTest());
        splashScreen.start();
        
        Thread myGameThread = new Thread(this);
        myGameThread.start();       
    }

    private void doTimeConsumingInit(){ 
        // Just mimic some lengthy initialization for 10 secs
        long endTime= System.currentTimeMillis()+10000;
        while(System.currentTimeMillis()<endTime ){}
        
        // init the game´s main Displyable (here a Form)
        myForm = new Form("Game Started!");
        myForm.addCommand(exitCommand);
        myForm.setCommandListener(this);
        isInitialized=true;
        display.setCurrent(myForm);
        
    }

    public class SplashScreen implements Runnable{
        private SplashCanvas splashCanvas;
        
        public void run(){
            splashCanvas = new SplashCanvas ();      
            display.setCurrent(splashCanvas);
            splashCanvas.repaint();
            splashCanvas.serviceRepaints();
            while(!isInitialized){
                try{
                    Thread.yield();
                }catch(Exception e){}
            }
        }

    }
    
    public class SplashCanvas extends Canvas {
            protected void paint(Graphics g){
            g.drawString("Show splash screen", 15, 60, Graphics.BOTTOM| Graphics.LEFT );
            g.drawString("image here!", 15, 75, Graphics.BOTTOM| Graphics.LEFT );
            splashIsShown=true;
        }
    }

     public static Display getDisplay(){
         return display;
     }

     // função de pausa orbigatoria do MIDlet
     protected void pauseApp(){
        Alert alert = new Alert("Information", "App em pausa", null, AlertType.INFO);
        display.setCurrent(alert);
        initialized = true;
     }

     // função orbigatoria do midlet (saida) 
     protected void destroyApp(boolean unconditional) throws MIDletStateChangeException{} 

     // gerenciador de ação (comando)
     public void commandAction(Command cmd, Displayable s) {
         if (cmd == cmdExit){
             destroyApp(true);
             notifyDestroyed();
         }
 
         else if (cmd == cmdPesquisar){
             PesquisarGet();
         }

         else if (cmd == cmdEditorPOI){
            if (coord != null){
               editorPOI.showEditor(coord, LandmarkEditor.MODE_ADDNEW);
            }
            else{
                Alert alert = new Alert("Information", "Dados de localização não são válidos", null, AlertType.INFO);
                display.setCurrent(alert);
            }
        } 
     }

     // Tela de apresentação (Splash Screen)

     public void showSplashScreen(Display d, Displayable next){
        Image logo = null;
   
         try {
            // res é a pasta padrão de imagens em um projeto de um MIDlet seguido do nome da imagem
           logo = Image.createImage("/res/GUJ.jpg");
         }
         catch(IOException e){}
    
         Alert a = new Alert("Time Tracker", "Elias Franco Lopes.", logo, null); 
         a.setTimeout(Alert.FOREVER);
         display.setCurrent(a, next);
     }

     // Inicializa o Provedor de Localização (LocationProvider)
     protect void criarProvedor() {
          if (ConfigurationProvider.isLocationApiSupported()){
             ConfigurationProvider.getInstance().autoSearch(this);
          }
          else{
             Alert alert = new Alert("Information", "Dispositivo não suporta a API Location", null, AlertType.INFO);
             // atualiza o display
             display.setCurrent(alert);
             destroyApp(false);
             notifyDestroyed();
        }

        ConfigurationProvider config = ConfigurationProvider.getInstance();
        provedor = config.getSelectedProvider();

        if (provedor == null) {
             Alert alert = new Alert("Information", "MIDLet não pode funcionar sem um provedor de localização", null, AlertType.INFO);
             // atualiza o display
             display.setCurrent(alert);
             destroyApp(false);
             notifyDestroyed();
          }

        if (provedor != null){
              provedor.setLocationListener(this, intervalo, timeout, maxage);
        }

        if (provedor == null) {
            // obtêm uma instancia da classe criteria
            cr = new Criteria();
            // Precisão de 1000m horizontalmente e verticalmente
            cr.setHorizontalAccuracy(100);
            cr.setVerticalAccuracy(100);
            // ajusta o nível de consumo de potência do aparelho p/ realizar a localização (nível alto p/ melhor localização)
            c.setPreferredPowerConsumption(Criteria.POWER_USAGE_HIGH);
       
             thread tGetLocation = new thread(){ 
                 public void run(){ 
                    try{
                       // obtêm uma instância da classe Location 
                       provedor = LocationProvider.getInstance(cr);
                       // pega a localização com tempo limite de 60s 
                       Location loc=provedor.getLocation(60); 
                    } 
                    catch(LocationException e){ 
                       Alert alert = new Alert("Information", "Não é possível criar o LocationProvider para criteria", null, AlertType.INFO);
                       display.setCurrent(alert);
                    } 
                    catch(InterruptedException e){ 
                       Alert alert = new Alert("Information", "Parada inexperada", null, AlertType.INFO);
                       display.setCurrent(alert);
                    } 
                 } 
             }; 
        } 
     }

     public static void coordenadas(){
        if((qc != null) || (loc.isValid())) {
           AddressInfo address = loc.getAddressInfo();
           // obtêm a latitude
           lat = Coordinates.convert(qc.getLatitude(), Coordinates.DD_MM_SS), "");
           // obtêm a longitude
           long = Coordinates.convert(qc.getLongitude(), Coordinates.DD_MM_SS), "");
           // obtêm a altura
           alt = Coordinates.convert(qc.getAltitude(), Coordinates.DD_MM_SS), "");
           String locate = c.convert(alt,1);
           // obtêm a método de localização
           meth = location.getLocationMethod();

           if((loc.getLocationMethod() & loc.MTE_SATELLITE) !=0){
              f.append(?Method = Satellite?);
           }

           // exibe a altura
           f.append("Altura: "+lat);
           // exibe a latitude
           f.append("Latitude: "+long);
           // exibe a longitude
           f.append("Longitude: "+alt);
           // exibe o método
           f.append("Método: "+meth);
           // exibe a localizadde
           f.append(siLocalidade);
           // atualiza o display
           display.setCurrent(f);
        }
        else{
           // caso a localização ou as coordenadas não é valida.
           String msg = location.getExtraInfo(?application/X-jsr179-location-nmea?);
           f.append("Localização não válida: "+msg);
           loc.getExtraInfo(String mimetype);
           getExtraInfo(?application/X-jsr179-location-nmea?);
           getExtraInfo(?text/plain?);
           f.append(?loc.getExtraInfo("text/plain"));
        }
        qc = loc.getQualifiedCoordinates();
     }

     // Exibe o estado do provedor de localização
     public static void showProvStatus(){
        Gauge indicador = new Gauge(null, false, 50, 1);
        indicador.setValue(Gauge.CONTINUOUS_RUNNING);

        Alert alert = new Alert("Information", "Espere, procurando por dados de localização....", null, AlertType.INFO);
        alert.setIndicator(indicador);
        display().setCurrent(alert);
    }

     // Acesso ao Servlet Usando metodo Get
     public void PesquisarGet() throws IOException {
        // Criação dos elementos HttpConnection e InputStream utilizados numa conexão do tipo GET
        HttpConnection hc = null;
        InputStream is = null;
        boolean ret = false;

        thread tConnection = new thread(){
           public void run(){
              // Inicializa uma conexão
              hc = (HttpConnection) Connector.open(url);
              hc.setRequestMethod(HttpConnection.GET);
           }
        };
 
        // Definição de URL que enviara os dados (coordenadas) para a pesquisa
        String url = "http://ENDEREÇO_DO_SERVLET:8080/" + "?" + "latitude=" + lat + "&longitude=" + long
 
        try{
           // Inicializa uma conexão
           AlertType.INFO.playSound(m_Display);
           tConnection.start();
           tConnection.join();
           // Inicia o InputStream para troca de mensagens
           is = hc.openInputStream();
           ret = processResp(hc, is)     
         }
 
         finally{
            if (is != null)
               // Finaliza conexão
               is.close();   
               if (hc != null)
                  hc.close();
            }
            if(ret == false)
               showAlert(erroMsg);
            }
 
     // Processa uma reposta do Servlet
     public boolean processaResp(HttpConnection hc, InputStream is) throws IOException {        
        erroMsg = null; 
        // se conexão realizada e resposta foi OK, calcula o tamanho da resposta (resultado)
        if(hc.getResponseCode() == HttpConnection.HTTP_OK){
           int length = (int) hc.getLength();
           string str;
              
           if(length != -1){
              byte servletData[] = new Byte[lenght];
              // recebe resposta do servlet e depois guarda em str
              is.read(servletData);
              str = new string(servletData);
           }
           else{  
              ByteArrayOutputstream bos = new ByteArrayOutputstream();
              int ch;
              while(ch = is.read() != -1)
                 bos.write(ch);
             
              str = new String(bos.toByteArray());
              bos.close()
           }
           // amostra o resultado (resposta do servlet) no display   
           siLocalidade.setText(str);
           return true;
        }
        else{
           erroMsg = new String(hc.getResponseMessage());
           showAlerta(erroMsg);
           return false;
        }

        // exibe um alerta
        private void showAlerta(String msg){
           alert = new Alert("Error", msg, null, AlertType.ERROR);
           alert.setTimeout(3000); // 3 seg
           display.setCurrent(alert, this);
           return null;
        }

} // fim de locationMidlet 



Um alerta é flexível bastante, entretanto. Para demitir a tela com toda a chave ou para indicar um animation simples, é necessio usar um Canvas p/ a splash screen.
A classe Canvas da tela de apresentação (splash screen)


import java.util.*;
import javax.microedition.lcdui.*;

public class SplashScreen extends Canvas {
    private Display display;
    private Displayable next;
    private Timer timer = new Timer();

    public SplashScreen(Display display, Displayable next){
        this.display = display;
        this.next = next;
        display.setCurrent(this);
    }

    protected void keyPressed(int keyCode){
        dismiss();
    }

    protected void paint(Graphics g){
       g.setColor(255, 0, 0);
       g.fillRect(0, 0, getWidth(), getHeight(  ));
       g.setColor(255, 255, 255);
       g.drawString("Hello World!", 0, 0, g.TOP | g.LEFT);
    }

    protected void pointerPressed(int x, int y){
        dismiss();
    }

    protected void showNotify(){
        timer.schedule(new CountDown(), 5000);
    }

    private void dismiss(){
        timer.cancel();
        display.setCurrent(next);
    }

    private class CountDown extends TimerTask {
        public void run(){
            dismiss();
        }
    }
}



Classe do editor de marcos/pontos de interesse (landmark)


     import java.io.IOException;
     import java.util.Enumeration;
     import javax.microedition.lcdui.*;
     import javax.microedition.location.*;
     import ControleMarcos;

     Editor de Marcos/pontos de interesse (landmark)
     class LandmarkEditor extends Form implements CommandListener{
     // campos referentes aos marcos. (*) = campos obrigatórios
     private TextField nameField;
     private TextField descField;

     // campos do AddressInfo
     private TextField countryField;
     private TextField stateField;
     private TextField cityField;
     private TextField streetField;
     private TextField buildingNameField;
     // constantes
     public static final int MODE_UPDATE = 0;
     public static final int MODE_ADDNEW = 1;
     private QualifiedCoordinates coord = null;
     private Displayable route = null;
     private TouristData data = null;
     // informação de coordenadas
     private StringItem lat;
     private StringItem lon;
     private StringItem alt;
     // lista do marco selecionado
     private List list;
     private Command saveNewCmd;
     private Command saveUpdatedCmd;
     private Command updateCmd;
     private Command removeCmd;
     private Command listCmd;
     private Command routeCmd;

     public LandmarkEditor(Displayable route, TouristData data){
        super("Editor de Marcos");

        nameField = new TextField("Name (*):", "", 20, TextField.ANY);
        descField = new TextField("Description (*):", "", 40, TextField.ANY);
        countryField = new TextField("Country:", "", 20, TextField.ANY);
        stateField = new TextField("State:", "", 20, TextField.ANY);
        cityField = new TextField("City:", "", 20, TextField.ANY);
        streetField = new TextField("Street:", "", 20, TextField.ANY);
        buildingNameField = new TextField("Building name (*):", "", 20, TextField.ANY);
        lat = new StringItem("Lat:", "");
        lon = new StringItem("Lon:", "");
        alt = new StringItem("Alt:", "");
        list = new List("Landmarks:", List.EXCLUSIVE);
        cmdSaveNew = new Command("Savar", Command.OK, 1);
        cmdSaveUpdated = new Command("Savar", Command.OK, 1);
        cmdUpdate = new Command("Atualizar", Command.OK, 1);
        cmdRemove = new Command("Remover", Command.OK, 1);
        cmdList = new Command("Listar", Command.OK, 1);
        cmdRoute = new Command("Rota", Command.BACK, 1);

        this.route = route;
        this.data = data;

        // comandos do editor de marcos
        addCommand(routeCmd);
        addCommand(listCmd);
        setCommandListener(this);

        // comandos da lista de marcos 
        list.addCommand(routeCmd);
        list.setCommandListener(this);
    }

    // inicializa campos e exibe o editor de marcos
    public void showEditor(QualifiedCoordinates newCoord, int mode){
        this.coord = newCoord;

        // inicializa as coordenadas
        lat.setText(formatDouble(newCoord.getLatitude(), 3));
        lon.setText(formatDouble(newCoord.getLongitude(), 3));
        alt.setText(formatDouble(newCoord.getAltitude(), 1));

        // inicializa campos
        nameField.setString("");
        descField.setString("");
        countryField.setString("");
        stateField.setString("");
        cityField.setString("");
        streetField.setString("");
        buildingNameField.setString("");

        deleteAll();
        append(nameField);
        append(descField);
        append(countryField);
        append(stateField);
        append(cityField);
        append(streetField);
        append(buildingNameField);

        append(lat);
        append(lon);
        append(alt);

        // Atualiza existente marco
        if (mode == MODE_UPDATE){
            Landmark lm = ControleMarcos.getInstance().localizarProxMarco(newCoord);

            if (lm != null){
                nameField.setString(lm.getName());
                descField.setString(lm.getDescription());

                AddressInfo info = lm.getAddressInfo();
                if (info != null){
                    countryField.setString(info.getField(AddressInfo.COUNTRY));
                    stateField.setString(info.getField(AddressInfo.STATE));
                    cityField.setString(info.getField(AddressInfo.CITY));
                    streetField.setString(info.getField(AddressInfo.STREET));
                    buildingNameField.setString(info.getField(AddressInfo.BUILDING_NAME));
                }
            }

            removeCommand(updateCmd);
            removeCommand(saveNewCmd);
            addCommand(saveUpdatedCmd);
            addCommand(listCmd);
        }
        // adiciona novo marco ao LandmarkStore.
        else if (mode == MODE_ADDNEW){
            removeCommand(updateCmd);
            removeCommand(saveUpdatedCmd);
            addCommand(saveNewCmd);
            addCommand(listCmd);
        }
        display.setCurrent(this);
    }

    public void showList(){
        list.deleteAll();
        Landmark lm = null;
        Enumeration enuMarcos = ControleMarcoss.getInstance().getLandMarks();

        // verifica se o marco existe no landmarkstore.
        if (landmarks != null){
            while (enuMarcos.hasMoreElements()){
                lm = ((Landmark) enuMarcos.nextElement());
                list.append(lm.getName(), null);
            }

            list.addCommand(cmdUpdate);
            list.addCommand(cmdRemove);
        }
        // marco ñ localizado (lista em branco)
        else{
            list.removeCommand(cmdUpdate);
            list.removeCommand(cmdRemove);
        }
        display.setCurrent(list);
    }

    // verefica se os campos obrigatórios foram preenchidos
    private String checaCampos(){
        if (nameField.getString().equals("")){
            return "Nome";
        }
        else if (nameField.getString().equals("")){
            return "Descrição";
        }
        else if (buildingNameField.getString().equals("")){
            return "Local";
        }
        return null;
    }

     private Landmark gerarMarco(){
        String field = checaCampos();
        if (field != null){
           erroMsg = new String("Valor do campo obrigatório ("+ field + ") está errado");
           showAlerta(erroMsg);

           /*
           Alert alert = new Alert("Error", "Valor do campo obrigatório ("+ field + ") está errado.", null, AlertType.ERROR);
              alert.setTimeout(3000); // 3 secs
              display().setCurrent(alert, this);
              return null;
           }
           */

        AddressInfo info = new AddressInfo();
        info.setField(AddressInfo.COUNTRY, countryField.getString());
        info.setField(AddressInfo.STATE, stateField.getString());
        info.setField(AddressInfo.CITY, cityField.getString());
        info.setField(AddressInfo.STREET, streetField.getString());
        info.setField(AddressInfo.BUILDING_NAME, buildingNameField.getString());

        Landmark lm = new Landmark(nameField.getString(), descField.getString(), coord, info);
        return lm;
    }

        public void commandAction(Command command, Displayable displayable){
        Landmark landmark = null;

        // adiciona novo marco ao LandmarkStore
        if (command == cmdSaveNew){
            landmark = gerarMarco();
            if (landmark != null){
                try{
                    ControleMarcos.getInstance().addMarco(landmark);
                    data.createProximityListener(coord);
                }
                catch (IOException e)
                {
                    Alert alert = new Alert("Error", "Erro de Entrada/Saída", null, AlertType.ERROR);
                    display().setCurrent(alert);
                }
                // novo marco avaliado na lista
                showList();
            }
        }
        // atualiza o marco
        else if (command == cmdSaveUpdated){
            landmark = gerarMarco();
            if (landmark != null){
                try{
                    ControleMarcos.getInstance().atualizarMarco(landmark);
                    data.createProximityListener(coord);
                }
                catch (IOException e){
                    Alert alert = new Alert("Error", "Erro de Entrada/Saída", null, AlertType.ERROR);
                    display().setCurrent(alert);
                }
                catch (LandmarkException e){                   
                    Alert alert = new Alert("Error","Marco não localizado no Landmark Store.", null, AlertType.ERROR);
                    display().setCurrent(alert);
                }
                // atualiza o marco avaliado na lista
                showList();
            }
        }
        // retorna a tela anterior
        else if (command == cmdRoute){
           display().setCurrent(route);
        }
        // Show landmark editor for the selected landmark.
        else if (command == cmdUpdate){
            int index = list.getSelectedIndex();
            landmark = ControleMarcos.getInstance().proxMarco(index);
            showEditor(landmark.getQualifiedCoordinates(), MODE_UPDATE);
        }
        // Remove o marco selecionado do LandmarkStore
        else if (command == cmdRremove){
            try{
                int index = list.getSelectedIndex();
                landmark = ControleMarcos.getInstance().proxMarco(index);
                ControleMarcos.getInstance().removeMarco(landmark);

                Alert alert = new Alert("Information", "Marco removido com sucesso.", null, AlertType.INFO);
                display().setCurrent(alert);
            }
            catch (IOException e){
                Alert alert = new Alert("Error", "Erro de Entrada/Saída",null, AlertType.ERROR);
                display().setCurrent(alert);
            }
            catch (LandmarkException e){
                Alert alert = new Alert("Error", "Marco não localizado no Landmark Store.",
                        null, AlertType.ERROR);
                alert.setTimeout(3000); // 3 secs
                TouristMIDlet.getDisplay().setCurrent(alert);
            }
            showList();
        }
        // exibe a lista de marcos localizados
        else if (command == cmdList){
            showList();
        }
    }

    public static String formatDouble(double value, int decimals){
        String doubleStr = "" + value;
        int index = doubleStr.indexOf(".") != -1 ? doubleStr.indexOf("."): doubleStr.indexOf(",");
        // determina o ponto de decimal
        if (index == -1) return doubleStr;
        // trunca todos os decimais
        if (decimals == 0){
            return doubleStr.substring(0, index);
        }

        int len = index + decimals + 1;
        if (len >= doubleStr.length()) len = doubleStr.length();
        double d = Double.parseDouble(doubleStr.substring(0, len));
        return String.valueOf(d);
    }
}



Classe que cuida das ações sobre os marcos (landmark)


import java.io.IOException;
import java.util.Enumeration;
import javax.microedition.location.*;

public class ControleMarcos{
    private LandmarkStore store = null;
    private static final String STORE-NOME = "TURISTA";
    private static final String CATEG-PADRAO = null;
    private static ControleMarcos INSTANCIA = null;

    private ControleMarcos(){
        String nome = null;
        // tenta localizar no LandmarkStore "TURISTA".
        try{
            store = LandmarkStore.getInstance(STORE-NOME);
        }
        catch (NullPointerException e){
        }

        // verifica se a LandmarkStore selecionada existe
        if (store == null){
            // LandmarkStore não existe
            try{
                // cria um LandmarkStore de nome "TURISTA".
                LandmarkStore.createLandmarkStore(STORE-NOME);
                name = STORE-NOME;
            }
            catch (IllegalArgumentException e){                
            }
            catch (IOException e){
            }
            catch (LandmarkException e){
            }

            store = LandmarkStore.getInstance(nome);
        }
    }

    // padrão Singleton p/ o método getInstance
    public static ControleMarcos getInstance(){
        if (INSTANCIA == null){
            INSTANCE = new ControleMarcos();
        }
        return INSTANCIA;
    }

    // localiza o marco selecionado do LandmarkStore usando o indice
    public Landmark proxMarco(int index){
        Landmark lm = null;
        Enumeration enuCm = ControleMarcos.getInstance().getLandMarks();
        int counter = 0;

        while (enuCm.hasMoreElements()){
            lm = (Landmark) enuCm.nextElement();
            if (counter == index){
                break;
            }
            counter++;
        }
        return lm;
    }

    // localizado o próximo marco na LandmarkStore de acordo com coodenadas 
    public Landmark localizarProxMarco(Coordinates coord){
        Landmark landmark = null;
        double latRaio = 0.1;
        double lonRaio = 0.1;
        float dist = Float.MAX_VALUE;

        try{
            // gera um vetor de marcos de acordo com as coordenadas.
            Enumeration enu = store.getLandmarks(null, coord.getLatitude() - latRaio, coord.getLatitude() + latRadio, coord.getLongitude() - lonRaio, coord.getLongitude() + lonRadius);
            float tmpDist;
            Landmark tmpLandmark = null;

            while (enu.hasMoreElements()){
                tmpLandmark = (Landmark) enu.nextElement();
                tmpDist = tmpLandmark.getQualifiedCoordinates().distance(coord);

                if (tmpDist &lt dist){
                    landmark = tmpLandmark;
                }
            }
        }
        catch (IOException e){
            return null;
        }
        return landmark;
    }

    public Enumeration getLandMarks(){
        Enumeration enu = null;
        try{
            enu = store.getLandmarks();
        }
        catch (IOException e){
        }
        return enu;
    }

    // método de adição de marco
    public void addMarco(Landmark landmark) throws IOException{
        store.addLandmark(landmark, CATEG-PADRAO);
    }

    // método de atualização do marco
    public void atualizarMarco(Landmark landmark) throws IOException, LandmarkException{
        store.updateLandmark(landmark);
    }

    // método de remoção do marco
    public void removeMarco(Landmark landmark) throws IOException, LandmarkException{
        store.deleteLandmark(landmark);
    }



Código para uso no desktop, por exemplo com um GPS ligado ao computador via bluetooth


 import javax.microedition.location;
 //...

 void locationDesktop(){
     LocationProvider lp = LocationProvider.getInstance(null);
     Location loc = lp.getLocation(10);
     QualifiedCoordinate qc = LocationProvider.getInstance(
          new Criteria()).getLastKnownLocation().getQualifiedCoordinates() ;
     String exinf = l.getExtraInfo("text/plain");
     System.out.println("A palavra é... " + exinf); 
     if ((qc != null) || (location.isValid()){
        double latitude = qc.getLatitude();
        double longitude = qc.getLongitude();
        String locate = c.convert(alt,1);
        graphics.drawString(locate,4,30,Graphics.TOP|Graphics.LEFT); 
        System.out.println("Latitude: " + latitude);
        System.out.println("Longitude: " + longitude);
        System.out.println("Método: "+location.getLocationMethod());
     else{
        // caso a localização ou coordenadas não é valida.
        String msg = location.getExtraInfo(?application/X-jsr179-location-nmea?);
System.out.println(?Localização não valida: ?+msg);
     }

 }



Código da classe do servlet (servidor web) que receberá as coordenadas (dados gps) e realizará a consulta

Classe do servlet


import javax.servlet.http.*;
 import javax.servlet.*;
 import java.io.*;
 import java.util.*;
 import java.sql.*;
 
 public class Servlet extends HttpServlet {
      
      // Procedimento doGet (recebimento de solicitação do cliente)
      public void doGet(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {      
         
         // Captura os dados passados por parametro atraves do endereço URL
         String latitude = request.getParameter("latitude"),
         longitude = request.getParameter("longitude");
         String localidade = pesquisaLocal(latitude, longitude);
 
         // se resultado vazio, amostra msg de erro
         if(localidade == null){
     res.SendError(res.SC_BAD_REQUEST, "Nao possivel localizar o local");
     return;
 }
 
 res.SendContentType("text/plain");
 // Inicializa o objeto PrintWriter que vai escrever(enviar pro dispositivo) a resposta
         PrintWriter out = res.getWriter();
 out.print(localidade);
 out.close();
 desconectar();
      }
 
      // Pesquisa num banco de dados
      public String pesquisaLocal(String latitude, String longitude){
 Connection conn = null;
 Statement st = null;
 StringBuffer msgb = new StringBuffer("");
                // commando básico de pesquisa em um BD 
 String sql = Select LOCALIDADE From DADOS_LOCALIDADE Where latitude = " + latitude + "And longitude = " + longitude + "´"
 
 try{
                 // informações sobre o BD ussado ,no caso hsqldb
     Class.forName("org.hsqldb.jdbcDriver");
                 // nome do usuário (login), senha e endereço url do BD
             String user = "sa";
             String password = "";
           String url = "jdbc:hsqldb:hsql://localhost";            
     conn = DriverManager.getConnection(url,user,password);
 
     Statement stm = conn.createStatement();
     ResultSet rs = stm.executeQuery(sql);
 
     // retorna o resultado da pesquisa
     if(rs.next())
         return rs.getString(1);
     else
         resturn null;
  }
  // Erro ao acessar o banco de dados
         catch(ClassNotFoundException e) {
             resp = "* ERRO: BANCO DE DADOS INACESSIVEL! ";
             // e.printStackTrace(); // Esta linha iria imprimir no console informações sobre o erro obtido
         }
         
         // Erro ao executar a consulta sql
         catch(SQLException e) {
             resp = "* ERRO: CONSULTA SQL INVÁLIDA!";
             // e.printStackTrace();
         }
      }
 
      // Finaliza a conexão com o banco de dados
      public void desconectar() throws SQLException {
         this.conn.close();
      }
 }



Classe CongurationProvider, essa clase não faz parte da API Location. Precisa ser implementada


import javax.microedition.location.Criteria;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationProvider;
import javax.microedition.location.Orientation;

public class ConfigurationProvider
{
    private static ConfigurationProvider INSTANCE = null;
    private static Criteria[] freeCriterias = null;
    private static String[] freeCriteriaNames = null;
    private static Criteria[] costCriterias = null;
    private static String[] costCriteriaNames = null;
    private Criteria criteria = null;
    private LocationProvider provider = null;

    // estático contendo critério pagos grátis

    static
    {
        // 1. pré-definição dos critérios grátis

        freeCriterias = new Criteria[2];
        freeCriteriaNames = new String[2];

        Criteria crit1 = new Criteria();
        crit1.setHorizontalAccuracy(25); // 25m
        crit1.setVerticalAccuracy(25); // 25m
        crit1.setPreferredResponseTime(Criteria.NO_REQUIREMENT);
        crit1.setPreferredPowerConsumption(Criteria.POWER_USAGE_HIGH);
        crit1.setCostAllowed(false);
        crit1.setSpeedAndCourseRequired(true);
        crit1.setAltitudeRequired(true);
        crit1.setAddressInfoRequired(true);

        freeCriterias[0] = crit1;
        freeCriteriaNames[0] = "High details, cost not allowed";

        Criteria crit2 = new Criteria();
        crit2.setHorizontalAccuracy(Criteria.NO_REQUIREMENT);
        crit2.setVerticalAccuracy(Criteria.NO_REQUIREMENT);
        crit2.setPreferredResponseTime(Criteria.NO_REQUIREMENT);
        crit2.setPreferredPowerConsumption(Criteria.POWER_USAGE_HIGH);
        crit2.setCostAllowed(false); // allowed to cost
        crit2.setSpeedAndCourseRequired(false);
        crit2.setAltitudeRequired(false);
        crit2.setAddressInfoRequired(false);

        freeCriterias[1] = crit2;
        freeCriteriaNames[1] = "Low details and power consumption, cost not allowed";

        // 2. pré-definição dos critérios pagos

        costCriterias = new Criteria[3];
        costCriteriaNames = new String[3];

        Criteria crit3 = new Criteria();
        crit3.setHorizontalAccuracy(25); // 25m
        crit3.setVerticalAccuracy(25); // 25m
        crit3.setPreferredResponseTime(Criteria.NO_REQUIREMENT);
        crit3.setPreferredPowerConsumption(Criteria.NO_REQUIREMENT);
        crit3.setCostAllowed(true);
        crit3.setSpeedAndCourseRequired(true);
        crit3.setAltitudeRequired(true);
        crit3.setAddressInfoRequired(true);

        costCriterias[0] = crit3;
        costCriteriaNames[0] = "High details, cost allowed";

        Criteria crit4 = new Criteria();
        crit4.setHorizontalAccuracy(500); // 500m
        crit4.setVerticalAccuracy(Criteria.NO_REQUIREMENT);
        crit4.setPreferredResponseTime(Criteria.NO_REQUIREMENT);
        crit4.setPreferredPowerConsumption(Criteria.NO_REQUIREMENT);
        crit4.setCostAllowed(true);
        crit4.setSpeedAndCourseRequired(true);
        crit4.setAltitudeRequired(true);
        crit4.setAddressInfoRequired(false);

        costCriterias[1] = crit4;
        costCriteriaNames[1] = "Medium details, cost allowed";

        // Least restrictive criteria (with default values)
        Criteria crit5 = null;

        costCriterias[2] = crit5;
        costCriteriaNames[2] = "Least restrictive criteria";
    }

    // construtor
    private ConfigurationProvider()
    {
        queryUI = new ProviderQueryUI();
    }

    // uso do padrão singleton
    public static ConfigurationProvider getInstance()
    {
        if (INSTANCE == null)
        {
            // Enable use of this class when Location API is supported.
            if (isLocationApiSupported())
            {
                INSTANCE = new ConfigurationProvider();
            }
            else
            {
                INSTANCE = null;
            }
        }

        return INSTANCE;
    }

    // checa o suporte a API
    public static boolean isLocationApiSupported()
    {
        String version = System.getProperty("microedition.location.version");
        return (version != null && !version.equals("")) ? true : false;
    }

    public LocationProvider getSelectedProvider()
    {
        return provider;
    }

    // procura o provedor de localização
    public void autoSearch(ProviderStatusListener listener)
    {
        try
        {
            for (int i = 0; i &lt freeCriterias.length; i++)
            {
                criteria = freeCriterias[i];

                provider = LocationProvider.getInstance(criteria);
                if (provider != null)
                {
                    // Location provider found, send a selection event.
                    listener.providerSelectedEvent();
                    return;
                }
            }

            if (confirmCostProvider())
            {
                for (int i = 0; i &lt costCriterias.length; i++)
                {
                    criteria = costCriterias[i];

                    provider = LocationProvider.getInstance(criteria);
                    if (provider != null)
                    {
                        // Location provider found, send a selection event.
                        listener.providerSelectedEvent();
                        return;
                    }
                }
            }
            else
            {
                showNoFreeServiceFound();
            }
        }
        catch (LocationException le)
        {
            showOutOfService();
        }
    }

    public Orientation getOrientation()
    {
        try
        {
            return Orientation.getOrientation();
        }
        catch (LocationException e)
        {
            return null;
        }
    }

    // checa se o indicador de direção é suportado
    public boolean isOrientationSupported()
    {
        try
        {
            // Test whether Orientation instance can be obtained.
            Orientation.getOrientation();
            return true;
        }
        catch (LocationException e)
        {
            return false;
        }
    }

    // chega os serviços grátis ligados
    public void showNoFreeServiceFound()
    {
        Alert alert = new Alert("Error", NO_FREE_SERVICE_SERVICE_MESSAGE, null,
                AlertType.ERROR);
        alert.setTimeout(Alert.FOREVER);
        TouristMIDlet.getDisplay().setCurrent(alert, searchForm);
        infoItem.setText(NOT_FOUND_MESSAGE);
    }

    // chega os serviços pagos ligados
    public synchronized boolean confirmCostProvider()
    {
        Alert alert = new Alert("Confimnation", COST_QUERY_MESSAGE, null,
                AlertType.CONFIRMATION);
        alert.addCommand(yesCmd);
        alert.addCommand(noCmd);
        alert.setTimeout(Alert.FOREVER);

        // Set the monitoring object to be this instance.
        final ProviderQueryUI hinstance = this;

        // Add a CommandLister as anomynous inner class
        alert.setCommandListener(new CommandListener()
        {
            /*
             * Event indicating when a command button is pressed.
             * 
             * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command,
             *      javax.microedition.lcdui.Displayable)
             */
            public void commandAction(Command command, Displayable d)
            {
                if (command == yesCmd)
                {
                    infoItem.setText(SEACHING_COST_PROVIDERS);
                    result = true;
                    synchronized (hinstance)
                    {
                        // Wake up the monitoring object
                        hinstance.notifyAll();
                    }
                }
                else if (command == noCmd)
                {
                    result = false;
                    infoItem.setText(NOT_FOUND_MESSAGE);
                    synchronized (hinstance)
                    {
                        // Wake up the monitoring object
                        hinstance.notifyAll();
                    }
                }

            }
        });

}



Abraço Elias.Lôgan-X
Texto revisto e atualizado em: agosto/2007

Abraço Elias.Lôgan-X


Liclopes

Liclopes

Curtidas 0
POSTAR