Для инициализации соединения с удаленным устройствам (устройством, которое держит открытым серверный сокет) вам необходимо получить объект BluetoothDevice, содержащий информацию о нем. Этот объект используется для получения BluetoothSocket и инициализации соединения.
Опишем процедуру соединения: - Получим BluetoothSocket вызвав метод BluetoothDevice.createRfcommSocketToServiceRecord(UUID). Значение параметра UUID должно совпадать с значением, указанным при вызове listenUsingRfcommWithServiceRecord сервера.
- Инициализируем соединение, вызвав метод connect(). После вызова этого метода система будет выполнять SDP поиск на удаленном устройстве, чтобы сопоставить UUID. В случае успеха при условии подтверждения запроса со стороны сервера будет открыт RFCOMM канал. Это блокирующий вызов. Если по каким-то причинам соединение сорвется или выйдет timeout (около 12 секунд), будет сгенерировано исключение.
Как и в случае с accept, метод connect() следует выполнять в отдельном потоке, в противном случае может произойти подвисание интерфейса.
Замечание. Прежде чем вызывать connect() убедитесь, что в данный момент не происходит сканирование с целью поиска доступных устройств. В случае одновременного выполнения этих операций соединение будет устанавливаться намного медленнее, и вы рискуете не уложиться в timeout.
Приведем пример клиентского приложения, инициализирующего соединение
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// используем вспомогательную переменную, которую в дальнейшем
// свяжем с mmSocket,
BluetoothSocket tmp = null;
mmDevice = device;
// получаем BluetoothSocket чтобы соединиться с BluetoothDevice
try {
// MY_UUID это UUID, который используется и в сервере
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Отменяем сканирование, поскольку оно тормозит соединение
mBluetoothAdapter.cancelDiscovery();
try {
// Соединяемся с устройством через сокет.
// Метод блокирует выполнение программы до
// установки соединения или возникновения ошибки
mmSocket.connect();
} catch (IOException connectException) {
// Невозможно соединиться. Закрываем сокет и выходим.
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// управлчем соединением (в отдельном потоке)
manageConnectedSocket(mmSocket);
}
/** отмена ожидания сокета */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
} Для остановки сканирования эфира вызывается метод cancelDiscovery(). Перед вызовом этого метода можно проверить идет ли сканирование с помощью isDiscovering().
После завершения работы с BluetoothSocket всегда вызывайте метод close(). Это поможет сэкономить ресурсы телефона.
Передача данныхПосле успешного соединения, каждое из соединенных устройств имеет объект BluetoothSocket с помощью которого легко реализовать передачу/прием данных:
- С помощью методов getInputStream() и getOutputStream() полуить объекты InputStream и OutputStream, управляющие передачей через сокет.
- Читать и писать данные в поток с помощью методов read(byte[]) и write(byte[]).
Вы должны использовать отдельный поток для чтения и записи данных. Это важно, поскольку методы read(byte[]) и write(byte[]) являются блокирующими и их вызов в основном потоке может парализовать вашу программу. Главный цикл в этом отдельном потоке должен считывать данные из InputStream. Для записи в OutputStream имеет смысл создать отдельный public метод. private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Получить входящий и исходящий потоки данных
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // буферный массив
int bytes; // bytes returned from read()
// Прослушиваем InputStream пока не произойдет исключение
while (true) {
try {
// читаем из InputStream
bytes = mmInStream.read(buffer);
// посылаем прочитанные байты главной деятельности
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Вызываем этот метод из главной деятельности, чтобы отправить данные
удаленному устройству */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Вызываем этот метод из главной деятельности,
чтобы разорвать соединение */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
} В конструкторе создаются объекты для работы с потоками данных, после чего поток оживает входящие данные. После того как прочитан очередной блок данных из входящего потока он посылается в главную деятельность посредствам вызова метода Handler родительского класса. Для отправки данных из главной деятельности просто вызывается метод write(). Внутри этого публичного метода происходит вызов write(byte[]). Метод close() также можно вызвать из главной деятельности. Он разрывает соединение.
Перевод: Александр Ледков Взято с http://www.mobilab.ru
|
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.