FT8CN/ft8CN/app/src/main/java/com/bg7yoz/ft8cn/bluetooth/BluetoothSerialSocket.java

128 wiersze
4.0 KiB
Java
Executable File

package com.bg7yoz.ft8cn.bluetooth;
/**
* 蓝牙串口的SOCKET
* BG7YOZ
* 2023-03
*/
import android.annotation.SuppressLint;
import android.app.Activity;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.Executors;
public class BluetoothSerialSocket implements Runnable {
private static final UUID BLUETOOTH_SPP = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private final BroadcastReceiver disconnectBroadcastReceiver;
private final Context context;
private BluetoothSerialListener listener;
private final BluetoothDevice device;
private BluetoothSocket socket;
private boolean connected;
public BluetoothSerialSocket(Context context, BluetoothDevice device) {
if(context instanceof Activity)
throw new InvalidParameterException("expected non UI context");
this.context = context;
this.device = device;
disconnectBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(listener != null)
listener.onSerialIoError(new IOException("background disconnect"));
disconnect(); // disconnect now, else would be queued until UI re-attached
}
};
}
@SuppressLint("MissingPermission")
String getName() {
return device.getName() != null ? device.getName() : device.getAddress();
}
/**
* connect-success and most connect-errors are returned asynchronously to listener
*/
void connect(BluetoothSerialListener listener) throws IOException {
this.listener = listener;
context.registerReceiver(disconnectBroadcastReceiver, new IntentFilter(BluetoothConstants.INTENT_ACTION_DISCONNECT));
Executors.newCachedThreadPool().submit(this);
}
void disconnect() {
listener = null; // ignore remaining data and errors
// connected = false; // run loop will reset connected
if(socket != null) {
try {
socket.close();
} catch (Exception ignored) {
}
socket = null;
}
try {
context.unregisterReceiver(disconnectBroadcastReceiver);
} catch (Exception ignored) {
}
}
void write(byte[] data) throws IOException {
if (!connected)
throw new IOException("not connected");
socket.getOutputStream().write(data);
}
@SuppressLint("MissingPermission")
@Override
public void run() { // connect & read
try {
socket = device.createRfcommSocketToServiceRecord(BLUETOOTH_SPP);
socket.connect();
if(listener != null)
listener.onSerialConnect();
} catch (Exception e) {
if(listener != null)
listener.onSerialConnectError(e);
try {
socket.close();
} catch (Exception ignored) {
}
socket = null;
return;
}
connected = true;
try {
byte[] buffer = new byte[1024];
int len;
//noinspection InfiniteLoopStatement
while (true) {
len = socket.getInputStream().read(buffer);
byte[] data = Arrays.copyOf(buffer, len);
if(listener != null)
listener.onSerialRead(data);
}
} catch (Exception e) {
connected = false;
if (listener != null)
listener.onSerialIoError(e);
try {
socket.close();
} catch (Exception ignored) {
}
socket = null;
}
}
}