Android: Не получается отправить сообщение по Bluetooth
Сделал клиентское приложение для отправки сообщений по bluetooth на терминал-сервер. Поиск удаленного устройства и соединения проходя успешно, входящие сообщения успешно получаю, а исходящие сообщения не доходят до удаленного устройства, но ошибок никаких нет, не понимаю в чем дело, может кто подскажет?
MainActivity.java
package com.android.putenproject;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.bluetooth.*;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
public static Handler handlerMain;
private interface MessageConstants {
public static final int MESSAGE_READ = 0;
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_TOAST = 2;
}
Toast toaster;
BluetoothAdapter bluetooth;
private static final int REQUEST_ENABLE_BT = 1;
private static final int REQUEST_ASK_GPS = 2;
TextView statusBT;
TextView messageTW;
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bluetooth = BluetoothAdapter.getDefaultAdapter();
stateBT();
editText = findViewById(R.id.editTextSent);
handlerMain = new Handler(){
public void handleMessage(android.os.Message msg){
switch (msg.what){
case MessageConstants.MESSAGE_READ:
String readMessage = (String)msg.obj;
if (msg.arg1 > 0) {
messageTW = findViewById(R.id.messageTextView);
messageTW.clearComposingText();
messageTW.setText(readMessage);
showToast("Принято сообщение: \"" + readMessage + "\"");
}
break;
case MessageConstants.MESSAGE_WRITE:
showToast("Отправка сообщения");
break;
case MessageConstants.MESSAGE_TOAST:
showToast("Ошибка отправки");
break;
}
}
};
}
//метод показа высплывающего уведомления
public void showToast(String message) {
toaster = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT);
toaster.show();
}
//Проверка наличия модуля Bluetooth
boolean checkModuleBT() {
if (bluetooth != null) {
// bluetooth модуль присутствует
return true;
} else {
// bluetooth модуль отсутствует/не поддерживается
showToast("Ваше устройство не поддерживает технологию Bluetooth");
return false;
}
}
//Отображение статуса Bluetooth
void stateBT() {
if (checkModuleBT()) {
int state = bluetooth.getState();
statusBT = findViewById(R.id.statusBTTextView);
if (state == 10) {
statusBT.setText("Bluetooth OFF");
statusBT.setTextColor(Color.parseColor("#FFFF0000"));
} else if (state == 12) {
statusBT.setText("Bluetooth ON");
statusBT.setTextColor(Color.parseColor("#FF00FF04"));
if (ConnectThread.getNameDevice() != null && ConnectThread.getSuccess() == true) {
statusBT = findViewById(R.id.statusBTTextView);
statusBT.setText("Bluetooth connected to " + ConnectThread.getNameDevice());
statusBT.setTextColor(Color.parseColor("#FF00FF04"));
} else {
//statusBT.setText("Bluetooth disconnected" );
}
} else {
//ничего не делать
}
} else {
statusBT = findViewById(R.id.statusBTTextView);
statusBT.setText("Your device not support Bluetooth");
statusBT.setTextColor(Color.parseColor("#FFFF0000"));
}
}
//Событие на кнопку "Change Device"
public void onClickSearchBT(View view) {
if (checkModuleBT()) {
if (bluetooth.isEnabled()) {
//Bluetooth включен. Работаем.
askAccept(); //Вызов метода запроса доступа к местоположению
} else {
//Bluetooth выключен. Пердложим пользователю включить его.
Intent enableBTIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBTIntent, REQUEST_ENABLE_BT);
stateBT();
}
}
}
//События при включенном Bluetooth
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENABLE_BT && resultCode == RESULT_OK) {
askAccept(); //вызов запроса на доступ к GPS
} else {
//ничего не делать
}
}
//События, происходящие при развертывании приложения
@Override
protected void onResume() {
super.onResume();
stateBT();
}
//Запрос на доступ к местоположению
void askAccept() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//если Android Q
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE
}, REQUEST_ASK_GPS);
} else {
//если другая версия Android
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE
}, REQUEST_ASK_GPS);
}
}
//Проверка активности GPS-модуля
public static boolean checkGPSStatus(Context context) {
LocationManager manager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
return statusOfGPS;
}
//События при предоставлении доступа к метоположению
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_ASK_GPS && grantResults[0] == 0) {
//проверка активности модуля GPS
if (!checkGPSStatus(this)) {
//если GPS выключен, то вызвать активность GPS для включения
Intent gpsOptionsIntent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(gpsOptionsIntent);
} else {
//если GPS включен, то перейти в активность BT_Devices_Activity
Intent intent = new Intent(MainActivity.this, BT_Devices_Activity.class);
startActivity(intent);
}
}
}
//Событие по кнопке Отправить
public void onClickButtonSent(View view) {
////
if (ConnectThread.getSuccess()) {
String message = editText.getText().toString();
ConnectedThread.write(message);
Log.i("TESTBT", "edittext = " + message);
} else {
showToast("Нет соединения с удаленным устройством");
}
}
}
BT_Device_Activity.java
package com.android.putenproject;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.bluetooth.*;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;
public class BT_Devices_Activity extends AppCompatActivity {
private ListView listView;
private ArrayList mDeviceList = new ArrayList<String>();
private ArrayList <BluetoothDevice> mDeviceListTest = new ArrayList<BluetoothDevice>();
private BluetoothAdapter mBluetoothAdapter;
//////////////////
private ConnectThread connectThread;
public static Handler handler;
/////////сообщения Handler
final int STATUS_CONNECTION_SUCCESS_TRUE = 0;
final int STATUS_CONNECTION_SUCCESS_FALSE = 1;
/////////
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bt_devices);
setTitle("SearchDevices");
listView = (ListView) findViewById(R.id.listViewDevices);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.startDiscovery();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
handler = new Handler(){
public void handleMessage(android.os.Message msg){
switch (msg.what){
case STATUS_CONNECTION_SUCCESS_TRUE:
showToast("Соединение установлено");
break;
case STATUS_CONNECTION_SUCCESS_FALSE:
showToast("Не удалось соединиться");
break;
}
}
};
}
@Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
mBluetoothAdapter.cancelDiscovery();
}
public void showToast(String message){
Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT);
toast.show();
}
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
mDeviceList.add("..." + device.getName()+ "\n" + device.getAddress());
mDeviceListTest.add(device);
listView.setAdapter(new ArrayAdapter<Object>(context, android.R.layout.simple_list_item_1, mDeviceList));
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int pos = position + 1;
Log.i("TESTBT", "Нажатие на номер " + pos + ", имя устройства " + mDeviceList.get(position));
mBluetoothAdapter.cancelDiscovery();
Log.i("TESTBT", "прошло условие");
BluetoothDevice device = mDeviceListTest.get(position);
Log.i("TESTBT", "Полученное имя device " + device.getName());
if (device != null){
//по нажатию на выбранное устройство просиходит создание объекта класса и запуск
connectThread = new ConnectThread(device);
connectThread.start();
Log.i("TESTBT", "Соединение...");
showToast("Соединение...");
}
}
});
}
};
}
ConnectThread.java
package com.android.putenproject;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
public class ConnectThread extends Thread {
private static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
private static BluetoothSocket bluetoothSocket = null;
private static boolean success = false;
private static ConnectedThread connectedThread;
final int STATUS_CONNECTION_SUCCESS_TRUE = 0;
final int STATUS_CONNECTION_SUCCESS_FALSE = 1;
//////////////////////
public static String getNameDevice(){
try{
Log.i("TESTBT", "getName = " + bluetoothSocket.getRemoteDevice().getName());
return bluetoothSocket.getRemoteDevice().getName();
} catch (Exception e){
return null;
}
}
/////////////////////
public static boolean getSuccess(){
return success;
}
/////////////////////////////////
public ConnectThread(BluetoothDevice device) {
try {
bluetoothSocket = device.createRfcommSocketToServiceRecord(myUUID);
Log.i("TESTBT", "bluetoothSocket = " + bluetoothSocket);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
bluetoothSocket.connect();
success = true;
Log.i("TESTBT", "Cоединение установлено");
BT_Devices_Activity.handler.sendEmptyMessage(STATUS_CONNECTION_SUCCESS_TRUE);
} catch (IOException e) {
e.printStackTrace();
success = false;
Log.i("TESTBT", "Не удалось соединиться");
BT_Devices_Activity.handler.sendEmptyMessage(STATUS_CONNECTION_SUCCESS_FALSE);
cancel();
}
if (success) {
//TODO создаем экземлпяр класса
connectedThread = new ConnectedThread(bluetoothSocket);
connectedThread.start();
Log.i("TESTBT", "Соединение установлено с : " + bluetoothSocket.getRemoteDevice().getName());
Log.i("TESTBT", "Программа работает");
}
}
public void cancel() {
try {
bluetoothSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ConnectedThread.java
package com.android.putenproject;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static com.android.putenproject.MainActivity.handlerMain;
public class ConnectedThread extends Thread {
private static final String TAG = "MY_APP_DEBUG_TAG";
private static InputStream inputStream = null;
private static OutputStream outputStream = null;
private interface MessageConstants {
public static final int MESSAGE_READ = 0;
public static final int MESSAGE_WRITE = 1;
public static final int MESSAGE_TOAST = 2;
}
public ConnectedThread(BluetoothSocket bluetoothSocket) {
try {
inputStream = bluetoothSocket.getInputStream();
outputStream = bluetoothSocket.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//Считывание информации с BT
byte[] mmBuffer = new byte[256]; // Буффер для хранения потока
int numBytes; // количество байт, возвращаемые из потока read()
// Keep listening to the InputStream until an exception occurs.
while (true) {
try {
// Read from the InputStream.
numBytes = inputStream.read(mmBuffer);
String readMessage = new String(mmBuffer, 0, numBytes);
// Send the obtained bytes to the UI activity.
handlerMain.obtainMessage(MessageConstants.MESSAGE_READ, numBytes, -1,
readMessage).sendToTarget();
} catch (IOException e) {
Log.d(TAG, "Input stream was disconnected", e);
break;
}
}
}
//Метод отправкии сообщений
public static void write(String command) {
byte[] bytes = command.getBytes();
if (outputStream != null){
try {
outputStream.write(bytes);
outputStream.flush();
// Share the sent message with the UI activity.
handlerMain.obtainMessage(MessageConstants.MESSAGE_WRITE, -1, -1, bytes).sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Error occurred when sending data", e);
handlerMain.obtainMessage(MessageConstants.MESSAGE_TOAST, -1, -1, bytes).sendToTarget();
}
}
}
public void cancel() {
try {
inputStream.close();
inputStream.close();
} catch (IOException e) {
Log.e(TAG, "Could not close the connect socket", e);
}
}
}