Проблема с подключением Bluetooth при сопряжении приложения Android с Raspberry PiJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Проблема с подключением Bluetooth при сопряжении приложения Android с Raspberry Pi

Сообщение Anonymous »

Я работаю над приложением для Android, которое подключается к Bluetooth-устройству на базе Raspberry Pi с помощью последовательного соединения Bluetooth. Я пытаюсь отправить уведомления на устройство после того, как оно будет сопряжено, но у меня возникают проблемы: соединение не устанавливается должным образом, и устройство Bluetooth не отвечает должным образом.
Он отображается в настройках Bluetooth моего Android, и когда я нажимаю, он подключается без необходимости ввода ключа доступа, но затем на Pi он показывает, что он больше не подключен, но все еще подключен к телефону, но не подключен.
Настройка Raspberry Pi: у меня есть настроил Raspberry Pi для обнаружения и сопряжения с помощью команд bluetoothctl без ключа доступа, и он автоматически запускается при загрузке: он также настроен как «Устройство», а не как хост.

Код: Выделить всё

    bash
Copy code
sudo bluetoothctl
power on
agent NoInputNoOutput
default-agent
discoverable on
pairable on
Это моя Java-версия FirstFragment для Android Studio:

Код: Выделить всё

package com.aaadev.myapplication;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.fragment.app.Fragment;
import com.aaadev.myapplication.databinding.FragmentFirstBinding;

import java.util.ArrayList;
import java.util.Set;

public class FirstFragment extends Fragment {
private Button buttonSendNotification;

private static final int REQUEST_BLUETOOTH_PERMISSIONS = 1;
private FragmentFirstBinding binding;
private BluetoothAdapter bluetoothAdapter;
private ArrayList deviceList;
private ArrayList pairedDevicesList;
private ListView listViewDevices;
private static final String CHANNEL_ID = "app_push_notification_channel";

@Override
public View onCreateView(@NonNull android.view.LayoutInflater inflater, @Nullable android.view.ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentFirstBinding.inflate(inflater, container, false);
return binding.getRoot();
}

@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
buttonSendNotification = binding.buttonSendNotification;

listViewDevices = binding.listViewDevices;
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
deviceList = new ArrayList();
pairedDevicesList = new ArrayList();
// Check Bluetooth permissions and list paired devices
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.BLUETOOTH_CONNECT}, REQUEST_BLUETOOTH_PERMISSIONS);
} else {
listPairedDevices();
}
} else {
listPairedDevices();
}
// Button click listener to send a push notification
buttonSendNotification.setOnClickListener(v -> sendPushNotification());
// ListView item click listener to select a device
listViewDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
BluetoothDevice selectedDevice = pairedDevicesList.get(position);
@SuppressLint("MissingPermission") String deviceName = selectedDevice.getName();

if (deviceName != null &&  deviceName.contains("Pi")) {
// Start NotificationService and pass the device's address
Intent intent = new Intent(getActivity(), NotificationService.class);
intent.putExtra("device_address", selectedDevice.getAddress());
getActivity().startService(intent);
Toast.makeText(getContext(), "Connecting to " + deviceName, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "Selected device is not a Pi device", Toast.LENGTH_SHORT).show();
}
}
});
}

@SuppressLint("MissingPermission")
private void listPairedDevices() {
if (bluetoothAdapter != null) {
@SuppressLint("MissingPermission") Set pairedDevices = bluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
pairedDevicesList.add(device);
deviceList.add(device.getName() + "\n" + device.getAddress());
}
ArrayAdapter adapter = new ArrayAdapter(getContext(), android.R.layout.simple_list_item_1, deviceList);
listViewDevices.setAdapter(adapter);
} else {
Toast.makeText(getContext(), "No paired devices found", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getContext(), "Bluetooth not supported on this device", Toast.LENGTH_SHORT).show();
}
}

@SuppressLint("MissingPermission")
private void sendPushNotification() {
createNotificationChannel();

NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext(), CHANNEL_ID)
.setSmallIcon(android.R.drawable.stat_notify_chat)
.setContentTitle("New Push Notification")
.setContentText("This is a push notification from YapYap!")
.setPriority(NotificationCompat.PRIORITY_HIGH);

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getContext());
notificationManager.notify(1, builder.build());
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_BLUETOOTH_PERMISSIONS) {
if (grantResults.length > 0 &&  grantResults[0] == PackageManager.PERMISSION_GRANTED) {
listPairedDevices();
} else {
Toast.makeText(getContext(), "Bluetooth permission denied", Toast.LENGTH_SHORT).show();
}
}
}

private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "App Push Notifications";
String description = "Channel for app push notifications";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);

NotificationManager notificationManager = getContext().getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
}

@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

Вот уведомление Sevrer.java:

Код: Выделить всё

package com.aaadev.myapplication;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;

import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;

public class NotificationService extends Service {

private static final String CHANNEL_ID = "notification_service_channel";
public static final String ACTION_CONNECTION_STATUS = "com.aaadev.myapplication.CONNECTION_STATUS";
public static final String EXTRA_CONNECTION_SUCCESS = "connection_success";

private BluetoothSocket bluetoothSocket;
private OutputStream outputStream;

@Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
String deviceAddress = intent.getStringExtra("device_address");
if (deviceAddress != null) {
new Thread(() -> connectToDevice(deviceAddress)).start(); // Run on background thread
}

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Pi Notification Service")
.setContentText("Attempting to connect to Pi device...")
.setSmallIcon(android.R.drawable.stat_notify_chat)
.build();

startForeground(1, notification);
return START_NOT_STICKY;
}

private void connectToDevice(String address) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

if (!checkBluetoothPermission()) {
Log.e("NotificationService", "Missing BLUETOOTH_CONNECT permission.");
broadcastConnectionStatus(false);
stopSelf();
return;
}

BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
Log.d("NotificationService", "Attempting to connect to device: " + device.getName() + " (" + address + ")");

try {
Log.d("NotificationService", "Creating BluetoothSocket...");
bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"));

Log.d("NotificationService", "Connecting to BluetoothSocket...");
bluetoothSocket.connect();  // Attempt to connect

Log.d("NotificationService", "BluetoothSocket connected successfully!");
outputStream = bluetoothSocket.getOutputStream();

// Broadcast success status
broadcastConnectionStatus(true);
} catch (IOException e) {
Log.e("NotificationService", "Connection failed: " + e.getMessage(), e);
handleConnectionFailure();
}
}

private boolean checkBluetoothPermission() {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.S ||
ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED;
}

private void handleConnectionFailure() {
if (bluetoothSocket != null) {
try {
Log.d("NotificationService", "Closing BluetoothSocket due to failure...");
bluetoothSocket.close();
} catch (IOException closeException) {
Log.e("NotificationService", "Failed to close BluetoothSocket: " + closeException.getMessage(), closeException);
}
}

broadcastConnectionStatus(false);
stopSelf();
}

private void broadcastConnectionStatus(boolean success) {
Intent broadcastIntent = new Intent(ACTION_CONNECTION_STATUS);
broadcastIntent.putExtra(EXTRA_CONNECTION_SUCCESS, success);
sendBroadcast(broadcastIntent);
}

private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Notification Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
if (manager != null) {
manager.createNotificationChannel(serviceChannel);
}
}
}

@Override
public void onDestroy() {
super.onDestroy();
try {
if (outputStream != null) outputStream.close();
if (bluetoothSocket != null) bluetoothSocket.close();
} catch (Exception e) {
Log.e("NotificationService", "Error closing resources: "  + e.getMessage(), e);
}
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

В моем списке отображается значок «Pi», и когда я нажимаю на него, во всплывающем сообщении появляется сообщение «Соединение», но выдается эта ошибка:

Код: Выделить всё

Attempting to connect to device: Pi (XX:XX:XX:D2:XX:XX)
2024-12-15 13:53:42.781 27103-27156 NotificationService     com.aaadev.myapplication             D  Creating BluetoothSocket...
2024-12-15 13:53:42.782 27103-27156 NotificationService     com.aaadev.myapplication             D  Connecting to BluetoothSocket...
2024-12-15 13:53:42.782 27103-27156 BluetoothSocket         com.aaadev.myapplication             I  connect() for device XX:XX:XX:XX:5D:XX called by pid: 27103
2024-12-15 13:53:47.172 27103-27196 ProfileInstaller        com.aaadev.myapplication             D  Installing profile for com.aaadev.myapplication
2024-12-15 13:53:47.868 27103-27156 NotificationService     com.aaadev.myapplication             E  Connection failed: read failed, socket might closed or timeout, read ret: -1
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:1054)
at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:1068)
at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:583)
at com.aaadev.myapplication.NotificationService.connectToDevice(NotificationService.java:74)
at com.aaadev.myapplication.NotificationService.lambda$onStartCommand$0$com-aaadev-myapplication-NotificationService(NotificationService.java:43)
at com.aaadev.myapplication.NotificationService$$ExternalSyntheticLambda0.run(Unknown Source:4)
at java.lang.Thread.run(Thread.java:1012)
2024-12-15 13:53:47.868 27103-27156 NotificationService     com.aaadev.myapplication             D  Closing BluetoothSocket due to failure...

Я не знаю, почему Pi не подключается... Мне нужно, чтобы он получал push-уведомления на Pi с телефона от службы переднего плана/фоновой службы.
Сообщите мне, почему появляется эта ошибка.
Заранее спасибо.

Подробнее здесь: https://stackoverflow.com/questions/792 ... spberry-pi
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»