BlackBerry 应用程序开发者指南 第一卷:基础–第11章 使用位置信息

11

             第11 使用位置信息

位置API

代码实例

位置API

位置API(javax.microedition.location)允许应用程序获取BlackBerry设备的全球定位系统(GPS)位置。GPS位置是BlackBerry设备中的地理坐标(经度和纬度)。根据使用

的位置方法,应用程序也可以获得BlackBerry设备的速度,方向,以及路线。

获得GPS位置的方法

方法

常数

描述

Cellsite

GPS_AID_MODE_CELLSITE

本方法使用活动的蜂窝(cellsite 塔的GPS位置来提供第一个有序GPS信息。它提供最不精确的位置信息;虽说如此,但它是最快的位置模式。

:如果使用本模式,将得不到方向,路径,以及速度获。这个位置方法需要网络连接以及运营商的支持。

Assisted

GPS_AID_MODE_ASSIST

本方法使用网络为设备的芯片提供天文卫星数据。它比自动模式提供GPS位置更快些,并且比蜂窝模式更精确。

:本位置方法需要网络连接以及运营商的支持。

Autonomous

GPS_AID_MODE_AUTONOMOUS

本方法在没有网络的协助下使用BlackBerry上的GPS芯片。自动模式提供第一个GPS位置最慢。

为选择GPS位置方法指定原则

通过创建一个javax.microedition.location.Criteria类,调用合适的set方法,然后传递这个LocationProvider.getInstance()实例来指定需要的原则.

:为创建一个缺省规则的LocationProvider实例,调用LocationProvider.getInstance(null).

Criteria criteria = new Criteria();

// Allow cost.

criteria.setCostAllowed(true);

// Require a horizontal accuracy of 50 metres.

criteria.setHorizontalAccuracy(50);

// Require a vertical accuracy of 50 metres.

criteria.setVerticalAccuracy(50);

LocationProvider provider = LocationProvider.getInstance(criteria);

选择GPS位置方法的原则

建议的GPS位置方法

水平精确度

垂直精确度

费用

耗电量

自动

需要

需要

不允许

不可用

自动

需要

需要

允许

低,一般或没有需求

第一次修正:协助

后续修正:自动

需要

需要

允许

自动

不需要

不需要

不允许

一般,高或没有需求

协助

不需要

不需要

允许

一般,或没有需求

第一次修正:协助

后续修正:自动

不需要

不需要

允许

蜂窝

不需要

不需要

允许

:如果BlackBerry无线设备有一个卫星的障碍视图,GPS可能不可用。当设备在室内或被建筑物,树,以及密云围绕,这是有可能发生的。

获取BlackBerry设备的位置

第一次获取BlackBerry设备位置所花的时间依赖多方面的因素,例如选择的GPS模式,GPS的信号强度。在自动模式中,典型的至少需要2分钟,在协助模式。典型的是至少需要30秒。

如果GPS修正在10秒的请求内发生后,连续请求的平均响应时间为12秒,这取决位置条件。

:如果你使用了一个可能花费用户资费的位置方法,不要经常查询BlackBerry设备的位置。

为了指定一个需要的响应事件,调用Criteaia.setPreferredReponseTime(),以毫秒为单位提供需要的时间。

获取BlackBerry设备的位置

调用LocationProvider.getLocation(int),提供一个以毫秒为单位的超时时间。

:如果LocationProvider.getLocation(int)早事件线程调用,LocationExcept会抛出。

try {

    // Specify -1 to have the implementation use its default timeout value

    // for this provider.

    Location location = provider.getLocation(-1);

}

catch (Exception e) {

    // handle LocationException, InterruptedException, SecurityException

    // and IllegalArgumentException

}

获取位置信息

Location类提供方法来获取位置信息,例如GPS坐标,以及路径。

RIM的实现不支持文本地址信息。结果,getAddressInfo()方法会空。

QualifiedCoordinates coordinates = location.getQualifiedCoordinates;

float speed = location.getSpeed();

float course = location.getCourse();

注册一个位置监听者

实现LocationListener方法。调用LocationProvider.setLocationListener()注册你的实现。

:一个位置监听者可以与一个指定的位置提供者项关联。应用程序在一个独立的线程上典型用来监听更新。


import javax.microedition.LocationProvider.*;

 

public class SampleLocationApp {

    public static void main (string[] Args) {

       // …

       provider.setLocationListener(new SampleLocationListener(), 0, 60, 60);

       }

    }

 

class SampleLocationListener implements LocationListener {

    void locationUpdated(LocationProvider provider, Location location)

    {

    // Respond to the updated location.

    // If the application registered the location listener with an interval of

    // 0, the location provider does not provide location updates.

    }

   

    void providerStateChanged(LocationProvider provider, int newState) {

       switch (newState) {

         case LocationProvider.AVAILABLE :

             // The location provider is available.

             break;

         case LocationProvider.OUT_OF_SERVICE :

             // The location provider is permanently unavailable.

             // Consider cancelling the location listener by calling

             // provider.setLocationListener() with null as the listener.

             break;

        case LocationProvider.TEMPORARILY_UNAVAILABLE :

            // The location provider is temporarily unavailable.

            break;

            }

       }

}


 

代码实例


例:GPSDemo.java

/**

* A GPS sample application using the JSR 179 APIs.

*

* Copyright (C) 2005 Research In Motion Limited.

*/

package com.rim.samples.docs.gpsdemo;

import net.rim.device.api.ui.*;

import net.rim.device.api.ui.component.*;

import net.rim.device.api.ui.container.*;

import com.rim.samples.docs.baseapp.*;

import net.rim.device.api.io.*;

import net.rim.device.api.system.*;

import net.rim.device.api.i18n.*;

import javax.microedition.io.*;

import java.util.*;

import java.io.*;

import javax.microedition.location.*;

import net.rim.device.api.util.*;

import com.rim.samples.docs.resource.*;

 

/* 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 BaseApp implements GPSDemoResResource

{

    // Constants. —————————————————————-

    // The number of updates in seconds over which the altitude is calculated.

    private static final int GRADE_INTERVAL=5;

    // com.rim.samples.docs.gpsdemo.GPSDemo.ID

    private static final long ID = 0x4e94d9bc9c54fed3L;

    private static final int CAPTURE_INTERVAL=10;

    // Statics. ——————————————————————

    private static ResourceBundle _resources = ResourceBundle.getBundle(GPSDemoResResource.BUNDLE_ID, GPSDemoResResource.BUNDLE_NAME);

    // The 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 persistent store.

    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 ListField _listField;

    private EditField _status;

    private StringBuffer _messageString;

    private String _oldmessageString;

    private LocationProvider _locationProvider;

    /* Instantiate the new application object and enter the event loop.

     * @param args unsupported. no args are supported for this application

     */

    public static void main(String[] args)

    {

       new GPSDemo().enterEventDispatcher();

    }

    // Constructors. ————————————————————-

    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];

       _messageString= new StringBuffer();

       MainScreen screen = new MainScreen();

       screen.setTitle(new LabelField(_resources.getString(GPSDEMO_TITLE), LabelField.USE_ALL_WIDTH));

       _status = new EditField();

       screen.add(_status);

       screen.addKeyListener(this);

       screen.addTrackwheelListener(this);

       // Start the GPS thread that listens for updates.

       startLocationUpdate();

       // Render our screen.

       pushScreen(screen);

    }

 

    /* Update the GUI with the data just received.

     */

    private void updateLocationScreen(final String msg)

    {

       invokeLater(new Runnable()

       {

           public void run()

           {

              _status.setText(msg);

           }

       });

    }

 

    // Menu items. —————————————————————

    // Cache the markwaypoint menu item for reuse.

    private MenuItem _markWayPoint = new MenuItem(_resources, GPSDEMO_MENUITEM_MARKWAYPOINT, 110, 10)

    {

       public void run()

       {

           GPSDemo.this.markPoint();

       }

    };

    // Cache the view waypoints menu item for reuse.

   private MenuItem _viewWayPoints = new MenuItem(_resources, GPSDEMO_MENUITEM_VIEWWAYPOINTS, 110, 10)

    {

       public void run()

       {

           GPSDemo.this.viewPreviousPoints();

       }

    };

    // Cache the close menu item for reuse.

 

    private MenuItem _close = new MenuItem(_resources, GPSDEMO_MENUITEM_CLOSE, 110, 10)

    {

       public void run()

       {

           System.exit(0);

       }

    };

    protected void makeMenu(Menu menu, int instance)

    {

       menu.add( _markWayPoint );

       menu.add( _viewWayPoints );

       menu.add( _close );

       menu.addSeparator();

       super.makeMenu(menu, instance);

    }

    /* Invokes the Location API with the default criteria.

 

     */

    private void startLocationUpdate()

    {

       try

       {

           _locationProvider = LocationProvider.getInstance(null);

           if ( _locationProvider == null )

           {

              Dialog.alert("GPS is not supported on this platform, exiting…");

              System.exit(0);

           }

           // A single listener can be associated with a provider,

           // and unsetting it involves the same call but with null,

           // so there is no need to cache the listener instance.

           // Request an update every second.

           _locationProvider.setLocationListener(new LocationListenerImpl(), _interval, 1, 1);

       }

       catch (LocationException le)

       {

           System.err.println("Failed to add a location listener. Exiting…");

           System.err.println(le);

           System.exit(0);

       }

    }

 

    /* Marks a point 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()

    {

       long current = System.currentTimeMillis();

       WayPoint p= new WayPoint(_startTime, current, _wayHorizontalDistance, _verticalDistance);

       addWayPoint(p);

       // Reset the waypoint variables.

       _startTime = current;

       _wayHorizontalDistance = 0;

       _verticalDistance = 0;

    }

 

    // View the saved waypoints.

    private void viewPreviousPoints()

    {

       PointScreen pointScreen = new PointScreen(_previousPoints, _resources);

       pushScreen(pointScreen);

    }

 

    // Called by the framework when this application is losing focus.

    protected void onExit()

    {

       if ( _locationProvider != null )

       {

           _locationProvider.reset();

           _locationProvider.setLocationListener(null, -1, -1, -1);

       }

    }

   

    /* Adds a new WayPoint and commits the set of saved waypoints

     * to flash memory.

     * @param p The point to add.

     */

    /*package*/

    synchronized static void addWayPoint(WayPoint p)

    {

       _previousPoints.addElement(p);

       commit();

    }

 

    /* Removes a waypoint from the set of saved points and

     * commits the modifed set to flash memory.

     * @param p the point to remove

     */

    /*package*/ synchronized static void removeWayPoint(WayPoint p)

              {

                  _previousPoints.removeElement(p);

                  commit();

              }

 

    // Commit the waypoint set to flash memory.

    private static void commit()

    {

       _store.setContents(_previousPoints);

       _store.commit();

    }

 

    /*

     * Implementation of the LocationListener interface.

     */

    private class LocationListenerImpl implements LocationListener

    {

       // Members. ————————————————————–

       private int captureCount;

       // Methods. ————————————————————–

       public void locationUpdated(LocationProvider provider, Location location)

       {

           if(location.isValid())

           {

              float heading = location.getCourse();

              double longitude = location.getQualifiedCoordinates().getLongitude();

              double latitude = location.getQualifiedCoordinates().getLatitude();

              float altitude = location.getQualifiedCoordinates().getAltitude();

              float speed = location.getSpeed();

              // Horizontal distance.

              float horizontalDistance = speed * _interval;

              _horizontalDistance += horizontalDistance;

              // Horizontal distance for this 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];

              float grade = (_altitudes[4] – _altitudes[0]) * 100/totalDist;

              // Running total of the vertical distance gain.

              float altGain = _altitudes[GRADE_INTERVAL-1] – _altitudes[GRADE_INTERVAL-2];

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

              captureCount += _interval;

              // If we’re mod zero then it’s time to record this data.

              captureCount %= CAPTURE_INTERVAL;

              // Information to display on the device.

              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());

           }

       }

       public void providerStateChanged(LocationProvider provider, int newState)

        {

           // No operation defined.

       }

    }

    /* WayPoint describes a way point, a marker on a journey or point of interest.

     * WayPoints are persistable.

     * package

     */

    static class WayPoint implements Persistable

    {

       public long _startTime;

       public long _endTime;

       public float _distance;

       public float _verticalDistance;

       public WayPoint(long startTime,long endTime,float distance,float verticalDistance)

       {

           _startTime=startTime;

           _endTime=endTime;

           _distance=distance;

           _verticalDistance=verticalDistance;

       }

    }

}

 

public float _verticalDistance;

public WayPoint(long startTime,long endTime,float distance,float verticalDistance)

{

    _startTime=startTime;

    _endTime=endTime;

    _distance=distance;

    _verticalDistance=verticalDistance;

}

}

 

 

/*PointScreen.java

Copyright (C) 2005 Research In Motion Limited.

*/

package com.rim.samples.docs.gpsdemo;

import net.rim.device.api.ui.*;

import net.rim.device.api.ui.component.*;

import net.rim.device.api.ui.container.*;

import com.rim.samples.docs.baseapp.*;

import net.rim.device.api.io.*;

import net.rim.device.api.system.*;

import com.rim.samples.docs.resource.*;

import net.rim.device.api.i18n.*;

import javax.microedition.io.*;

import java.util.*;

import java.io.*;

import javax.microedition.location.*;

import com.rim.samples.docs.gpsdemo.GPSDemo.WayPoint;

import com.rim.samples.docs.resource.*;

 

/*

 * PointScreen is a screen derivative that renders the saved WayPoints.

 * */

public class PointScreen extends MainScreen implements ListFieldCallback, GPSDemoResResource

{

    private Vector _points;

    private ListField _listField;

    private ResourceBundle _resources;

    public float _verticalDistance;

    public WayPoint(long startTime,long endTime,float distance,float verticalDistance)

    {

       _startTime=startTime;

       _endTime=endTime;

       _distance=distance;

       _verticalDistance=verticalDistance;

    }

}

 

/*

 * PointScreen.java

Copyright (C) 2005 Research In Motion Limited.

*/

package com.rim.samples.docs.gpsdemo;

import net.rim.device.api.ui.*;

import net.rim.device.api.ui.component.*;

import net.rim.device.api.ui.container.*;

import com.rim.samples.docs.baseapp.*;

import net.rim.device.api.io.*;

import net.rim.device.api.system.*;

import com.rim.samples.docs.resource.*;

import net.rim.device.api.i18n.*;

import javax.microedition.io.*;

import java.util.*;

import java.io.*;

import javax.microedition.location.*;

import com.rim.samples.docs.gpsdemo.GPSDemo.WayPoint;

import com.rim.samples.docs.resource.*;

 

/*

 * PointScreen is a screen derivative that renders the saved WayPoints.

 */

public class PointScreen extends MainScreen implements ListFieldCallback, GPSDemoResResource

{

    private Vector _points;

    private ListField _listField;

    private ResourceBundle _resources;

}

    // Menu items. —————————————————————

private class ViewPointAction extends MenuItem

{

    private int _index;

    public ViewPointAction( int index )

    {

       super(PointScreen.this._resources.getString(GPSDEMO_POINTSCREEN_MENUITEM_VIEW), 100000, 10);

       _index = index;

    }

    public void run()

    {

       ViewScreen screen = new ViewScreen( (WayPoint)_points.elementAt(_index),

           index, _resources );

       UiApplication.getUiApplication().pushModalScreen( screen );

    }

}

private class DeletePointAction extends MenuItem

{

    private int _index;

    public DeletePointAction( int index )

    {

       super(PointScreen.this._resources.getString(GPSDEMO_POINTSCREEN_MENUITEM_DELETE), 100000, 10);

       _index = index;

    }

    public void run()

    {

       GPSDemo.removeWayPoint((WayPoint)_points.elementAt(_index));

    }

}

protected void makeMenu(Menu menu, int instance)

{

    if( _points.size() > 0 )

    {

       ViewPointAction viewPointAction = new ViewPointAction(

              listField.getSelectedIndex() );

       menu.add( viewPointAction );

       menu.addSeparator();

       DeletePointAction deletePointAction =

           new DeletePointAction(

                  listField.getSelectedIndex() );

       menu.add( deletePointAction );

       }

    super.makeMenu(menu, instance);

    }

/*

 * Renders a particular Waypoint.

 */

private static class ViewScreen extends MainScreen

{

    private ResourceBundle _resources;

    private MenuItem _cancel;

    public ViewScreen(WayPoint point, int count, ResourceBundle resources)

    {

       super();

       _resources = resources;

       LabelField title = new LabelField(resources.getString(GPSDEMO_VIEWSCREEN_TITLE) + count,

           LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);

       setTitle(title);

       Date date = new Date(point._startTime);

       String startTime = date.toString();

       date = new Date(point._endTime);

       String endTime = date.toString();

       float avgSpeed = point._distance/(point._endTime – point._startTime);

      add(new BasicEditField(resources.getString(GPSDEMO_VIEWSCREEN_STARTFIELD), startTime, 30, Field.READONLY));

       add(new BasicEditField(resources.getString(GPSDEMO_VIEWSCREEN_ENDFIELD), endTime, 30, Field.READONLY));

       add(new BasicEditField(resources.getString(GPSDEMO_VIEWSCREEN_HORIZONTALDISTANCEFIELD), Float.toString(point._distance), 30, Field.READONLY));

       add(new BasicEditField(resources.getString(GPSDEMO_VIEWSCREEN_VERTICALDISTANCEFIELD), Float.toString(point._verticalDistance), 30, Field.READONLY));

       add(new BasicEditField(resources.getString(GPSDEMO_VIEWSCREEN_AVESPEEDFIELD), Float.toString(avgSpeed), 30, Field.READONLY));

    }

       private class CancelMenuItem extends MenuItem

    {

       public CancelMenuItem()

       {

           // Reuse an identical resource below.

           super(ViewScreen.this._resources, GPSDEMO_OPTIONSSCREEN_MENUITEM_CANCEL, 300000, 10);

       }

       public void run()

       {

           UiApplication uiapp = UiApplication.getUiApplication();

           uiapp.popScreen(ViewScreen.this);

       }

    };

   

    protected void makeMenu( Menu menu, int instance )

    {

       if ( _cancel == null ) _cancel = new CancelMenuItem(); // Create on demand.

       menu.add(_cancel);

       super.makeMenu(menu, instance);

    }

}

}



发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注