BlackBerry 应用程序开发者指南 第一卷:基础--第11章 使用位置信息
作者:Confach 发表于2006-04-28 21:48
版权信息:可以任意转载, 转载时请务必以超链接形式标明文章原始出处 和作者信息.
http://www.cnblogs.com/confach/articles/387915.html
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秒的请求内发生后,连续请求的平均响应时间为1到2秒,这取决位置条件。
注:如果你使用了一个可能花费用户资费的位置方法,不要经常查询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();
       }
    };
    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);
    }
     */
    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);
    }
}
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号