/* * ReverseGeocodeScreen.java * * Copyright � 1998-2011 Research In Motion Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Note: For the sake of simplicity, this sample application may not leverage * resource bundles and resource strings. However, it is STRONGLY recommended * that application developers make use of the localization features available * within the BlackBerry development platform to ensure a seamless application * experience across a variety of languages and geographies. For more information * on localizing your application, please refer to the BlackBerry Java Development * Environment Development Guide associated with this release. */ package com.rim.samples.device.geocodedemo; import java.util.Vector; import net.rim.device.api.lbs.maps.model.MapLocation; import net.rim.device.api.lbs.maps.model.MapPoint; import net.rim.device.api.lbs.maps.server.ReverseGeocoder; import net.rim.device.api.lbs.maps.server.ServerExchangeCallback; import net.rim.device.api.lbs.maps.server.exchange.ReverseGeocodeException; import net.rim.device.api.lbs.maps.server.exchange.ReverseGeocodeExchange; import net.rim.device.api.lbs.maps.server.exchange.ServerExchange; import net.rim.device.api.system.Application; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.FieldChangeListener; import net.rim.device.api.ui.UiApplication; import net.rim.device.api.ui.component.BasicEditField; import net.rim.device.api.ui.component.ButtonField; import net.rim.device.api.ui.component.CheckboxField; import net.rim.device.api.ui.component.Dialog; import net.rim.device.api.ui.component.LabelField; import net.rim.device.api.ui.component.ObjectChoiceField; import net.rim.device.api.ui.component.SeparatorField; import net.rim.device.api.ui.container.MainScreen; /** * Screen that allows user to type in lat/lon pairs and see the reverse geocoded * result along with other attributes of the location found. */ public final class ReverseGeocodeScreen extends MainScreen implements FieldChangeListener, ServerExchangeCallback { private final BasicEditField _editFieldLatitude; private final BasicEditField _editFieldLongitude; private final BasicEditField _bearingEditField; private final ButtonField _searchButton; private final ObjectChoiceField _choiceField; private final LabelField _resultsField; private final CheckboxField _blockingCheckBox; private final AdminChoice[] choices = new AdminChoice[] { new AdminChoice("Address", ReverseGeocodeExchange.ADDRESS), new AdminChoice("Country", ReverseGeocodeExchange.COUNTRY), new AdminChoice("Province/State", ReverseGeocodeExchange.PROVINCE_STATE), new AdminChoice("City", ReverseGeocodeExchange.CITY), new AdminChoice("Postal Code", ReverseGeocodeExchange.POSTAL), new AdminChoice("Out Of Bounds", 100), new AdminChoice("Below Bounds", -100) }; /** * Creates a new ReverseGeocodeScreen object and initializes UI elements */ public ReverseGeocodeScreen() { setTitle("Reverse Geocode"); _editFieldLatitude = new BasicEditField("Latitude: ", ""); _editFieldLongitude = new BasicEditField("Longitude: ", ""); _blockingCheckBox = new CheckboxField("Blocking:", false); _bearingEditField = new BasicEditField("Bearing: ", "-1", 4, BasicEditField.FILTER_INTEGER); add(_editFieldLatitude); add(_editFieldLongitude); add(_blockingCheckBox); add(_bearingEditField); _choiceField = new ObjectChoiceField("Admin Level:", choices, 0); add(_choiceField); _searchButton = new ButtonField("Search"); _searchButton.setChangeListener(this); add(_searchButton); add(new SeparatorField()); _resultsField = new LabelField(); add(_resultsField); } /** * @see net.rim.device.api.ui.container.MainScreen#onSavePrompt() */ protected boolean onSavePrompt() { // Prevent the save dialog from being displayed return true; } /** * @see net.rim.device.api.ui.FieldChangeListener#fieldChanged(Field, int) */ public void fieldChanged(final Field field, final int actionId) { if (field == _searchButton) { _resultsField.setText(""); final String lat = _editFieldLatitude.getText().trim(); final String lon = _editFieldLongitude.getText().trim(); if (lat.length() > 0 && lon.length() > 0) { try { final MapPoint origin = new MapPoint(Float.parseFloat(lat), Float .parseFloat(lon)); final AdminChoice choice = (AdminChoice) _choiceField.getChoice(_choiceField .getSelectedIndex()); final ReverseGeocoder reverseGeocoder = ReverseGeocoder.getInstance(); if (_blockingCheckBox.getChecked()) { // We are making a blocking request, should not be // called on event thread. final Thread t = new Thread(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { try { // This will check the cache first before // making // a request to the server. Passing null as // the // first argument to reverseGeocode() // results in // a blocking call. final ReverseGeocodeExchange ex = reverseGeocoder .reverseGeocode( null, origin, choice.getValue(), Integer.parseInt(_bearingEditField .getText()), 0); UiApplication.getUiApplication() .invokeLater(new Runnable() { /** * @see java.lang.Runnable#run() */ public void run() { _resultsField .setText("Blocking method"); } }); // In this case we did not provide a // callback so we need to initiate // the processing of the reverse geocoding // result ourselves. if (ex.getExceptionList().size() == 0) { requestSuccess(ex); } else { requestFailure(ex); } } catch (final ReverseGeocodeException rge) { GeocodeDemo.errorDialog(rge.toString()); } } }); t.start(); } else { try { // This will check the cache first before making // a request to the server. ReverseGeocoder.getInstance().reverseGeocode( this, origin, choice.getValue(), Integer.parseInt(_bearingEditField .getText()), 0); _resultsField.setText("Non-blocking method"); } catch (final ReverseGeocodeException rge) { GeocodeDemo.errorDialog(rge.toString()); } } } catch (final NumberFormatException nfe) { GeocodeDemo.errorDialog(nfe.toString()); } } else { Dialog.alert("Please enter both latitude and longitude coordinates"); } } } /** * @see net.rim.device.api.lbs.maps.server.ServerExchangeCallback#requestSuccess(ServerExchange) */ public void requestSuccess(final ServerExchange exchange) { // Display results in the event of a successful request. if (exchange instanceof ReverseGeocodeExchange) { final ReverseGeocodeExchange reverseGeocodeExchange = (ReverseGeocodeExchange) exchange; final Vector results = reverseGeocodeExchange.getResults(); final StringBuffer text = new StringBuffer(); for (int i = 0; i < results.size(); i++) { text.append(GeocodeDemo.composeLocation((MapLocation) results .elementAt(i))); } synchronized (Application.getEventLock()) { _resultsField.setText(_resultsField.getText() + '\n' + text.toString()); } } } /** * @see net.rim.device.api.lbs.maps.server.ServerExchangeCallback#requestFailure(ServerExchange) */ public void requestFailure(final ServerExchange exchange) { // Display any exceptions that were thrown in the event // of a request failure. final Vector exList = exchange.getExceptionList(); final StringBuffer buffer = new StringBuffer(); for (int i = 0; i < exList.size(); i++) { final Exception ex = (Exception) exList.elementAt(i); if (buffer.length() == 0) { buffer.append("Exception List").append('\n'); } if (ex instanceof ReverseGeocodeException) { final ReverseGeocodeException rgex = (ReverseGeocodeException) ex; buffer.append( " ReverseGeocode Exception code: " + rgex.getErrorCode()).append('\n'); } else { buffer.append(" Exception: " + ex).append('\n'); } } synchronized (Application.getEventLock()) { _resultsField.setText(_resultsField.getText() + '\n' + buffer.toString()); } } /** * @see net.rim.device.api.lbs.maps.server.ServerExchangeCallback#requestHalted() */ public void requestHalted() { GeocodeDemo.errorDialog("Request halted"); } /** * Represents a choice of administration boundary level as defined in the * <code>net.rim.device.api.lbs.maps.server.exchangeReverseGeocodeExchange</code> * class. */ private final static class AdminChoice { private final String _name; private final int _value; public AdminChoice(final String name, final int value) { _name = name; _value = value; } /** * Retrieves the value associated with this AdminChoice object * * @return The value associated with this AdminChoice object */ public int getValue() { return _value; } /** * @see java.lang.Object#toString() */ public String toString() { // Return the name associated with this AdminChoice object return _name; } } }