LBS e a API Location - Exemplo
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)
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)
Classe do editor de marcos/pontos de interesse (landmark)
Classe que cuida das ações sobre os marcos (landmark)
Código para uso no desktop, por exemplo com um GPS ligado ao computador via bluetooth
Código da classe do servlet (servidor web) que receberá as coordenadas (dados gps) e realizará a consulta
Classe do servlet
Classe CongurationProvider, essa clase não faz parte da API Location. Precisa ser implementada
Abraço Elias.Lôgan-X
Texto revisto e atualizado em: agosto/2007
Abraço Elias.Lôgan-X
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 < 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 < 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 < 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
Curtidas 0