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