Eterna orientadora: Drª Thienne Mesquita Johnson ([email removido]) Contribuição: Portal jmebrasil.org e [email removido]
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)
[code]
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);
}
[code]
Código para uso no desktop, por exemplo com um GPS ligado ao computador via bluetooth
[code]
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);
}
}
[/code]
Código da classe do servlet (servidor web) que receberá as coordenadas (dados gps) e realizará a consulta
Classe do servlet
[code]
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();
}
}[/code]
Classe CongurationProvider, essa clase não faz parte da API Location. Precisa ser implementada
[code]
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();
}
}
}
});
}[/code]
Abraço Elias.Lôgan-X
Texto revisto e atualizado em: agosto/2007
Abraço Elias.Lôgan-X[code][/code]
