Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

The Network API

The Network API is implemented in the net.rim.device.api.io.transport and net.rim.device.api.io.transport.options packages. Most of the functionality is provided by the ConnectionFactory and TransportInfo classes. A ConnectionFactory object returns a ConnectionDescriptor object that contains a Connection object and information about the transport over which the connection was opened.

Choosing network transports

The TransportInfo class provides information about the network transports that are available on a BlackBerry smartphone. You can retrieve a list of transports that currently have coverage, or use the API to determine whether a particular transport is available and has coverage.

If you don't provide an ordered list of preferred transports when you open a connection, the Network API chooses a transport for you. However, you should prioritize the transports your app uses based on the type of user your app targets. The API steps through an array of transport types that you set with ConnectionFactory.setPreferredTransportTypes().

After you list your preferred transports, you should set options for any transports that require specific options. For example, WAP 1.0 and 1.1 transports require information about an APN, gateway authentication, and so on.

You should also create a CoverageStatusListener object (in the net.rim.device.api.io.transport package), and register it using TransportInfo.addListener(). The smartphone notifies your app about changes in coverage status so your app can respond appropriately.

Opening a network connection using the Network API

After you decide which network transports to use, you can open a connection and use it to send and receive data. The ConnectionFactory object is responsible for opening connections. In addition to your preferred transports, you can use ConnectionFactory to configure connection options, such as:
  • Maximum number of connection attempts
  • Maximum time to spend making connection attempts
  • Delay between connection attempts
  • Whether or not encryption is required between the connection end points

When you are ready to open a connection, you should invoke one of the ConnectionFactory.getConnection methods. Be sure that you call getConnection on a thread that is separate from the main event thread.

When you open a connection successfully, ConnectionFactory returns a ConnectionDescriptor object. ConnectionDescriptor contains a Connection object and information about the transport that was used to open the connection.

Open a network connection using the Network API

CAUTION:
The ConnectionFactory.getConnection() method blocks thread execution. You should create a separate thread to call getConnection().

Import the required classes and interfaces.

import net.rim.device.api.io.transport.*;
import net.rim.device.api.io.transport.options.*;
import net.rim.device.api.io.transport.TransportInfo;
import net.rim.device.api.ui.UiApplication;

Create an ordered list of preferred transports.

int[] intTransports =
{ TransportInfo.TRANSPORT_TCP_WIFI,
  TransportInfo.TRANSPORT_WAP2,
  TransportInfo.TRANSPORT_TCP_CELLULAR
}

Configure the options for the TCP Cellular transport, if applicable.

TcpCellularOptions tcpOptions = new TcpCellularOptions();
if(!TcpCellularOptions.isDefaultAPNSet())
{
    tcpOptions.setApn("My APN");
    tcpOptions.setTunnelAuthUsername("user");
    tcpOptions.setTunnelAuthPassword("password");
}

Create a ConnectionFactory object.

ConnectionFactory factory = new ConnectionFactory();

Set any other ConnectionFactory options that are applicable to your app. In this case, TCP Cellular is one of the preferred transports, so set the TCP Cellular transport options.

factory.setTransportTypeOptions(TransportInfo.TRANSPORT_TCP_CELLULAR, tcpOptions);
factory.setAttemptsLimit(5);

Create a thread to retrieve the connection. If the connection was successful, then ConnectionFactory returns a ConnectionDescriptor object that you can use. In this step, pass the ConnectionDescriptor object to another method (displayContent()) that is responsible for displaying the content.

Thread t = new Thread(new Runnable()
{
    public void run()
    {
        ConnectionDescriptor cd = _factory.getConnection
                                       ("http://www.blackberry.com");
        if(cd != null) 
        {
            Connection c = cd.getConnection();
            displayContent(c);
        }
     }

});
t.start();

Implement displayContent(). In this case, push a screen that uses a Connection parameter to retrieve and display the content, after the connection retrieval thread completes.

private void displayContent(final Connection conn) 
{
    UiApplication.getUiApplication().invokeLater(new Runnable()
    {
        public void run() {
            UiApplication.getUiApplication().pushScreen(new HTTPOutputScreen(conn));
        }
    });
}

Code sample: Retrieving a web page using the Network API

To make this code sample as generic as possible, the InputConnection and OutputConnection interfaces are used in place of the HttpConnection interface.

import net.rim.device.api.io.transport.*;
import net.rim.device.api.io.transport.options.*;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.util.Arrays;
import java.io.*;
import javax.microedition.io.*;

public class NetworkSample extends UiApplication 
{
    public static void main(String[] args) 
    {
        NetworkSample app = new NetworkSample();
        app.enterEventDispatcher();
    }
    public NetworkSample() 
    {
        new HTTPConnectionSetup();
    }
}

class HTTPConnectionSetup 
{
    ConnectionFactory _factory = new ConnectionFactory();

    public HTTPConnectionSetup() 
    {

        // Create a preference-ordered list of transports.
        int[] _intTransports =
        { TransportInfo.TRANSPORT_TCP_WIFI,
          TransportInfo.TRANSPORT_WAP2,
          TransportInfo.TRANSPORT_TCP_CELLULAR
        };

        // Remove any transports that are not currently available.
        for(int i = 0; i < _intTransports.length ; i++)
        {
            int transport = _intTransports[i];
            if(!TransportInfo.isTransportTypeAvailable(transport)
                  || !TransportInfo.hasSufficientCoverage(transport))
            {
                Arrays.removeAt(_intTransports, i);
            }
        }

        // Set options for TCP Cellular transport.
        TcpCellularOptions tcpOptions = new TcpCellularOptions();
        if(!TcpCellularOptions.isDefaultAPNSet())
        {
            tcpOptions.setApn("My APN");
            tcpOptions.setTunnelAuthUsername("user");
            tcpOptions.setTunnelAuthPassword("password");
        }

        // Set ConnectionFactory options.
        if(_intTransports.length > 0)
        {
            _factory.setPreferredTransportTypes(_intTransports);
        }
        _factory.setTransportTypeOptions(
                  TransportInfo.TRANSPORT_TCP_CELLULAR,tcpOptions);
        _factory.setAttemptsLimit(5);

        // Open a connection on a new thread.
        Thread t = new Thread(new Runnable()
        {
            public void run()
            {
                ConnectionDescriptor cd = _factory.getConnection
                    ("http://www.blackberry.com");
                // If connection was successful, fetch and show  
                // the content from the web server.
                if(cd != null) 
                {
                    Connection c = cd.getConnection();
                    displayContent(c);
                }
             }

        });
        t.start();
    }

    private void displayContent(final Connection conn) 
    {
        // When the connection thread completes, 
        // show the data from the web server.
        UiApplication.getUiApplication().invokeLater(new Runnable()
        {
            public void run() 
            {
                UiApplication.getUiApplication().pushScreen(
                       new HTTPOutputScreen(conn));
            }
        });
    }
}

class HTTPOutputScreen extends MainScreen 
{
    RichTextField _rtfOutput = new RichTextField();

    public HTTPOutputScreen(Connection conn)
    {
        // Create a container for the data and put it on the screen.
        _rtfOutput.setText("Retrieving data. Please wait...");
        add(_rtfOutput);
        // Retrieve the data from the web server, using the 
        // connection, on a separate thread.
        ContentReaderThread t = new ContentReaderThread(conn);
        t.start();
    }

    // After the data has been retrieved, display it.
    public void showContents(final String result) 
    {
        UiApplication.getUiApplication().invokeLater(new Runnable() 
        {

            public void run() 
            {
                _rtfOutput.setText(result);
            }
        });
    }

    private final class ContentReaderThread extends Thread
    {
        private Connection _connection;

        ContentReaderThread(Connection conn)
        {
            _connection = conn;
        }

        public void run()
        {
            String result = "";
            OutputStream os = null;
            InputStream is = null;

            try
            {
                // Send HTTP GET to the server.
                OutputConnection outputConn = (OutputConnection) _connection;
                os = outputConn.openOutputStream();
                String getCommand = "GET " + "/" + " HTTP/1.0\r\n\r\n";
                os.write(getCommand.getBytes());
                os.flush();

                // Get InputConnection and read the server's response.
                InputConnection inputConn = (InputConnection) _connection;
                is = inputConn.openInputStream();
                byte[] data = net.rim.device.api.io.IOUtilities.streamToBytes(is);
                result = new String(data);
                // is.close();

            }
            catch(Exception e)
            {
                result = "ERROR fetching content: " + e.toString();
            }
            finally
            {
                // Close OutputStream.
                if(os != null)
                {
                    try
                    {
                        os.close();
                    }
                    catch(IOException e)
                    {
                    }
                }

                // Close InputStream.
                if(is != null)
                {
                    try
                    {
                        is.close();
                    }
                    catch(IOException e)
                    {
                    }
                }

                // Close Connection.
                try
                {
                    _connection.close();
                }
                catch(IOException ioe)
                {
                }
            }

            // Show the response from the web server or an error message.
            showContents(result);
        }
    }
}

Code sample: Determining network transports with sufficient coverage using the Network API

import net.rim.device.api.io.transport.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;

public class NetworkSample extends UiApplication 
{
    public static void main(String[] args) 
    {
        NetworkSample app = new NetworkSample();
        app.enterEventDispatcher();
    }
    public NetworkSample() {
        pushScreen(new ListTransportsWithCoverageScreen());
    }
}

class ListTransportsWithCoverageScreen extends MainScreen
{
    private int[] _transportsWithCoverage;
    private TransportDescriptor[] _transports;
    private RichTextField _rtfDisplay;
    private ButtonField _btnShowTransports;

    public ListTransportsWithCoverageScreen()
    {
        VerticalFieldManager vfm = new VerticalFieldManager();
        setTitle("Network Sample");
        _rtfDisplay = new RichTextField
             ("Click button below to display available transports.");
        _btnShowTransports = new ButtonField
             ("Show Transports", Field.FIELD_HCENTER);
        _btnShowTransports.setChangeListener(new FieldChangeListener()
        {
            public void fieldChanged(Field field, int context)
            {
                getTransports();
            }
        });
        vfm.add(_rtfDisplay);
        vfm.add(_btnShowTransports);
        add(vfm);

    }

    public void getTransports()
    {
        StringBuffer sb = new StringBuffer();
        sb.append("The transports currently available are: \n");
        _transportsWithCoverage = TransportInfo.getCoverageStatus();
        _transports = TransportInfo.getTransportDescriptors
                          (_transportsWithCoverage);
        for(int i = _transports.length - 1; i >=0; --i)
        {
            switch(_transports[i].getTransportType())
            {
            case TransportInfo.TRANSPORT_BIS_B:
                sb.append("BlackBerry Internet Service\n");
                break;
            case TransportInfo.TRANSPORT_MDS:
                sb.append("BlackBerry Mobile Data Service\n");
                break;
            case TransportInfo.TRANSPORT_TCP_CELLULAR:
                sb.append("TCP Cellular\n");
                break;
            case TransportInfo.TRANSPORT_TCP_WIFI:
                sb.append("TCP WiFi\n");
                break;
            case TransportInfo.TRANSPORT_WAP:
                sb.append("WAP 1.0 or 1.1\n");
                break;
            case TransportInfo.TRANSPORT_WAP2:
                sb.append("WAP 2.0\n");
                break;
           }
        }
        _rtfDisplay.setText(sb.toString());
    }
}

Code sample: Determining the status of a network transport using the Network API

import net.rim.device.api.io.transport.TransportInfo;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;

public class NetworkSample extends UiApplication 
{
    public static void main(String[] args) 
    {
        NetworkSample app = new NetworkSample();
        app.enterEventDispatcher();
    }
    public NetworkSample() 
    {
        pushScreen(new ProbeSpecificTransportScreen());
    }
}

class ProbeSpecificTransportScreen extends MainScreen implements FieldChangeListener {

    private TextField _tfTransportStatus;
    private ObjectChoiceField _ocfTransports;

    public ProbeSpecificTransportScreen()
    {
        String[] strTransportNames = 
        {"none", "TCP Cellular", "WAP 1.0/1.1", 
         "WAP 2.0", "MDS", "BIS", "TCP WiFi"
        };

        VerticalFieldManager vfm = new VerticalFieldManager();

        _tfTransportStatus = new TextField(Field.FIELD_HCENTER);
        _tfTransportStatus.setText
            ("Select a transport from the list above, then click 'Probe Transport'");

        _ocfTransports = new ObjectChoiceField
            ("Select Transport to Probe: ", strTransportNames, 
                 0, Field.FIELD_HCENTER);
        _ocfTransports.setEditable(true);

        ButtonField btnProbe = new ButtonField("Probe Transport", Field.FIELD_HCENTER);
        btnProbe.setChangeListener(this);

        vfm.add(_ocfTransports);
        vfm.add(btnProbe);
        vfm.add(_tfTransportStatus);
        add(vfm);
    }

    public void fieldChanged(Field field, int context)
    {
        int intTransportType = _ocfTransports.getSelectedIndex();
        if(intTransportType > 0)
        {
            if(TransportInfo.isTransportTypeAvailable(intTransportType))
            {
                if(TransportInfo.hasSufficientCoverage(intTransportType))
                {
                    _tfTransportStatus.setText
                         ((String)_ocfTransports.getChoice(intTransportType) 
                             + " is available.");
                } else
                {
                    _tfTransportStatus.setText
                         ((String)_ocfTransports.getChoice(intTransportType) 
                             + " is available but has insufficient coverage.");
                }
            } else
            {
                _tfTransportStatus.setText("Sorry, " + 
                     (String)_ocfTransports.getChoice(intTransportType) 
                         + " is not available.");

            }
        } else
        {
            _tfTransportStatus.setText
                ("Please select a transport first, then click 'Probe Transport'");
        }
    }
}