Testing for availability of transports
A big part of the decision for
which transport to use comes down to being able to test to see which
transports are available. You can't test for every possibility, but you
can certainly test for certain aspects, such as whether the device
supports Wi-Fi or whether the application is currently running on the
simulator or not.
One common technique that
seems to work well is to only prompt the user for an address and to
remove any other connection string options the user might have added.
Then, after some testing to determine which transports are available,
add the appropriate connection string options and create the connection.
This takes the responsibility of knowing anything about the network
transports off the user and makes the whole experience much smoother for
the user.
There are several classes
that can be used to gather bits of information about what capabilities
are present on the device. Some of these classes have changed over time,
so there may be differences when working with other versions of the
SDK. For our purposes here though, we will focus only on version 4.5.
With that in mind, let's add one more feature to the HttpBasics
application-a small diagnostics screen. It is worth noting that
Research In Motion provides a much more extensive tool called the Network Diagnostic Tool, which can be found at
http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800451/800563/What_Is_-_Network_Diagnostic_Tool.html?nodeid=1450596&vernum=0.
Time for action - testing for availability
Create a new class in the HTTPBasics project called DiagMainScreen, which is derived from the MainScreen class.
Add this constructor to the class
public DiagMainScreen()
{
if (DeviceInfo.isSimulator())
{
add(new LabelField ("This is running in the simulator."));
}
if(WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)
{
add(new LabelField ("There is a WiFi connection available."));
}
if(CoverageInfo.isCoverageSufficient( CoverageInfo.COVERAGE_DIRECT)
{
add(new LabelField ("Direct TCP/IP Connections are available (Including WAP)."));
}
if(CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_MDS))
{
add(new LabelField ("Connections via MDS are available."));
}
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.findRecordsByCid("WPTCP");
for (int i = 0; i < records.length; i++)
{
String uid = records[i].getUid().toLowerCase();
if ( uid.indexOf("wifi") == -1 && uid.indexOf("mms") == -1)
{
add(new LabelField ("A WAP 2.0 connection is available using UID=" + records[i].getUid()));
}
}
}
Add a menu item to show the new screen to HttpBasicsMainScreen.
protected MenuItem _DisplayDiagAction = new MenuItem( "Display Diagnostics", 90000, 10)
{
public void run()
{
UiApplication.getUiApplication().pushScreen( new DiagMainScreen());
}
};
Lastly, add the menu item to the application by adding the following line to the constructor of the HttpBasicsMainScreen class.
addMenuItem(_DisplayDiagAction);
What just happened?
This small screen demonstrates
the kind of checks you can do to determine what capabilities are
available on a handheld. These are the most general conditions which
should be checked, but there may be other more specific cases that you
run into for your specific application, such as having multiple service
books available for WAP 2.0.
There are only a few checks
that you can make and unfortunately, they aren't all in one class. Some
of them aren't even available in older versions, such as the WLANInfo class, which didn't appear until version 4.5.
The first, and most basic, test is to see if the application is running in the simulator. The DeviceInfo
class will show this and much more information about the hardware
aspects of the device that the application is running on. Methods such
as hasCamera() and isInHolster()
can be essential for some tasks. You can also get the OS software
version from this class as well, which can be an important piece of
information when debugging problems with a user's handheld.
if (DeviceInfo.isSimulator())
{
add(new LabelField ("This is running in the simulator."));
}
The next simple test is one to check whether there is a Wi-Fi connection or not. The WLANInfo
class can provide information about whether the Wi-Fi is currently
connected to an access point or not. If there is a connection, you can
also get additional information about the access point it is connected
to, such as what kind of 802.11 connection is being used, A, B, or G,
and so on. There is no way to tell if the device is Wi-Fi capable, but
is simply not currently connected however.
if(WLANInfo.getWLANState() == WLANInfo.WLAN_STATE_CONNECTED)
{
add(new LabelField ("There is a WiFi connection available."));
}
The CoverageInfo
class is used to gather information about the cellular network that
the device uses. For this situation we're particularly interested in the isCoverageSufficient method. Things get a bit muddied with this class though because the WAP and TCP/IP direct transports are both lumped into the COVERAGE_DIRECT grouping. A separate constant, COVERAGE_MDS, is used to determine if the MDS transport is available though, and this makes it easy to use.
if(CoverageInfo.isCoverageSufficient(CoverageInfo.COVERAGE_DIRECT))
{
add(new LabelField ("Direct TCP/IP Connections are available (Including WAP)."));
}
The last section of code is
there to find the service book entry to use with the WAP 2.0 transport.
Remember, earlier we said that in order to use the WAP 2.0 transport you
need to append the ConnectionUID=<uid> parameter to the connection string. The<uid> value in that string is not a constant and is provided by your carrier in the form of a service book.
A service book is a collection of configuration records, called service records,
which are provided by your carrier or your BES administrator and is
what controls how your device can communicate with other servers on the
network. You can have a great number of service records in the service
book actually, each for a different situation
This small loop is used to
query the service book for records that have the CID, or Content ID, of
WPTCP. WPTCP is basically another name for WAP 2.0.
The first step is to get the service book itself, which is done using a static method in the ServiceBook class called getSB. Once you have an instance of the ServiceBook you can get only those records that have a Content ID of WPTCP by calling findRecordsByCid. It is possible to simply get all of the service records with the getRecords method, but this would just mean more work for us.
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.findRecordsByCid("WPTCP");
If there are no records with
that CID then the array that is returned will be empty, but if there is
at least one you need to examine it more closely to pick the best one.
The conditional if statement inside the loop does some checking on the UID of the service record to see if it is one you are looking for. The UID
is essentially a unique name identifier. There can be multiple WPTCP
service records which facilitate communicating over other methods
besides the carrier network. Specifically, there can be service records
for use with Wi-Fi or Multimedia Messaging Service
(MMS). In general, we only want to be using the carrier network so
service records with these words in the name are skipped over in this
algorithm.
for (int i = 0; i < records.length; i++)
{
String uid = records[i].getUid().toLowerCase();
if ( uid.indexOf("wifi") == -1 && uid.indexOf("mms") == -1)
{
add(new LabelField ("A WAP 2.0 connection is available using UID=" + records[i].getUid()));
}
}
Unfortunately,
running this code in the simulator isn't very interesting because only
the labels regarding the simulator and direct TCP/IP will be shown. The
simulator doesn't have service books for WCTCP like a real device does.
You can go through the BES association process on a simulator just like
you can on your phone in order to configure the MDS connection. But this
isn't done very often unless necessary because it truly configures the
simulator as a device on your BES.