BLACKBERRY

NAVBUILDER INSIDE LBS SDK

Blackberry icon
GETTING STARTED GUIDE

1          Executive Summary

1.1       Introduction

This Getting Started Guide provides the basic information you need to create BlackBerry® mobile device applications with NAVBuilder Inside (NBI). After reading this document, you should be able to create a simple application that uses NBI libraries to display a map of the area around your current location.

1.2       Assumptions

This document assumes that you are familiar with the BlackBerry operating system and the BlackBerry JDE. Familiarity with the Eclipse development environment and installing the BlackBerry SDK into Eclipse is recommended, but not required.

 

The NBI library for BlackBerry was built using the RIM JDE v4.7.0 and the Java compiler v1.6.0_20.

1.3       What’s New in Phase 2

-          Mobile Coupons – Added functionality for mobile coupons, including the ability to retrieve coupons and retailers based on location, and for allowing redemption at the retailer mobile website.

-          Custom Layers – Added the ability to add 3rd party map tiles to the map view, including base and overlay map tiles.  Also added support for multiple POI (Point Of Interest) layers and automatic POI layers.

-          Cross-Carrier Support – The NBI library now works on all carriers.

2          Getting Started

This section explains how to add NBI libraries to your project and integrate NBI into your BlackBerry project.

2.1       Installing NBI files

This section explains how to add NBI libraries to your project.  If necessary, refer to section 5 for instructions to create a project.

2.1.1    Installing the nbi.jar File

The nbi.jar file contains the NBI library, which includes both the MapKit and the LocationKit.

To install the nbi.jar file

1.      In your project's directory, create a directory named lib.

2.      Copy the nbi.jar file into the lib directory.

3.      In the BlackBerry JDE, select Add File to Project from the Project menu.

4.      Change the Files of Type files to All Files to see the nbi.jar file.

5.      Select the nbi.jar file in the lib directory, and then click Open.

You should see the nbi.jar file in the list of files.

2.2       Create an Application-specific store

The Blackberry persistent BBStore, which is used by the MapKit cache requires a unique class name to work correctly. Since NBI is an SDK, it’s not possible for us to do it transparently inside the library. Instead, the host application has to do a bit of work as described below:

  • Create a persistent object:

//Persistent object required by NBI

public class YourAppNameAppCache extends Hashtable implements Persistable {

}

  • At runtime, load the class as follows:

private Hashtable getPersistableHastable() throws NimStoreException {

    Hashtable ht = null;

    UiApplication uia = UiApplication.getUiApplication();

    String cacheClassName = uia.getClass().getName() + "Cache";

    try {

        Class cacheClass = Class.forName(cacheClassName);

        try {

            ht = (Hashtable) cacheClass.newInstance();

            } catch (InstantiationException e) {

            e.printStackTrace();

            throw new NimStoreException(

            "InstantiationException trying to instantiate an instance of " +

            cacheClassName + ".");

            } catch (IllegalAccessException e) {

            e.printStackTrace();

            throw new NimStoreException(

            "IllegalAccessException trying to access " +

            cacheClassName + ".");

        }

        } catch (ClassNotFoundException e) {

        e.printStackTrace();

        throw new NimStoreException(

        "ClassNotFoundException trying to dynamically load class " +

        cacheClassName + ".");      }

    return ht;

}

2.3       Create an LBSManager Class

To be able to use NBI services, you must create an NBIContext object. To use the LocationKit, you must also create a LocationProvider object. This can be done by creating a class called LBSManager (or you can name it anything you want). The following example shows how to create the LBSManager class:

Note:

You should have been given an API key that is required to communicate with NBI servers. The API key should be specified at the <fill in your API Key here> location shown in the following code sample.

import com.nbi.common.NBIContext;

import com.nbi.location.LocationProvider;

public class LBSManager {

    public static final String API_KEY = "<fill in your API Key here>";  

    private static NBIContext sNBIContext;

    private static String sCurrentCredential;

    private static LocationProvider sLocationProvider = null;  

    public static void init() {

        LBSManager.init(API_KEY);

    }  

    public static void init(String credential) {

        if (sNBIContext == null)

            sNBIContext = new NBIContext(credential, null);

        sCurrentCredential = credential;

        try {

            sLocationProvider = LocationProvider.getInstance(sNBIContext, null);

        } catch(Exception e) {

            e = null;

        }

    }  

    public static void destroy() {

        sNBIContext.destroy();

        sNBIContext = null;

    }  

    public static NBIContext getNBIContext() {

        return sNBIContext;

    }  

    public static LocationProvider getLocationProvider() {

        return sLocationProvider;

    }

}

The LBSManager creates the required objects to communicate with NBI servers. Several methods require these objects to work correctly.

3          Using the MapField Class

This section explains how to implement a MapField in a sample application.

3.1       Using the MapField in Your Code

You must first create the NBIContext object to display the MapWidget. Then, create a MapConfiguration object, which is used to create the MapField object. The following code example displays the MapField object.

public class MainMapView extends MainScreen {

    private NBIContext nbiContext;

    private MapField mapField;

    private MapConfiguration mapConfiguration;

    // creates a new MainMapView object

    MainMapView() {

        // hide the title bar

        setTitle((LabelField)null);

        // the LBSManager contains data structures used by the NBI library

        // so we must initialize the variables when we launch the application

        LBSManager.init();

        nbiContext = LBSManager.getNBIContext();

        // create the map configuration

        Location location = new Location();

        location.setLatitude(33.5598);

        location.setLongitude(-117.72884);

        MapConfiguration mapConfiguration = MapConfiguration.defaultConfigurationFromLocation(nbiContext, location);

        mapConfiguration.setZoomButtons(true);

        // display the map

        mapField = new MapField(mapConfiguration);

        add(mapField);

    }

}

4          Using the LocationProvider Class

The following section describes how to implement the LocationProvider class.

4.1       Updating Your Activity Class to Handle Callbacks

The LocationProvider class provides functionality to get your current location. These calls are made asynchronously and they call back to your listener class with the results. To change your MainScreen class to handle these callbacks, you must allow your class to implement the LocationListener class.

You must import the LocationListener class in your source code:

import com.nbi.location.LocationListener;

Your MainScreen class must implement LocationListener:

public class MainMapView extends MainScreen implements LocationListener { … }

By implementing this class, you must define three methods in your class:

public void locationUpdated(Location location)

public void onLocationError(int errCode)

public void providerStateChanged(int newState)

The locationUpdated method will be called after a successful location fix by the LocationListener object.

The following example shows the MainScreen class that implements the LocationListener class:

...

import com.nbi.location.LocationListener;

public class MainMapView extends MainScreen implements LocationListener {

....

    public void locationUpdated(Location location) { ... }

    public void onLocationError(int errCode) {...}

    public void providerStateChanged(int arg0) {...}

}

4.2       Creating the locationUpdated Callback Method

The locationUpdated method is called after a successful location fix by the LocationListener object.

The current location is passed to the method as a parameter. The following example of this callback method centers the current location on the displayed map.

public void locationUpdated(Location location) {

    if (location != null) {

        Coordinates center = new Coordinates(location.getLatitude(), location.getLongitude());

        // update the location on the map

        mapField.mapShowLocation(true);

        mapField.mapUpdateLocation(center, location.getAccuracy(), true, true, true);

    }

}

This method centers the new location in the map view by calling the method mapUpdateLocation. Add this method call to your code so the callback gets called.

// this method will ask the LocationProvider to get your current location

LBSManager.getLocationProvidert().getOneFix(listener, LocationProvider.LOCATION_FIX_FAST);

5          Creating the Sample Application in the BlackBerry JDE

To import the Sample Application into the BlackBerry JDE, you must follow these steps:

 

1.     From the File menu, select Open Workspace.

2.     Select the map_sample_app.jdw file, and click Open.

 

The workspace should be imported into the JDE, and you can build and run the application.

 

6          NBI Programming Guidelines for RIM Development

6.1       About the NBI Library

The NBI Library is a set of APIs that allows the developer to create LBS (Location Based Services) applications easily and quickly.  The NBI Library consists of two main parts, the Map Kit and the Location Kit.  These two libraries can be used together, or separately if only one library is required.

6.1.1    Map Kit

The Map Kit enables an application to display a map, allow user interaction with the map, get driving directions, and performs searches and display the results on the map.  The map tiles and search results are queried from NBI servers.  Search types include: point of interest search, geocode and reverse geocode searching, fuel (gas stations), movies, and weather.

6.1.2    Location Kit

The Location Kit enables an application to get its current location, and to provide a tracking session, which will update the location of a moving object.  The location kit uses the device’s GPS, wi-fi, and cell ID to obtain its current location.

6.2       Using the Map Kit

Install the nbi.jar file in your application to use the MapKit’s functionality. For more information about setting up NBI libraries, see “Installing the nbi.jar File” on page 2.

6.2.1    Displaying the map

One of the best features with the Map Kit is the ability to easily display a map in your application.

 



The map allows user interaction, including panning, flicking, and pinching. The buttons near the bottom of the map can programmatically be shown or hidden when the map is created.

6.2.2    MapConfiguration

A MapConfiguration object must be created before a MapField object can be displayed.  The MapConfiguration object contains information such as location coordinates and initial zoom level.  This object is also used to configure if the MapField should display the zoom buttons and the traffic button.

After creating a MapConfiguration object, there are methods that can be called to customize the MapField that will be created.  To set the center of the map, call MapConfiguration_setCenter.  To select the initial zoom level of the map, call MapConfiguration_setZoom.  To select the map type (see section 2.1.2.1) of the map, call MapConfiguration_setViewType.  If you want to display the Map Kit’s own zoom buttons, then call MapConfiguration_setZoomButtons.  And to display the Map Kit’s own traffic button, call MapConfiguration_setTrafficButton.

There are two convenience MapConfiguration constructors that can be used to create this object from a Location object or a Place object.  They are MapConfiguration_defaultConfigurationFromLocation and MapConfiguration_defaultConfigurationFrom Place.  These can be used to quickly create this object given a known location.

6.2.3    MapField

The MapField object is used to display the map.  To create the MapField from the MapConfiguration object and then display it, use:

MapField mapField = new MapField(mapConfiguration);

add(mapField);

6.2.3.1       Map Type

The MapField can display three different types of maps:

            - Street Map

            - Satellite Map

            - Hybrid Map (satellite map with street names)

The application can switch between these different map types using the method MapField_setMapViewType.  Also, the current map type being displayed can be retrieved with the method MapField_getMapViewType.

6.2.3.2       Center Map

The map can be centered on any location.  The application can create a Coordinate object, and call the method MapField_mapSetCenter.  Conversely, the current center of the map can be retrieved with the method MapField_getMapCenter.

6.2.3.3       Current Location

The map can also display the user’s current location.  Please refer to section 3 on how to get the current location.  Once the current location is known, the application can call the method MapField_mapUpdateLocation.  The application also must call MapField_mapShowLocation(true) to show the location on the map.

A common use of these methods would be in a Location Kit listener callback routine.

The application can also retrieve the current location from the map by calling the method MapField_mapGetUpdateLocation.

6.2.3.4       Zoom Level

The map can be zoomed manually by the user, or set programmatically.  To set the zoom level of the map, call the method MapField_setZoomLevel.  To get the current zoom value, call MapField.getZoomLevel.

If the zoom buttons are displayed, they will change the zoom level when pressed.

A shortcut method MapField_setCenterAndZoom can be called if the center of the map and the zoom level are to change at the same time.

6.2.3.5       Traffic

The map can display real time traffic and traffic incidents overlaid on the map.  The display real time traffic on the map, use the method MapField_showTrafficLayer.  To display traffic incidents on the map, use the method MapField_showTrafficIncidentsLayer.

If the traffic button is displayed, it will toggle the traffic layer and traffic incident layer.

6.2.3.6       Overlaying Buttons on the Map Field

In some situations, you may want to overlay your own button instead of, or in addition to the Map Kit’s buttons.  In that case, you will want to create your own custom class that implements the Manager class.  Please refer to the Sample Application’s MapManager.java file for an example.

6.3       Searches

The Map Kit has several types of searches that can be queried by the application.  These searches are carried out asynchronously, and will call a completion routine when completed.  All searches implement the class NBIRequest.  And all search listeners implement the class NBIListener.

6.3.1    The Listener

A listener is required to receive the search results.  Each search type has it’s own specific listener class, but must implement several required methods.  These methods are callbacks, and should not be called directly by the application.

NBIListener_onRequestStart is called when the search request is about to be sent.

NBIListener_onRequestProgress is called while a request is in progress, returning a percentage complete parameter.

NBIListener_onRequestComplete is called when the request has completed successfully.

NBIListener_onRequestCancelled is called if the request is cancelled.

NBIListener_onRequestError is called if there is an error in the request.

NBIListener_onRequestTimeout is called if the request times out.

NOTE: You can create one class that implements several listeners so you only need to have one copy of all the required callback methods.

6.3.2    The Search Request

All search types implement the NBIRequest class.  Each search type has it’s own specific search class, but must implement several required methods.

NBIRequest_startRequest is called to initiate a search.

NBIRequest_isRequestInProgress can be called to check if a specific request object has an outstanding request.

NBIRequest_cancelRequest can be called to cancel a specific request.  This is usually called as a result of the user cancelling the request.

Many of the searches will search for things that are near a specified area on the map.  You will need to create a SearchRegion object to specify the area to search.  Search results are batched together in groups of 10, with a maximum of 100 results.

6.3.3    Search Types

There are several different search types available.  Each search type implements its own subclass of the NBIRequest class.

6.3.3.1       Point of Interest Search

To initiate a POI search request, you must implement the listener class POISearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method POISearchListener_onLocalSearch.

Create an object of type POISearchRequest to initiate a local search around a specific area on the map.  There are two constructors for this request.  The first is used to initiate the initial search, which will return up to 10 results.  The other is used for subsequent searches, which is used to return more groups of 10 results.

Call POISearchRequest_startRequest to initiate the POI search.  When the search successfully completes, the POISearchListener_onLocalSearch callback method will be called with the results of the search.

Please refer to the Sample Application’s PlacesList.java file for an example.

6.3.3.2       Event Search

To initiate an event search request, you must implement the listener class EventSearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method EventSearchListener_onEventSearch.

Create an object of type EventSearchRequest to initiate an event search around a specific area on the map.  There are two constructors for this request.  The first is used to initiate the initial search, which will return up to 10 results.  The other is used for subsequent searches, which is used to return more groups of 10 results.

Call EventSearchRequest_startRequest to initiate the event search.  When the search successfully completes, the EventSearchListener_onEventSearch callback method will be called with the results of the search.

6.3.3.3       Fuel Search

To initiate a search for gas stations, you must implement the listener class FuelSearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method FuelSearchListener_onFuelSearch.

Create an object of type FuelSearchRequest to initiate a gas station search around a specific area on the map.  There are two constructors for this request.  The first is used to initiate the initial search, which will return up to 10 results.  The other is used for subsequent searches, which is used to return more groups of 10 results.

Call FuelSearchRequest_startRequest to initiate the gas station search.  When the search successfully completes, the FuelSearchListener_onFuelSearch callback method will be called with the results of the search.

6.3.3.4       Movie Event Search

There are several movie and theater searches available within the Map Kit.

6.3.3.4.1      Movie Search

To initiate a movie search request, you must implement the listener class MovieSearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method MovieSearchListener_onMovieSearch.

Create an object of type MovieSearchRequest to initiate a movie search around a specific area on the map.  There are two constructors for this request.  The first is used to initiate the initial search, which will return up to 10 results.  The other is used for subsequent searches, which is used to return more groups of 10 results.

Call MovieSearchRequest_startRequest to initiate the movie search.  When the search successfully completes, the MovieSearchListener_onMovieSearch callback method will be called with the results of the search.

6.3.3.4.2      Movie Showtime Search

Once you have the movie search results, you can search for movie showtimes. To initiate a movie search request, you must implement the listener class MovieShowtimeSearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method MovieShowtimeSearchListener_onMovieShowtimeSearch.

Create an object of type MovieShowtimeSearchRequest to initiate a movie showtime search based on your previous movie search results.  There are two constructors for this request.  The first is used to initiate the initial search, which will return up to 10 results.  The other is used for subsequent searches, which is used to return more groups of 10 results.

Call MovieShowtimeSearchRequest_startRequest to initiate the movie showtime search.  When the search successfully completes, the MovieShowtimeSearchListener_onMovieShowtimeSearch callback method will be called with the results of the search.

6.3.3.4.3      Theater Search

To initiate a theater search request, you must implement the listener class TheaterSearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method TheaterSearchListener_onTheaterSearch.

Create an object of type TheaterSearchRequest to initiate a theater search around a specific area on the map.  There are two constructors for this request.  The first is used to initiate the initial search, which will return up to 10 results.  The other is used for subsequent searches, which is used to return more groups of 10 results.

Call TheaterSearchRequest_startRequest to initiate the theater search.  When the search successfully completes, the TheaterSearchListener_onTheaterSearch callback method will be called with the results of the search.

6.3.3.4.4      Theater Showtime Search

Once you have the theater search results, you can search for theater showtimes. To initiate a theater showtime search request, you must implement the listener class TheaterShowtimeSearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method TheaterShowtimeSearchListener_onTheaterShowtimeSearch.

Create an object of type TheaterShowtimeSearchRequest to initiate a theater showtime search based on your previous theater search results.  There are two constructors for this request.  The first is used to initiate the initial search, which will return up to 10 results.  The other is used for subsequent searches, which is used to return more groups of 10 results.

Call TheaterShowtimeSearchRequest_startRequest to initiate the theater showtime search.  When the search successfully completes, the TheaterShowtimeSearchListener_onTheaterShowtimeSearch callback method will be called with the results of the search.

6.3.3.5       Weather Search

To initiate a weather request, you must implement the listener class WeatherSearchListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method WeatherSearchListener_onWeatherSearch.

Create an object of type WeatherSearchRequest to initiate a weather request around a specific area on the map.  This request will return a single object, which is the current weather for the specific area.

Call WeatherSearchRequest_startRequest to initiate the weather request.  When the search successfully completes, the WeatherSearchListener_onWeatherSearch callback method will be called with the weather information requested.

6.3.3.6       Geocoding

A geocode search is an address search that will return the coordinates of the specified address.  To initiate a geocode request, you must implement the listener class GeocodeListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method GeocodeListener_onGeocode.

Create an object of type GeocodeRequest to initiate a geocode request, based on an address.  There are several constructors for this object, depending on what address information you have specified.   The first request will return up to 10 results.  One more constructor is used for subsequent requests, which is used to return more groups of 10 results.

Call GeocodeRequest_startRequest to initiate the geocode request.  When the request successfully completes, the GeocodeListener_onGeocode callback method will be called with the results of the search.

6.3.3.7       Reverse Geocoding

A reverse geocode is a search from specified coordinates, returning the address of the coordinates.  To initiate a reverse geocode request, you must implement the listener class ReverseGeocodeListener, which inherits from the class NBIListener.  In addition to the required NBIListener callback methods, you must implement the method ReverseGeocodeListener_onReverseGeocode.

Create an object of type ReverseGeocodeRequest to initiate a reverse geocode request, based on specified latitude and longitude coordinates.

Call ReverseGeocodeRequest_startRequest to initiate the reverse geocode request.  When the request successfully completes, the ReverseGeocodeListener_onReverseGeocode callback method will be called with the results of the search.

6.4       Pins

Pins are graphic elements that show specific locations on a map. Multiple pins can be used to show several search result locations simultaneously on a map. If the user taps a pin, a pin bubble appears above the pin containing more information about the location identified by the pin.

A Pin object can be created easily from a search result. The Pin can be created in several different colors, and a custom PinImage can be applied to the Pin if required. After a pin is created, it can be added to the MapField object using method MapField_addPin.

A Pin object can also be created without a specific location. Instead, a pin can be dropped onto a specific x,y coordinate of the MapField using the method MapField_dropPin. After the pin is dropped onto the map, a reverse geocode operation occurs with the results displayed in the pin’s bubble. A dropped pin can be dragged around the map by the user with a press and hold gesture.

6.5       Using the Location Kit

Install the nbi.jar file in your application to use the LocationKit’s functionality. For more information about setting up NBI libraries, see “Installing the nbi.jar File” on page 2.

6.6       Location Listener

All location kit routines require a LocationListener object to receive the information from the LocationProvider class.

The LocationListener must has three methods defined.

LocationListener_locationUpdated is called when the current location has been determined.

LocationListener_onLocationError is called when an error has occurred when attempting to determine the current location.

LocationListener_providerStateChanged is called when the state of the LocationProvider object has changed.

6.6.1    Getting your current location once

To get your current location, in latitude and longitude, call the method LocationProvider_getOneFix.  This method takes a parameter that can have three different values:

LOCATION_FIX_FAST: uses Cell-ID/wi-fi or sGPS if warm

LOCATION_FIX_ACCURATE: uses sGPS with a long time-out period

LOCATION_FIX_NORMAL: uses Cell-ID/wi-fi or sGPS with a short time-out period

The method LocationListener_locationUpdated will be called after the location has been determined.

6.6.2    Starting a tracking session

To start a tracking session, which can be used to track your current location on the map, call  method LocationProvider_startReceivingFixes.  To stop the tracking session, call method LocationProvider_stopReceivingFixes.

NOTE:

Do not keep a tracking session alive any longer than necessary. Using GPS services on a device can drain a battery more quickly than in normal usage.

7          New features in Phase 2

7.1       Mobile Coupons

NBI now provides the ability for third parties to provide mobile coupons to the end user.  These new APIs include the following functionality:

-          Retrieving retailers with coupons/deals based on location

-          Retrieving coupons/deal by category based on location

-          Retrieving coupons/deals based on location

-          Displaying coupon details

-          Storing coupons

-          Click to call retailer with a coupon if the coupon has a phone number

-          Redemption at the retailer mobile website (using an in-application browser)

-          Store the coupon/deal for later use

Searching for coupons is similar to doing a POI search.  Here is an example of how to search for coupons:

// create a coupon search request and fire it off

CouponStoreSearchFilter filter = new CouponStoreSearchFilter();

filter.setReturn("deals");

filter.setDealQuality("good");

filter.setCouponAvailability(new String[] {"local"});

filter.setMobileCompatibility("good");

filter.setKeyword(searchString);

CouponSearchRequest couponRequest = new CouponSearchRequest(nbiContext, new SearchRegion(coords), NBIRequest.SLICE_RESULTS_DEFAULT, filter, this);

couponRequest.startRequest();

NOTE: If you search for deals from a national store chain, and get a list of deals returned from the search query, you still need to validate that there is a branch of that store near you.  You can use a standard POI query to check if there is a store near you.  For example, if you search national store chains for a deal of TVs, and you receive a list of deals from Best Buy, you need to perform a POI query for “Best Buy” and verify there are store branches near you.

7.1.1    Mobile Coupon Terms and Conditions

 (a).      Publisher agrees (i) to install and incorporate the API as provided by TCS to enable Content distribution, search, and display for the purpose of using the Services, including any updates, fixes or patches provided by TCS from time to time; (ii) to maintain throughout the term all software codes, tags and identifiers provided by TCS to serve the Content, manage Brand campaigns and perform the Services; and (iii) to receive and accept all messages sent to Publisher by TCS relevant to the Content including confirmation, redemption, and error messages, and to display those messages to appropriate Consumers.

(b).       Publisher shall not alter, modify or otherwise interfere with the operation of any of the Content or Services including any copy, content, codes, tags, identifiers or links contained within any Content, except with the prior, written approval of TCS. Publisher will comply with any additional Brand restrictions applicable to Content, including but not limited to specific attribution requirements and banned search terms. 

(c).       Publisher represents and warrants that it will not, and will not assist or enable others to:

(i) use the Services, API or Content in any way that infringes or violates any right of any third party, or violate any applicable law, rule or regulation, including but not limited to, MMA Best Practices, applicable wireless carrier guidelines, and FTC and state clear disclosure rules.  Publisher further represents and warrants that its Publisher Properties will not infringe or violate any right of any third party, or violate any applicable law, rule or regulation. Publisher agrees that it shall be solely and exclusively responsible for the Publisher Properties, other than with respect to Content displayed on such Publisher Properties in accordance with the terms of this Agreement, and that TCS has no responsibility, to review or approve the Publisher Properties.

(ii) display or market Content contemporaneously with inappropriate content, which includes, but is not limited to, content that (A) promotes the use of alcohol (except to the extent expressly allowed by TCS), tobacco or illegal substances; (B) contains nudity, pornography, adult-oriented content such as phone sex or escort services, or expletives or other words banned by any applicable U.S. wireless carrier; (C) promotes or contains gratuitous violence or other material that abuses or threatens physical harm;  (D) is libelous, defamatory, disparaging, infringing of any right of any third party, false, or misleading; or (E) is otherwise prohibited by Federal, state, or local law, rule or regulation applicable to any jurisdiction where the marketing occurs. 

(iii) engage in any activity that will result in the generation of fraudulent clicks or Actions in connection with Content, including but not limited to through the use of robots, repeated manual clicks, optimization software, or the offering of any incentives unless expressly approved in writing from TCS. 

(iv) cache, record, pre-fetch, or otherwise store any portion of the Content, or attempt or provide a means to execute any "bulk download" operations.

(v) create, publish or otherwise disclose (except to TCS) metrics about, or perform any statistical analysis of, the API or Content.

            (vi) copy, rent, lease, sell, transfer, sublicense, dissemble, reverse engineer or decompile (except to the limited extent expressly authorized under applicable statutory law), modify or alter any part of the API except as expressly authorized by this Agreement.

            (vii) use the API in a manner that impacts the stability of TCS servers or impacts the behavior of other Publishers or applications using the API.  Publisher shall, as soon as practicable, but in no event less than ten (10) business days in advance, inform TCS of any Publisher action that will substantially increase or reduce expected Content distribution or Consumer interaction with such Content on the Publisher Properties.

 

7.2       Custom Map Layers

NBI now provides the ability to add custom map layers to the displayed map.  This can allow an application to overlay weather or public transit lines easily on the map.  These new APIs include the following functionality:

7.2.1    Custom base map layer

A custom base map layer can be used to display features on a map such as a shopping mall or an amusement park.  Here is an example of a custom base map layer:

         

A custom base map layer is created using this API:

MapLayer baseLayer = mapField.addMapLayer("http://www.tileserver.com/ x=$x&y=$y&z=$z", null, MapField.MIN_ZOOM_LEVEL, MapField.MAX_ZOOM_LEVEL, MapField.NBI_LAYER_BASE, 0, null, null);

In the case of creating a shopping mall base layer, you will want to use a bounding box to limit the area when tiles are fetched from the server.  You may also want to specify minimum and maximum zoom levels when the shopping mall is displayed.

When entering the URL, there are several tokens that will be substituted by NBI before it is sent off to the server.

-          $x will become the X position of the map tile

-          $y will become the Y position of the map tile

-          $z will become the zoom level of the map tile

-          $q will become the quadkey of the map tile

-          $sz will become the size of the map tile (128 or 256)

-          $user will be substituted with the string provided by the user callback function.  (See the API document for more information about this.)

If the URL does not specify a tile size, then most likely the tile being requested is size 256.  In that case, you will want to force NBI to only use map tiles of size 256x256.  This can be done when creating the MapField object by using the setForce256 function.  Here is an example of how to do that.

MapConfiguration mapConfiguration = new MapConfiguration(nbiContext);

mapConfiguration.setForce256(true);

mapField.setConfiguration(mapConfiguration);

7.2.2    Custom overlay map layer

A custom overlay map layer may be used to display traffic conditions or transit lines on the map.  Here is an example on how to create a custom overlay map layer:

MapLayer overlayLayer = mapField.addMapLayer("http://www.tileserver.com/ x=$x&y=$y&z=$z", null, MapField.MIN_ZOOM_LEVEL, MapField.MAX_ZOOM_LEVEL, MapField.NBI_LAYER_OVERLAY, 0, null, null);

Depending on what is being displayed, you may want to specify a timeout period to force the tiles to be refreshed automatically.  For example, if you are displaying a traffic overlay, you may want to refresh the overlay tiles every 5 minutes.

7.2.3    Multiple POI (Point Of Interest) layers

Previously, there was a singular layer for adding Pins to the map.  Now, you can have several POILayers on the map at the same time.  For example, one POI layer can display all the pizza places, another can display all the sushi restaurants, and another can display all the burger places.  You can individually show or hide each of these layers.

New POILayers can be added to the map using this API:

POILayer poiLayer = mapField.addPOILayer(MapView.NBI_LAYER_OVERLAY_PIN);

After creating this POILayer, you can add Pins to the layer by using this API:

mapField.addPin(poiLayer, pin, false, false);

7.2.4    Automatic POI layers

An automatic POILayer will add and remove Pins from the layer automatically.  NBI uses a URL to contact a POI server to get the data from the server, and then it will call the POIExtractionCallback function to extract the data, and Pins are added to the layer.

Here is an example of how to create an automatic POILayer:

POILayer autoPOILayer = mapField.addPOILayer("http://yourPOIserver.com/ ?x=$x&y=$y&z=$z ", null, MapView.MIN_ZOOM_LEVEL, MapView.MAX_ZOOM_LEVEL, MapView.NBI_LAYER_OVERLAY_POI, 0, this, null, null);

The automatic POI layers require a custom POI server.  Instructions for the POI server can be found in the POI Server Read Me document.

Whenever new data is read from the server, the POIExtractionCallback function is called.  Here is an example of this:

public void poiExtractionCallback(MapField view, POILayer layer, byte[] buff)  {

    // iterate through the buffer, one line at a time

    // example of the line returned from the server:

    // "Starbucks",33.1234,-120.4567

    String dataString = new String(buffer);

    String lines[] = dataString.split("\\r?\\n");

    for (String line : lines) {

        // get the name

        int del = line.indexOf("\",");

        if (del == -1)

            continue;

        String name = line.substring(1, del);

        line = line.substring(del + 2);

        String data[] = line.split(",");

        MapLocation mapLocation = new MapLocation();

        double lat = Double.parseDouble(data[0]);

        double lon = Double.parseDouble(data[1]);

        if (lat == 0 || lon == 0)

            continue;

        mapLocation.setLatLon(lat, lon);

        Place place = new Place(name, mapLocation);

        Pin pin = new Pin(Pin.PIN_ORANGE, place, null);

        view.addPin(layer, pin, false, false);

    }

7.3       Cross Carrier Support

NBI now has the ability to run on devices from all carriers.  However, running on a non-Verizon device will have a subset of the full functionality given on a Verizon device.

NBI V2 FEATURES

NON-VZW DEVICES

VZW DEVICES

Road maps

X

X

Satellite maps

X

X

Directions

X

X

Geocoding

X

X

Reverse Geocoding

X

X

Local Search

X

X

Static Directions

X

X

Static Directions with Traffic Delays

 

X

Location using standalone GPS, Cell-ID and Wi-Fi (if supported by the device)

X

X

Location Databases

X

X

VZW’s Cell-ID Database

 

X

VZW’s Wi-Fi Access Point Database

 

X

Non-VZW Cell-ID Database

X

 

Non-VZW Wi-Fi Access Point Database

X

 

Premium Content

 

X

Movies, Movie Showtimes and Theaters

 

X

Events, Event Details and Event Venues

 

X

Weather

 

X

Gas prices

 

X

Traffic overlay on the map

 

X

Traffic data on static directions

 

X

Traffic Incidents

 

X