Package com.rim.samples.device.bluetoothdemo

Source Code of com.rim.samples.device.bluetoothdemo.SPPScreen

/*
* SPPScreen.java
*
* Copyright � 1998-2011 Research In Motion Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Note: For the sake of simplicity, this sample application may not leverage
* resource bundles and resource strings.  However, it is STRONGLY recommended
* that application developers make use of the localization features available
* within the BlackBerry development platform to ensure a seamless application
* experience across a variety of languages and geographies.  For more information
* on localizing your application, please refer to the BlackBerry Java Development
* Environment Development Guide associated with this release.
*/

package com.rim.samples.device.bluetoothdemo;

import java.io.IOException;

import net.rim.device.api.bluetooth.BluetoothSerialPort;
import net.rim.device.api.bluetooth.BluetoothSerialPortInfo;
import net.rim.device.api.bluetooth.BluetoothSerialPortListener;
import net.rim.device.api.command.Command;
import net.rim.device.api.command.CommandHandler;
import net.rim.device.api.command.ReadOnlyCommandMetadata;
import net.rim.device.api.system.Characters;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.component.Status;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.util.Arrays;
import net.rim.device.api.util.DataBuffer;
import net.rim.device.api.util.StringProvider;

/**
* This class handles the bluetooth communication between two devices.
* Connecting, waiting for a connection, sending and receiving messages and
* displaying the information sent between the two devices are all handled by
* this class.
*/
public class SPPScreen extends MainScreen implements
        BluetoothSerialPortListener {
    private RichTextField _rtf;
    private final StringBuffer _data;
    private final byte[] _receiveBuffer = new byte[1024];
    private BluetoothSerialPort _port;
    private boolean _loopback;
    private static boolean _dataSent = true;
    private String _deviceName;
    private final DataBuffer _db;

    /**
     * Constructs a serial port connection screen.
     *
     * @param info
     *            The information describing the bluetooth serial port to
     *            connect to. If 'null' then a new serial port is opened on this
     *            device.
     */
    public SPPScreen(final BluetoothSerialPortInfo info) {
        // Fill an lk array with the 'a' character.
        Arrays.fill(_receiveBuffer, (byte) 'a');

        // Initialize the buffers
        _data = new StringBuffer();
        _db = new DataBuffer();

        try {
            if (info == null) {
                // Open a port to listen for incoming connections
                _rtf =
                        new RichTextField(
                                "Connect external device and then type something...",
                                Field.NON_FOCUSABLE);
                _port =
                        new BluetoothSerialPort(
                                "Hi there",
                                BluetoothSerialPort.BAUD_115200,
                                BluetoothSerialPort.DATA_FORMAT_PARITY_NONE
                                        | BluetoothSerialPort.DATA_FORMAT_STOP_BITS_1
                                        | BluetoothSerialPort.DATA_FORMAT_DATA_BITS_8,
                                BluetoothSerialPort.FLOW_CONTROL_NONE, 1024,
                                1024, this);
                _deviceName = "unknown";
            } else {
                // Connect to the selected device
                _rtf =
                        new RichTextField("Type something...",
                                Field.NON_FOCUSABLE);
                _port =
                        new BluetoothSerialPort(
                                info,
                                BluetoothSerialPort.BAUD_115200,
                                BluetoothSerialPort.DATA_FORMAT_PARITY_NONE
                                        | BluetoothSerialPort.DATA_FORMAT_STOP_BITS_1
                                        | BluetoothSerialPort.DATA_FORMAT_DATA_BITS_8,
                                BluetoothSerialPort.FLOW_CONTROL_NONE, 1024,
                                1024, this);
                _deviceName = info.getDeviceName();
            }
        } catch (final IOException ex) {
            BluetoothDemo.errorDialog(ex.toString());
        }

        add(_rtf);

        // Closes the screen
        final MenuItem closeSP =
                new MenuItem(new StringProvider("Close serial port"), 0x230010,
                        0);
        closeSP.setCommand(new Command(new CommandHandler() {
            /**
             * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
             *      Object)
             */
            public void execute(final ReadOnlyCommandMetadata metadata,
                    final Object context) {
                close();
            }
        }));

        // Displays the DTR line's state
        final MenuItem dtr =
                new MenuItem(new StringProvider("Get DTR"), 0x230020, 1);
        dtr.setCommand(new Command(new CommandHandler() {
            /**
             * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
             *      Object)
             */
            public void execute(final ReadOnlyCommandMetadata metadata,
                    final Object context) {
                try {
                    Status.show("DTR: " + _port.getDtr());
                } catch (final IOException ioex) {
                    Status.show("");
                    BluetoothDemo
                            .errorDialog("BluetoothSerialPort#getDtr() threw "
                                    + ioex.toString());
                }
            }
        }));

        // Turns DSR on
        final MenuItem dsrOn =
                new MenuItem(new StringProvider("DSR on"), 0x230030, 2);
        dsrOn.setCommand(new Command(new CommandHandler() {
            /**
             * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
             *      Object)
             */
            public void execute(final ReadOnlyCommandMetadata metadata,
                    final Object context) {
                Status.show("DSR on");
                try {
                    _port.setDsr(true);
                } catch (final IOException ioex) {
                    Status.show("");
                    BluetoothDemo
                            .errorDialog("BluetoothSerialPort#setDsr(boolean) threw "
                                    + ioex.toString());
                }
            }
        }));

        // Turns DSR off
        final MenuItem dsrOff =
                new MenuItem(new StringProvider("DSR off"), 0x230040, 3);
        dsrOff.setCommand(new Command(new CommandHandler() {
            /**
             * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
             *      Object)
             */
            public void execute(final ReadOnlyCommandMetadata metadata,
                    final Object context) {
                Status.show("DSR off");
                try {
                    _port.setDsr(false);
                } catch (final IOException ioex) {
                    Status.show("");
                    BluetoothDemo
                            .errorDialog("BluetoothSerialPort#setDsr(boolean) threw "
                                    + ioex.toString());
                }
            }
        }));

        // Enables loop back
        final MenuItem enableLoopback =
                new MenuItem(new StringProvider("Enable loopback"), 0x230050, 4);
        enableLoopback.setCommand(new Command(new CommandHandler() {
            /**
             * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
             *      Object)
             */
            public void execute(final ReadOnlyCommandMetadata metadata,
                    final Object context) {
                _loopback = true;
            }
        }));

        // Disables loop back
        final MenuItem disableLoopback =
                new MenuItem(new StringProvider("Disable loopback"), 0x230060,
                        5);
        disableLoopback.setCommand(new Command(new CommandHandler() {
            /**
             * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
             *      Object)
             */
            public void execute(final ReadOnlyCommandMetadata metadata,
                    final Object context) {
                _loopback = false;
            }
        }));

        // Sends 1kb of information to the other device
        final MenuItem send1k =
                new MenuItem(new StringProvider("Send 1k"), 0x230070, 6);
        send1k.setCommand(new Command(new CommandHandler() {
            /**
             * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata,
             *      Object)
             */
            public void execute(final ReadOnlyCommandMetadata metadata,
                    final Object context) {
                writeData(_receiveBuffer, 0, _receiveBuffer.length);
            }
        }));

        // Add menu items to the screen
        addMenuItem(closeSP);
        addMenuItem(dtr);
        addMenuItem(dsrOn);
        addMenuItem(dsrOff);
        addMenuItem(enableLoopback);
        addMenuItem(disableLoopback);
        addMenuItem(send1k);
    }

    /**
     * Alerts the user if a device was connected or if it failed to connect
     *
     * @param success
     *            True if the connection was successful, false otherwise
     * @see net.rim.device.api.bluetooth.BluetoothSerialPortListener#deviceConnected(boolean)
     */
    public void deviceConnected(final boolean success) {
        if (success) {
            Status.show("Bluetooth SPP connected to " + _deviceName);
        } else {
            Status.show("Bluetooth SPP failed to connect to " + _deviceName);
        }
    }

    /**
     * @see net.rim.device.api.bluetooth.BluetoothSerialPortListener#deviceDisconnected()
     */
    public void deviceDisconnected() {
        Status.show("Disconnected from " + _deviceName);
    }

    /**
     * @see net.rim.device.api.bluetooth.BluetoothSerialPortListener#dtrStateChange(boolean)
     */
    public void dtrStateChange(final boolean high) {
        Status.show("DTR: " + high);
    }

    /**
     * @see net.rim.device.api.bluetooth.BluetoothSerialPortListener#dataReceived(int)
     */
    public void dataReceived(final int length) {
        int len;
        try {
            // Read the data that arrived
            if ((len =
                    _port.read(_receiveBuffer, 0,
                            length == -1 ? _receiveBuffer.length : length)) != 0) {
                // If loopback is enabled write the data back
                if (_loopback) {
                    writeData(_receiveBuffer, 0, len);
                } else {
                    if (len == 1 && _receiveBuffer[0] == '\r') {
                        _receiveBuffer[1] = '\n';
                        ++len;
                    }
                }

                // Update the screen with the new data that arrived
                _data.append(new String(_receiveBuffer, 0, len));
                _rtf.setText(_data.toString());
            }
        } catch (final IOException ioex) {
            BluetoothDemo.errorDialog(ioex.toString());
        }
    }

    /**
     * @see net.rim.device.api.bluetooth.BluetoothSerialPortListener#dataSent()
     */
    public void dataSent() {
        // Set the _dataSent flag to true to allow more data to be written
        _dataSent = true;

        // Call sendData in case there is data waiting to be sent
        sendData();
    }

    /*
     * Invoked when a key is pressed
     *
     * @see net.rim.device.api.ui.Screen#keyChar(char,int,int)
     */
    public boolean keyChar(final char key, final int status, final int time) {
        if (!(key == Characters.ESCAPE)) {
            // Send the key if a Bluetooth connection has been established
            if (_port != null) {
                if (key == '\n') {
                    writeData((byte) '\r');
                } else {
                    writeData((byte) key);
                }

                // Update the screen adding the character just pressed
                _data.append(key);
                _rtf.setText(_data.toString());

                return true;
            }
        }

        return super.keyChar(key, status, time);
    }

    /**
     * Writes a byte to the 'send' buffer
     *
     * @param theData
     *            The byte to write to the buffer
     */
    private void writeData(final byte theData) {
        synchronized (_db) {
            _db.write(theData);

            // Call sendData to send the data
            sendData();
        }
    }

    /**
     * Writes data from a source byte array to the 'send' buffer
     *
     * @param theData
     *            The source data to write to the buffer
     * @param offset
     *            The off set in the source data to write to the buffer
     * @param length
     *            The length of the array of bytes to write to the buffer
     */
    private void writeData(final byte[] theData, final int offset,
            final int length) {
        synchronized (_db) {
            _db.write(theData, offset, length);

            // Call sendData to send the data
            sendData();
        }
    }

    /**
     * Sends the data currently stored in the DataBuffer to the other device
     */
    private void sendData() {
        // Ensure we have data to send
        if (_db.getArrayLength() > 0) {
            // Ensure the last write call has resulted in the sending of the
            // data
            // prior to calling write again. Calling write in sequence without
            // waiting
            // for the data to be sent can overwrite existing requests and
            // result in
            // data loss.
            if (_dataSent) {
                try {
                    // Set the _dataSent flag to false so we don't send any more
                    // data until it has been verified that this data was sent.
                    _dataSent = false;

                    synchronized (_db) {
                        // Write out the data in the DataBuffer and reset the
                        // DataBuffer
                        _port.write(_db.getArray(), 0, _db.getArrayLength());
                        _db.reset();
                    }
                } catch (final IOException ioex) {
                    // Reset _dataSent to true so we can attempt another data
                    // write
                    _dataSent = true;
                    BluetoothDemo.errorDialog("Failed to write data: "
                            + ioex.toString());
                }
            } else {
                System.out
                        .println("Can't send data right now, data will be sent after dataSent notify call.");
            }
        }
    }

    /**
     * @see net.rim.device.api.ui.Screen#close()
     */
    public void close() {
        if (_port != null) {
            _port.close();
        }
        super.close();
    }
}
TOP

Related Classes of com.rim.samples.device.bluetoothdemo.SPPScreen

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.