kopia lustrzana https://github.com/N0BOY/FT8CN
128 wiersze
4.0 KiB
Java
Executable File
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;
|
|
}
|
|
}
|
|
|
|
}
|