Android bluetooth обмен данными

Bluetooth в Android Studio

Понадобилось мне как то приложение на телефон с OS Android, для работы с моим устройством на микроконтроллере через Bluetooth. И вот я уже погрузился в изучение Bluetooth в android studio.

Составим простой алгоритм работы:

  1. При запуске приложения на телефоне, отобразим все Bluetooth устройства, которые уже спарены с телефоном.
  2. Организуем поиск новых устройств.
  3. Далее, по нажатию на устройство в списке, сделаем спаривание с этим устройством ( конечно же не для того, что бы появились маленькие Bluetooth –ики, этого требует протокол работы bluetooth)
  4. Создадим класс для подключение устройств друг с другом по протоколу SPP.

Что ж, план намечен приступаем к действию. Так как статья получается довольно обширная, по этому 3 и 4 пункты опишем в следующей статье.

Включение Bluetooth в телефоне

Что бы начать работать с Bluetooth первым делом его надо включить. Рассмотрим функцию реализующую проверку на включение Bluetooth, и если выключен, предлагает пользователю включить его.

public boolean BluetoothON() < if (!bleAdapter.isEnabled()) < Intent turnOn = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) < return false; >startActivity(turnOn); > else < return true; >return false; >

Здесь, первым делом мы проверяем есть ли у нас в системе Bluetooth адаптер. Если есть, создаем intent с действием на включение блютуза. Так же нам надо проверить есть ли разрешение на работу с блютуз в манифесте. Результатом работы кода будет следующий рисунок.

android studio bluetooth on

Bluetooth в Android Studio: показываем сопряженные устройства

Рассмотрим данный вопрос на примере приведенного ниже кода.

public void GetPairDevise(ArrayList list, BluetoothAdapter bluetoothAdapter) < if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) < // Выдать сообщение о ошибке return; >Set pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) < for (BluetoothDevice device : pairedDevices) < arrayNewDevice.add(device); list.add(device.getName() + " - " + device.getAddress()); >> >

И так, функция принимает на вход переменную типа ArrayList. В этот массив мы помещаем найденные в системе устройства.

Вторым параметром наш BluetoothAdapter. По сути это наш физический модуль Bluetooth в телефоне. Узнаем о его присутствии через функцию:

getDefaultAtapter();

BluetoothAdapter bleAdapter = BluetoothAdapter.getDefaultAdapter();

Далее необходимо проверить, есть ли необходимые разрешение в нашем файле Манифесте. Без них Bluetooth работать не будет.

getBondedDevices(),

получаем все сопряженные устройства.

Set pairedDevices = bluetoothAdapter.getBondedDevices();

Далее в цикле проходим по всему сету и добавляем наши устройства в массив для дальнейшей работы и в список отображение. На картинке ниже, результат работы нашей функции.

Bluetooth pair

Bluetooth в android studio: поиск устройств

Поиск новых устройств запускает функция bluetoothAdapter.startDiscovery() . Результат работы будет в обработчике событий BroadcastResiver . Это класс в котором идет обработка сообщений.

Посмотрим нижеприведенный код. Сначала мы очистим наши списки. Далее проверим разрешение в манифесте и запустим функцию bluetoothAdapter.startDiscovery(). Инициируем два события: поиск устройств и окончание поиска устройств. После этого регистрируем каждое событие Bluetooth.

public void GetScanDevise(BluetoothAdapter mYBluetoothAdapter) < if (listNewDeviceAdapter.getCount() != 0) listNewDeviceAdapter.clear(); arrayNewDevice.clear(); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) < return; >myBleAdapter.startDiscovery(); IntentFilter myFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mResiver, myFilter); myFilter = new IntentFilter((BluetoothAdapter.ACTION_DISCOVERY_FINISHED)); registerReceiver(mResiver, myFilter); > private final BroadcastReceiver mResiver = new BroadcastReceiver() < @SuppressLint("MissingPermission") @Override public void onReceive(Context context, Intent intent) < String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) < myDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (myDevice.getName() != null) < arrayNewDevice.add(myDevice); deviseScanList.add(myDevice.getName() + " - " + myDevice.getAddress()); listDevice.setAdapter(listNewDeviceAdapter); >> else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) < myBleAdapter.cancelDiscovery(); >> >;

Внимание! Что бы вновь начать поиск новых устройств, необходимо убедиться, что предыдущий поиск остановлен.

Читайте также:  Перкуссионный массажер hyperice hypervolt bluetooth

Также можно перед стартом нового поиска сначала вызвать функцию

bleAdapter.cancelDiscovery();

Результат работы кода будет представлен на картинке ниже.

Bluetooth scan

Внимание! Данный программный код представлен из реально работающей программы. Описывал все так как понял сам, читая открытые источники. К сожалению я не являюсь программистом Android, по этому говорю честно, данную задачу можно реализовать красивым и правильным кодом. В этой статье описан просто рабочий код и принцип работы с Bluetooth в android studio на языке java.

Источник

Обмен данными Bluetooth

Пример обмена данными Bluetooth

Продолжаем предыдущую статью о работе с Bluetooth в Android Studio. В этой статье рассмотрим обмен данными Bluetooth, через SPP профиль.

Профиль SPP (Serial Port Profile) – предназначен для обмена данными по Bluetooth. SPP профиль дает возможность, соединить два устройства Bluetooth на транспортном уровне. При таком соединении одно из устройств станет мастером, а второе ведомым. На самом деле нам это не так важно, так как все тонкости скрыты разработчиками классов java. Единственное что нам надо запомнить, это то, что SPP профиль, основан на базовом профиле RFCOM.

SPP профиль Bluetooth

После того как мы обнаружили наше устройство и произвели сопряжение. Нам необходимо создать и открыть сокет.

Для создания сокета воспользуемся следующей командой:

device.createInsecureRfcommSocketToServiceRecord(MY_UUID);

device — это наше устройство Bluetooth.

MY_UUID – uuid SPP профиля.

Внимание!
UUID профиля «00001101-0000-1000-8000-00805f9b34fb»

После создания сокета нам необходимо создать подключение командой connect :

Внимание!
Будьте внимательны при использовании метода connect , он блокирует программу, пока не будет установлено соединение или пока не закончится таймаут. Рекомендуется использовать отдельный поток.

Обмен данными Bluetooth: InputStream

Входящим потоком данных в java является InputStream . В java есть два типа потоков, символьный и байтовый потоки. Что бы инициализировать байтовый поток Input, необходимо применить метод сокета:

Обмен данными Bluetooth: OutputStream

Исходящим потоком данных в java является OutputStream . Что бы инициализировать байтовый поток Otput, необходимо применить метод сокета:

Android studio: пример обмена по bluetooth

Создадим новый класс для обмена данными по Bluetooth. Класс наследуем от класса реализующего потоки.

private class ConnectThread extends Thread < private BluetoothSocket mmSocket = null; private boolean isUpdateDate = false; private final Activity mmActivity; private BluetoothAdapter mmAdapter = null; private OutputStream outData = null; private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); public ConnectThread(BluetoothDevice device, BluetoothAdapter adapter, Activity activity) < BluetoothSocket tmp = null; mmAdapter = adapter; mmActivity = activity; try < if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) < return; >//device.getUuids()[0].getUuid() tmp = device.createInsecureRfcommSocketToServiceRecord(MY_UUID); Log.e("TODO", "Сокет создан"); > catch (IOException e) < Log.e("TODO", "Ошибка созадания сокета"); >mmSocket = tmp; > public void setIsUpdate(Boolean data) < isUpdateDate = data; >public void run() < while (isUpdateDate) < if (mServiceBound) < sendData(latitudeToSend + " " + longitudeToSend); try < Thread.sleep(1000); >catch (InterruptedException e) < e.printStackTrace(); >> > > public void connectSSP() < if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) < return; >mmAdapter.cancelDiscovery(); Log.e("TODO", "Завершил поиск даже если небыл включен"); try < Log.e("TODO", "Включаю сокет"); mmSocket.connect(); outData = mmSocket.getOutputStream(); InputStream inData = mmSocket.getInputStream(); AlertDialog dialog = DialogView.getDialog(mmActivity, DialogView.IDD_INFO_CONNECT); dialog.show(); >catch (IOException connectException) < Log.e("TODO", "Не могу подключить SPP", connectException); try < mmSocket.close(); >catch (IOException closeException) < Log.e("TAG", "Не могу закрыть сокет", closeException); >> > public void sendData(String dataStr) < if (isUpdateDate) < try < outData = mmSocket.getOutputStream(); >catch (IOException e) < Log.d("Error", "SSP OUT", e); >byte[] msgBuf = dataStr.getBytes(); try < outData.write(msgBuf); >catch (IOException e) < Log.d("Error", "SSP OUT", e); >> > public void cancel() < try < if (mmSocket != null) < if (mmSocket.isConnected()) mmSocket.close(); >> catch (IOException e) < Log.e("TAG", "Не могу закрыть сокет", e); >//Закрываем поток ConnectThread.interrupted(); > >

Пояснения к коду обмена данными по Bluetooth

При инициализации класса в конструктор класса необходимо передать наше устройство Bluetooth (устройство с которым будем обмениваться данными) и наш Bluetooth adapter (физический блютуз).

Читайте также:  Bluetooth adapter ks bta100

Метод класса setIsUpdate , позволяет установить флаг, для старта передачи данных, если флаг не установлен, то передача не идет.

Метод connectSSP реализует соединение с устройством Bluetooth через профиль SPP. После установки соединения пользователь получит диалоговое сообщение о успешном соединении.

sendData метод класса, который принимает на вход строку для отправки другому устройству. Затем эта строка конвертируется в массив байт и отправляется на передачу.

Последний метод cancel . Данный метод необходимо применять, когда мы завершаем работу с сокетом.

Чтобы начать работу с классом, необходимо из основного активити создать объект класса и вызвать метод Start .

ConnectThread connectBLE = new ConnectThread(btConnectDevice, mAdapter, MainActivity.this); connectBLE.start();

Источник

How to send/receive messages via bluetooth android studio

I am trying to create an app that allows a string to be sent from one Android phone to another. The code for this is provided below. However, it isn’t working as I keep getting exceptions from the try catch piece of code under the pairDevice() section. Does anyone know why I might be getting this?

import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.os.ParcelUuid; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Scanner; import java.util.Set; public class MainActivity extends AppCompatActivity < InputStream inStream; OutputStream outputStream; private static final int REQUEST_ENABLE_BT = 1; public void pairDevice() < BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) < Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);>Set pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) < Object[] devices = pairedDevices.toArray(); BluetoothDevice device = (BluetoothDevice) devices[0]; ParcelUuid[] uuid = device.getUuids(); try < BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid[0].getUuid()); socket.connect(); Toast.makeText(this, "Socket connected", Toast.LENGTH_LONG).show(); outputStream = socket.getOutputStream(); inStream = socket.getInputStream(); >catch (IOException e) < Toast.makeText(this, "Exception found", Toast.LENGTH_LONG).show(); >> > public void SendMessage(View v) < EditText outMessage = (EditText) findViewById(R.id.editText); try < if (outputStream != null) outputStream.write(outMessage.toString().getBytes()); TextView displayMessage = (TextView) findViewById(R.id.textView); Scanner s = new Scanner(inStream).useDelimiter("\\A"); displayMessage.setText(s.hasNext() ? s.next() : ""); >catch (IOException e) Toast.makeText(this,"No output stream", Toast.LENGTH_LONG).show(); > @Override protected void onCreate(Bundle savedInstanceState)

3 Answers 3

I have made few changes to your app:-

Firstly, I shifted the code responsible for creating the Bluetooth connection to ConnectThread .

2) Added AcceptThread responsible for listening incoming connections and ConnectedThread maintaining the BTConnection, Sending the data, and receiving incoming data through input/output streams respectively. 3) Created 2 buttons to start ConnectThread and AcceptThread.

NOTE: Make sure both the devices are paired and the device that you are trying to connect to is at the top of the list(or just remove all the paired devices from both the devices and only pair the devices that you want to connect). Also, you must start the AcceptThread before ConnectThread

MAINACTIVITY.JAVA

public class MainActivity extends AppCompatActivity < private static final UUID MY_UUID_INSECURE = UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66"); private static final int REQUEST_ENABLE_BT = 1; BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); private BluetoothDevice mmDevice; private UUID deviceUUID; ConnectedThread mConnectedThread; private Handler handler; String TAG = "MainActivity"; EditText send_data; TextView view_data; StringBuilder messages; public void pairDevice(View v) < SetpairedDevices = bluetoothAdapter.getBondedDevices(); Log.e("MAinActivity", "" + pairedDevices.size() ); if (pairedDevices.size() > 0) < Object[] devices = pairedDevices.toArray(); BluetoothDevice device = (BluetoothDevice) devices[0]; //ParcelUuid[] uuid = device.getUuids(); Log.e("MAinActivity", "" + device ); //Log.e("MAinActivity", "" + uuid) ConnectThread connect = new ConnectThread(device,MY_UUID_INSECURE); connect.start(); >> private class ConnectThread extends Thread < private BluetoothSocket mmSocket; public ConnectThread(BluetoothDevice device, UUID uuid) < Log.d(TAG, "ConnectThread: started."); mmDevice = device; deviceUUID = uuid; >public void run() < BluetoothSocket tmp = null; Log.i(TAG, "RUN mConnectThread "); // Get a BluetoothSocket for a connection with the // given BluetoothDevice try < Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: " +MY_UUID_INSECURE ); tmp = mmDevice.createRfcommSocketToServiceRecord(MY_UUID_INSECURE); >catch (IOException e) < Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage()); >mmSocket = tmp; // Make a connection to the BluetoothSocket try < // This is a blocking call and will only return on a // successful connection or an exception mmSocket.connect(); >catch (IOException e) < // Close the socket try < mmSocket.close(); Log.d(TAG, "run: Closed Socket."); >catch (IOException e1) < Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage()); >Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE ); > //will talk about this in the 3rd video connected(mmSocket); > public void cancel() < try < Log.d(TAG, "cancel: Closing Client Socket."); mmSocket.close(); >catch (IOException e) < Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage()); >> > private void connected(BluetoothSocket mmSocket) < Log.d(TAG, "connected: Starting."); // Start the thread to manage the connection and perform transmissions mConnectedThread = new ConnectedThread(mmSocket); mConnectedThread.start(); >private class ConnectedThread extends Thread < private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) < Log.d(TAG, "ConnectedThread: Starting."); mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; try < tmpIn = mmSocket.getInputStream(); tmpOut = mmSocket.getOutputStream(); >catch (IOException e) < e.printStackTrace(); >mmInStream = tmpIn; mmOutStream = tmpOut; > public void run() < byte[] buffer = new byte[1024]; // buffer store for the stream int bytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs while (true) < // Read from the InputStream try < bytes = mmInStream.read(buffer); final String incomingMessage = new String(buffer, 0, bytes); Log.d(TAG, "InputStream: " + incomingMessage); runOnUiThread(new Runnable() < @Override public void run() < view_data.setText(incomingMessage); >>); > catch (IOException e) < Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() ); break; >> > public void write(byte[] bytes) < String text = new String(bytes, Charset.defaultCharset()); Log.d(TAG, "write: Writing to outputstream: " + text); try < mmOutStream.write(bytes); >catch (IOException e) < Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() ); >> /* Call this from the main activity to shutdown the connection */ public void cancel() < try < mmSocket.close(); >catch (IOException e) < >> > public void SendMessage(View v) < byte[] bytes = send_data.getText().toString().getBytes(Charset.defaultCharset()); mConnectedThread.write(bytes); >@Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); send_data =(EditText) findViewById(R.id.editText); view_data = (TextView) findViewById(R.id.textView); if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) < Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); >> public void Start_Server(View view) < AcceptThread accept = new AcceptThread(); accept.start(); >private class AcceptThread extends Thread < // The local server socket private final BluetoothServerSocket mmServerSocket; public AcceptThread()< BluetoothServerSocket tmp = null ; // Create a new listening server socket try< tmp = bluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord("appname", MY_UUID_INSECURE); Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE); >catch (IOException e) < Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() ); >mmServerSocket = tmp; > public void run()< Log.d(TAG, "run: AcceptThread Running."); BluetoothSocket socket = null; try< // This is a blocking call and will only return on a // successful connection or an exception Log.d(TAG, "run: RFCOM server socket start. "); socket = mmServerSocket.accept(); Log.d(TAG, "run: RFCOM server socket accepted connection."); >catch (IOException e) < Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() ); >//talk about this is in the 3rd if(socket != null) < connected(socket); >Log.i(TAG, "END mAcceptThread "); > public void cancel() < Log.d(TAG, "cancel: Canceling AcceptThread."); try < mmServerSocket.close(); >catch (IOException e) < Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage() ); >> > 

ACTIVITY_MAIN.XML

Читайте также:  Отключается bluetooth на iphone

Источник

Оцените статью
Adblock
detector