kopia lustrzana https://github.com/N0BOY/FT8CN
214 wiersze
6.4 KiB
Java
Executable File
214 wiersze
6.4 KiB
Java
Executable File
package com.bg7yoz.ft8cn.bluetooth;
|
|
|
|
import android.app.Service;
|
|
import android.content.Intent;
|
|
import android.os.Binder;
|
|
import android.os.Handler;
|
|
import android.os.IBinder;
|
|
import android.os.Looper;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import java.io.IOException;
|
|
import java.util.LinkedList;
|
|
import java.util.Queue;
|
|
|
|
/**
|
|
* 蓝牙串口有关的服务
|
|
* BG7YOZ
|
|
* 2023-03
|
|
*/
|
|
public class BluetoothSerialService extends Service implements BluetoothSerialListener {
|
|
|
|
public class SerialBinder extends Binder {
|
|
public BluetoothSerialService getService() { return BluetoothSerialService.this; }
|
|
}
|
|
|
|
private enum QueueType {Connect, ConnectError, Read, IoError}
|
|
|
|
private static class QueueItem {
|
|
QueueType type;
|
|
byte[] data;
|
|
Exception e;
|
|
|
|
QueueItem(QueueType type, byte[] data, Exception e) { this.type=type; this.data=data; this.e=e; }
|
|
}
|
|
|
|
private final Handler mainLooper;
|
|
private final IBinder binder;
|
|
private final Queue<QueueItem> queue1, queue2;
|
|
|
|
private BluetoothSerialSocket socket;
|
|
private BluetoothSerialListener listener;
|
|
private boolean connected;
|
|
|
|
/**
|
|
* Lifecylce
|
|
*/
|
|
public BluetoothSerialService() {
|
|
mainLooper = new Handler(Looper.getMainLooper());
|
|
binder = new SerialBinder();
|
|
queue1 = new LinkedList<>();
|
|
queue2 = new LinkedList<>();
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
//cancelNotification();
|
|
disconnect();
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public IBinder onBind(Intent intent) {
|
|
return binder;
|
|
}
|
|
|
|
/**
|
|
* Api
|
|
*/
|
|
public void connect(BluetoothSerialSocket socket) throws IOException {
|
|
socket.connect(this);
|
|
this.socket = socket;
|
|
connected = true;
|
|
}
|
|
|
|
public void disconnect() {
|
|
connected = false; // ignore data,errors while disconnecting
|
|
//cancelNotification();
|
|
if(socket != null) {
|
|
socket.disconnect();
|
|
socket = null;
|
|
}
|
|
}
|
|
|
|
public void write(byte[] data) throws IOException {
|
|
if(!connected)
|
|
throw new IOException("not connected");
|
|
socket.write(data);
|
|
}
|
|
|
|
public void attach(BluetoothSerialListener listener) {
|
|
if(Looper.getMainLooper().getThread() != Thread.currentThread())
|
|
throw new IllegalArgumentException("not in main thread");
|
|
//cancelNotification();
|
|
// use synchronized() to prevent new items in queue2
|
|
// new items will not be added to queue1 because mainLooper.post and attach() run in main thread
|
|
synchronized (this) {
|
|
this.listener = listener;
|
|
}
|
|
for(QueueItem item : queue1) {
|
|
switch(item.type) {
|
|
case Connect: listener.onSerialConnect (); break;
|
|
case ConnectError: listener.onSerialConnectError (item.e); break;
|
|
case Read: listener.onSerialRead (item.data); break;
|
|
case IoError: listener.onSerialIoError (item.e); break;
|
|
}
|
|
}
|
|
for(QueueItem item : queue2) {
|
|
switch(item.type) {
|
|
case Connect: listener.onSerialConnect (); break;
|
|
case ConnectError: listener.onSerialConnectError (item.e); break;
|
|
case Read: listener.onSerialRead (item.data); break;
|
|
case IoError: listener.onSerialIoError (item.e); break;
|
|
}
|
|
}
|
|
queue1.clear();
|
|
queue2.clear();
|
|
}
|
|
|
|
public void detach() {
|
|
if (connected){
|
|
disconnect();
|
|
}
|
|
listener = null;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* SerialListener
|
|
*/
|
|
public void onSerialConnect() {
|
|
if(connected) {
|
|
synchronized (this) {
|
|
if (listener != null) {
|
|
mainLooper.post(() -> {
|
|
if (listener != null) {
|
|
listener.onSerialConnect();
|
|
} else {
|
|
queue1.add(new QueueItem(QueueType.Connect, null, null));
|
|
}
|
|
});
|
|
} else {
|
|
queue2.add(new QueueItem(QueueType.Connect, null, null));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void onSerialConnectError(Exception e) {
|
|
if(connected) {
|
|
synchronized (this) {
|
|
if (listener != null) {
|
|
mainLooper.post(() -> {
|
|
if (listener != null) {
|
|
listener.onSerialConnectError(e);
|
|
} else {
|
|
queue1.add(new QueueItem(QueueType.ConnectError, null, e));
|
|
//cancelNotification();
|
|
disconnect();
|
|
}
|
|
});
|
|
} else {
|
|
queue2.add(new QueueItem(QueueType.ConnectError, null, e));
|
|
//cancelNotification();
|
|
disconnect();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void onSerialRead(byte[] data) {
|
|
if(connected) {
|
|
synchronized (this) {
|
|
if (listener != null) {
|
|
mainLooper.post(() -> {
|
|
if (listener != null) {
|
|
listener.onSerialRead(data);
|
|
} else {
|
|
queue1.add(new QueueItem(QueueType.Read, data, null));
|
|
}
|
|
});
|
|
} else {
|
|
queue2.add(new QueueItem(QueueType.Read, data, null));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void onSerialIoError(Exception e) {
|
|
if(connected) {
|
|
synchronized (this) {
|
|
if (listener != null) {
|
|
mainLooper.post(() -> {
|
|
if (listener != null) {
|
|
listener.onSerialIoError(e);
|
|
} else {
|
|
queue1.add(new QueueItem(QueueType.IoError, null, e));
|
|
//cancelNotification();
|
|
disconnect();
|
|
}
|
|
});
|
|
} else {
|
|
queue2.add(new QueueItem(QueueType.IoError, null, e));
|
|
//cancelNotification();
|
|
disconnect();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|