Package com.rim.samples.device.gpsdemo

Source Code of com.rim.samples.device.gpsdemo.GPSDemo

/**
* GPSDemo.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.gpsdemo;

import java.util.Vector;

import javax.microedition.location.Criteria;
import javax.microedition.location.Location;
import javax.microedition.location.LocationException;
import javax.microedition.location.LocationListener;
import javax.microedition.location.LocationProvider;

import net.rim.device.api.command.Command;
import net.rim.device.api.command.CommandHandler;
import net.rim.device.api.command.ReadOnlyCommandMetadata;
import net.rim.device.api.gps.GPSInfo;
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.EditField;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.component.TextField;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.util.Persistable;
import net.rim.device.api.util.StringProvider;

/**
* This application acts as a simple travel computer, recording route
* coordinates, speed and altitude. Recording begins as soon as the application
* is invoked.
*/
public class GPSDemo extends UiApplication {
    // Represents the number of updates over which altitude is calculated, in
    // seconds
    private static final int GRADE_INTERVAL = 5;

    // com.rim.samples.device.gpsdemo.GPSDemo.ID
    private static final long ID = 0x5d459971bb15ae7aL;

    // Represents period of the position query, in seconds
    private static int _interval = 1;

    private static Vector _previousPoints;
    private static float[] _altitudes;
    private static float[] _horizontalDistances;
    private static PersistentObject _store;

    // Initialize or reload the persisted WayPoints
    static {
        _store = PersistentStore.getPersistentObject(ID);

        if (_store.getContents() == null) {
            _previousPoints = new Vector();
            _store.setContents(_previousPoints);
        }

        _previousPoints = (Vector) _store.getContents();
    }

    private long _startTime;
    private float _wayHorizontalDistance;
    private float _horizontalDistance;
    private float _verticalDistance;
    private double _latitude;
    private double _longitude;
    private final EditField _status;
    private LocationProvider _locationProvider;
    private final GPSDemoScreen _screen;

    /**
     * Entry point for application
     *
     * @param args
     *            Command line arguments (not used)
     */
    public static void main(final String[] args) {
        // Create a new instance of the application and make the currently
        // running thread the application's event dispatch thread.
        new GPSDemo().enterEventDispatcher();
    }

    /**
     * Create a new GPSDemo object
     */
    public GPSDemo() {
        // Used by WayPoints, represents the time since the last waypoint
        _startTime = System.currentTimeMillis();

        _altitudes = new float[GRADE_INTERVAL];
        _horizontalDistances = new float[GRADE_INTERVAL];

        _screen = new GPSDemoScreen();
        _screen.setTitle("GPS Demo");

        _status = new EditField(Field.NON_FOCUSABLE);
        _screen.add(_status);

        // Attempt to start the location listening thread
        if (startLocationUpdate()) {
            _screen.setState(_locationProvider.getState());
        }

        // Render the screen
        pushScreen(_screen);
    }

    /**
     * Update the GUI with the data just received
     *
     * @param msg
     *            The message to display
     */
    private void updateLocationScreen(final String msg) {
        invokeLater(new Runnable() {
            public void run() {
                _status.setText(msg);
            }
        });
    }

    /**
     * Invokes the Location API with Standalone criteria
     *
     * @return True if the <code>LocationProvider</code> was successfully
     *         started, false otherwise
     */
    private boolean startLocationUpdate() {
        boolean returnValue = false;

        if (!(GPSInfo.getDefaultGPSMode() == GPSInfo.GPS_MODE_NONE)) {
            try {
                final Criteria criteria = new Criteria();
                criteria.setCostAllowed(false);

                _locationProvider = LocationProvider.getInstance(criteria);

                if (_locationProvider != null) {
                    /*
                     * Only a single listener can be associated with a provider,
                     * and unsetting it involves the same call but with null.
                     * Therefore, there is no need to cache the listener
                     * instance request an update every second.
                     */
                    _locationProvider.setLocationListener(
                            new LocationListenerImpl(), _interval, -1, -1);
                    returnValue = true;
                } else {
                    invokeLater(new Runnable() {
                        public void run() {
                            Dialog.alert("Failed to obtain a location provider, exiting...");
                            System.exit(0);
                        }
                    });
                }

            } catch (final LocationException le) {
                invokeLater(new Runnable() {
                    public void run() {
                        Dialog.alert("Failed to instantiate LocationProvider object, exiting..."
                                + le.toString());
                        System.exit(0);
                    }
                });
            }
        } else {
            invokeLater(new Runnable() {
                public void run() {
                    Dialog.alert("GPS is not supported on this device, exiting...");
                    System.exit(0);
                }
            });
        }

        return returnValue;
    }

    /**
     * Marks a WayPoint in the persistent store. Calculations are based on all
     * data collected since the previous way point, or from the start of the
     * application if no previous WayPoints exist.
     */
    private void markPoint() {
        final long current = System.currentTimeMillis();
        final WayPoint point =
                new WayPoint(_latitude, _longitude, _startTime, current,
                        _wayHorizontalDistance, _verticalDistance);

        addWayPoint(point);

        // Reset the WayPoint variables
        _startTime = current;
        _wayHorizontalDistance = 0;
        _verticalDistance = 0;
    }

    /**
     * View the various saved WayPoints
     */
    private void viewPreviousPoints() {
        final PointScreen pointScreen = new PointScreen(_previousPoints);
        pushScreen(pointScreen);
    }

    /**
     * Adds a new WayPoint and commits the set of saved waypoints to persistent
     * store.
     *
     * @param point
     *            The WayPoint to add
     */
    private synchronized static void addWayPoint(final WayPoint point) {
        _previousPoints.addElement(point);
        commit();
    }

    /**
     * Removes a WayPoint from the set of saved points and commits the modifed
     * set to persistent store
     *
     * @param point
     *            The WayPoint to remove
     */
    synchronized static void removeWayPoint(final WayPoint point) {
        _previousPoints.removeElement(point);
        commit();
    }

    /**
     * Commits the WayPoint set to persistent store
     */
    private static void commit() {
        _store.setContents(_previousPoints);
        _store.commit();
    }

    /**
     * Implementation of the LocationListener interface. Listens for updates to
     * the device location and displays the results.
     */
    private class LocationListenerImpl implements LocationListener {

        /**
         * @see javax.microedition.location.LocationListener#locationUpdated(LocationProvider,Location)
         */
        public void locationUpdated(final LocationProvider provider,
                final Location location) {
            if (location.isValid()) {
                final float heading = location.getCourse();
                _longitude = location.getQualifiedCoordinates().getLongitude();
                _latitude = location.getQualifiedCoordinates().getLatitude();
                final float altitude =
                        location.getQualifiedCoordinates().getAltitude();
                final float speed = location.getSpeed();

                // Horizontal distance for current Location
                final float horizontalDistance = speed * _interval;
                _horizontalDistance += horizontalDistance;

                // Horizontal distance for WayPoint
                _wayHorizontalDistance += horizontalDistance;

                // Distance over the current interval
                float totalDist = 0;

                // Moving average grade
                for (int i = 0; i < GRADE_INTERVAL - 1; ++i) {
                    _altitudes[i] = _altitudes[i + 1];
                    _horizontalDistances[i] = _horizontalDistances[i + 1];
                    totalDist = totalDist + _horizontalDistances[i];
                }

                _altitudes[GRADE_INTERVAL - 1] = altitude;
                _horizontalDistances[GRADE_INTERVAL - 1] = speed * _interval;
                totalDist =
                        totalDist + _horizontalDistances[GRADE_INTERVAL - 1];
                final float grade =
                        totalDist == 0.0F ? Float.NaN
                                : (_altitudes[4] - _altitudes[0]) * 100
                                        / totalDist;

                // Running total of the vertical distance gain
                final float altGain =
                        _altitudes[GRADE_INTERVAL - 1]
                                - _altitudes[GRADE_INTERVAL - 2];

                if (altGain > 0) {
                    _verticalDistance = _verticalDistance + altGain;
                }

                // Information to be displayed on the device
                final StringBuffer sb = new StringBuffer();
                sb.append("Longitude: ");
                sb.append(_longitude);
                sb.append("\n");
                sb.append("Latitude: ");
                sb.append(_latitude);
                sb.append("\n");
                sb.append("Altitude: ");
                sb.append(altitude);
                sb.append(" m");
                sb.append("\n");
                sb.append("Heading relative to true north: ");
                sb.append(heading);
                sb.append("\n");
                sb.append("Speed : ");
                sb.append(speed);
                sb.append(" m/s");
                sb.append("\n");
                sb.append("Grade : ");
                if (Float.isNaN(grade)) {
                    sb.append(" Not available");
                } else {
                    sb.append(grade + " %");
                }

                GPSDemo.this.updateLocationScreen(sb.toString());
            }
        }

        /**
         * @see javax.microedition.location.LocationListener#providerStateChanged(LocationProvider,
         *      int)
         */
        public void providerStateChanged(final LocationProvider provider,
                final int newState) {
            if (newState == LocationProvider.TEMPORARILY_UNAVAILABLE) {
                provider.reset();
            }
            _screen.setState(newState);
        }
    }

    /**
     * The main screen to display the current GPS information
     */
    private final class GPSDemoScreen extends MainScreen {
        TextField _statusTextField;

        /**
         * Create a new GPSDemoScreen object
         */
        GPSDemoScreen() {
            // Initialize UI
            _statusTextField = new TextField(Field.NON_FOCUSABLE);
            _statusTextField.setLabel("GPS Status: ");
            add(_statusTextField);
            final RichTextField instructions =
                    new RichTextField("Waiting for location update...",
                            Field.NON_FOCUSABLE);
            add(instructions);

            // Menu Item to add the current location to the list of WayPoints
            final MenuItem markWayPoint =
                    new MenuItem(new StringProvider("Mark waypoint"), 0x230010,
                            0);
            markWayPoint.setCommand(new Command(new CommandHandler() {
                /**
                 * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
                 *      Object)
                 */
                public void execute(final ReadOnlyCommandMetadata metadata,
                        final Object context) {
                    GPSDemo.this.markPoint();
                }
            }));

            // Menu Item to view the marked WayPoints
            final MenuItem viewWayPoints =
                    new MenuItem(new StringProvider("View waypoints"),
                            0x230020, 1);
            viewWayPoints.setCommand(new Command(new CommandHandler() {
                /**
                 * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
                 *      Object)
                 */
                public void execute(final ReadOnlyCommandMetadata metadata,
                        final Object context) {
                    GPSDemo.this.viewPreviousPoints();
                }
            }));
            addMenuItem(markWayPoint);
            addMenuItem(viewWayPoints);
        }

        /**
         * Display the state of the GPS service
         *
         * @param newState
         *            The state to display
         */
        public void setState(final int newState) {
            UiApplication.getUiApplication().invokeLater(new Runnable() {
                /**
                 * @see java.lang.Runnable#run()
                 */
                public void run() {
                    switch (newState) {
                    case LocationProvider.AVAILABLE:
                        _statusTextField.setText("Available");
                        break;
                    case LocationProvider.OUT_OF_SERVICE:
                        _statusTextField.setText("Out of Service");
                        break;
                    case LocationProvider.TEMPORARILY_UNAVAILABLE:
                        _statusTextField.setText("Temporarily Unavailable");
                        break;
                    }
                }
            });
        }

        /**
         * @see net.rim.device.api.ui.Screen#close()
         */
        public void close() {
            if (_locationProvider != null) {
                _locationProvider.reset();
                _locationProvider.setLocationListener(null, -1, -1, -1);
            }

            super.close();
        }
    }

    /**
     * A class to represent a way point, a marker on a journey or a point of
     * interest.
     */
    static class WayPoint implements Persistable {
        long _startTime;
        long _endTime;
        double _latitude;
        double _longitude;
        float _distance;
        float _verticalDistance;

        /**
         * Creates a new WayPoint object
         *
         * @param latitude
         *            Latitude of waypoint
         * @param longitude
         *            Longitude of waypoint
         * @param startTime
         *            Time at start of update
         * @param endTime
         *            Time at end of update
         * @param distance
         *            Distance travelled
         * @param verticalDistance
         *            Vertical distance travelled
         */
        WayPoint(final double latitude, final double longitude,
                final long startTime, final long endTime, final float distance,
                final float verticalDistance) {
            _startTime = startTime;
            _endTime = endTime;
            _distance = distance;
            _verticalDistance = verticalDistance;
            _latitude = latitude;
            _longitude = longitude;
        }
    }
}
TOP

Related Classes of com.rim.samples.device.gpsdemo.GPSDemo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.