aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/io/trygvis/android
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/io/trygvis/android')
-rw-r--r--app/src/main/java/io/trygvis/android/F2.java5
-rw-r--r--app/src/main/java/io/trygvis/android/F3.java5
-rw-r--r--app/src/main/java/io/trygvis/android/F4.java5
-rw-r--r--app/src/main/java/io/trygvis/android/Function.java5
-rw-r--r--app/src/main/java/io/trygvis/android/LocalBinder.java15
-rw-r--r--app/src/main/java/io/trygvis/android/Supplier.java5
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java358
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtCallback.java4
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtDevice.java40
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtDeviceListener.java4
-rw-r--r--app/src/main/java/io/trygvis/android/bt/BtService.java50
-rw-r--r--app/src/main/java/io/trygvis/android/bt/DefaultBtService.java100
12 files changed, 341 insertions, 255 deletions
diff --git a/app/src/main/java/io/trygvis/android/F2.java b/app/src/main/java/io/trygvis/android/F2.java
new file mode 100644
index 0000000..1f362cc
--- /dev/null
+++ b/app/src/main/java/io/trygvis/android/F2.java
@@ -0,0 +1,5 @@
+package io.trygvis.android;
+
+public interface F2<A, B, C> {
+ C apply(A a, B b);
+}
diff --git a/app/src/main/java/io/trygvis/android/F3.java b/app/src/main/java/io/trygvis/android/F3.java
new file mode 100644
index 0000000..30d3adf
--- /dev/null
+++ b/app/src/main/java/io/trygvis/android/F3.java
@@ -0,0 +1,5 @@
+package io.trygvis.android;
+
+public interface F3<A, B, C, D> {
+ D apply(A a, B b, C c);
+}
diff --git a/app/src/main/java/io/trygvis/android/F4.java b/app/src/main/java/io/trygvis/android/F4.java
new file mode 100644
index 0000000..5ff50f5
--- /dev/null
+++ b/app/src/main/java/io/trygvis/android/F4.java
@@ -0,0 +1,5 @@
+package io.trygvis.android;
+
+public interface F4<A, B, C, D, E> {
+ E apply(A a, B b, C c, D d);
+}
diff --git a/app/src/main/java/io/trygvis/android/Function.java b/app/src/main/java/io/trygvis/android/Function.java
new file mode 100644
index 0000000..5e3bb96
--- /dev/null
+++ b/app/src/main/java/io/trygvis/android/Function.java
@@ -0,0 +1,5 @@
+package io.trygvis.android;
+
+public interface Function<A, B> {
+ B apply(A a);
+}
diff --git a/app/src/main/java/io/trygvis/android/LocalBinder.java b/app/src/main/java/io/trygvis/android/LocalBinder.java
new file mode 100644
index 0000000..62d48fd
--- /dev/null
+++ b/app/src/main/java/io/trygvis/android/LocalBinder.java
@@ -0,0 +1,15 @@
+package io.trygvis.android;
+
+import android.os.Binder;
+
+public class LocalBinder<A> extends Binder {
+ private final A service;
+
+ public LocalBinder(A service) {
+ this.service = service;
+ }
+
+ public A getService() {
+ return service;
+ }
+}
diff --git a/app/src/main/java/io/trygvis/android/Supplier.java b/app/src/main/java/io/trygvis/android/Supplier.java
new file mode 100644
index 0000000..222dff2
--- /dev/null
+++ b/app/src/main/java/io/trygvis/android/Supplier.java
@@ -0,0 +1,5 @@
+package io.trygvis.android;
+
+public interface Supplier<A> {
+ A get();
+}
diff --git a/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java b/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java
index 8cbf87c..984c738 100644
--- a/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java
+++ b/app/src/main/java/io/trygvis/android/bt/BtActionExecutor.java
@@ -12,6 +12,9 @@ import java.util.Iterator;
import java.util.List;
import java.util.Queue;
+import io.trygvis.android.F2;
+import io.trygvis.android.Function;
+
import static io.trygvis.android.bt.BtActionExecutor.EventType.onCharacteristicChanged;
import static io.trygvis.android.bt.BtActionExecutor.EventType.onCharacteristicRead;
import static io.trygvis.android.bt.BtActionExecutor.EventType.onCharacteristicWrite;
@@ -19,239 +22,146 @@ import static io.trygvis.android.bt.BtActionExecutor.EventType.onConnectionState
import static io.trygvis.android.bt.BtActionExecutor.EventType.onDescriptorRead;
import static io.trygvis.android.bt.BtActionExecutor.EventType.onDescriptorWrite;
import static io.trygvis.android.bt.BtActionExecutor.EventType.onFailure;
+import static io.trygvis.android.bt.BtActionExecutor.EventType.onFinally;
import static io.trygvis.android.bt.BtActionExecutor.EventType.onReliableWriteCompleted;
import static io.trygvis.android.bt.BtActionExecutor.EventType.onServicesDiscovered;
public class BtActionExecutor {
private final static String TAG = BtActionExecutor.class.getSimpleName();
private final Queue<BtCallback> actionQ = new ArrayDeque<>();
+ private final Queue<BtCallback> failureQ = new ArrayDeque<>();
private final Queue<BtCallback> finallyQ = new ArrayDeque<>();
- private final List<BluetoothGattCallback> remoteRssi = new ArrayList<>();
-
- public BtActionExecutor() {
- }
-
- public BtActionExecutor(BtCallback first) {
- actionQ.add(first);
- }
-// public static final BtCallback waitForIt = new BtCallback("Wait for it") {
-// @Override
-// public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
-// Log.w(TAG, "wait for it...!");
-// return true;
-// }
-// };
-
-// public synchronized BtActionExecutor onSuccess(BtCallback btCallback) {
-// actionQ.add(btCallback);
-// return this;
-// }
-
- public synchronized BtActionExecutor onConnectionStateChange(OnConnectionStateChange callback) {
+ public synchronized BtActionExecutor onConnectionStateChange(F2<BluetoothGatt, Integer, Boolean> callback) {
actionQ.add(new BtCallback("onConnectionStateChange") {
@Override
public boolean onConnectionStateChange(BluetoothGatt gatt, int newState) {
- return callback.onConnectionStateChange(gatt, newState);
+ return callback.apply(gatt, newState);
}
});
return this;
}
- public synchronized BtActionExecutor onServicesDiscovered(OnServicesDiscovered callback) {
+ public synchronized BtActionExecutor onServicesDiscovered(Function<BluetoothGatt, Boolean> callback) {
actionQ.add(new BtCallback("onServicesDiscovered") {
@Override
public boolean onServicesDiscovered(BluetoothGatt gatt) {
- return callback.onServicesDiscovered(gatt);
+ return callback.apply(gatt);
}
});
return this;
}
- public synchronized BtActionExecutor onCharacteristicRead(OnCharacteristicRead callback) {
+ public synchronized BtActionExecutor onCharacteristicRead(F2<BluetoothGatt, BluetoothGattCharacteristic, Boolean> callback) {
actionQ.add(new BtCallback("onCharacteristicRead") {
@Override
public boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- return callback.onCharacteristicRead(gatt, characteristic);
+ return callback.apply(gatt, characteristic);
}
});
return this;
}
- public synchronized BtActionExecutor onCharacteristicWrite(OnCharacteristicWrite callback) {
+ public synchronized BtActionExecutor onCharacteristicWrite(F2<BluetoothGatt, BluetoothGattCharacteristic, Boolean> callback) {
actionQ.add(new BtCallback("onCharacteristicWrite") {
@Override
public boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- return callback.onCharacteristicWrite(gatt, characteristic);
+ return callback.apply(gatt, characteristic);
}
});
return this;
}
- public synchronized BtActionExecutor onCharacteristicChanged(OnCharacteristicChanged callback) {
+ public synchronized BtActionExecutor onCharacteristicChanged(F2<BluetoothGatt, BluetoothGattCharacteristic, Boolean> callback) {
actionQ.add(new BtCallback("onCharacteristicChanged") {
@Override
public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- return callback.onCharacteristicChanged(gatt, characteristic);
+ return callback.apply(gatt, characteristic);
}
});
return this;
}
- public synchronized BtActionExecutor onDescriptorRead(OnDescriptorRead callback) {
+ public synchronized BtActionExecutor onDescriptorRead(F2<BluetoothGatt, BluetoothGattDescriptor, Boolean> callback) {
actionQ.add(new BtCallback("onDescriptorRead") {
@Override
public boolean onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) {
- return callback.onDescriptorRead(gatt, descriptor);
+ return callback.apply(gatt, descriptor);
}
});
return this;
}
- public synchronized BtActionExecutor onDescriptorWrite(OnDescriptorWrite callback) {
+ public synchronized BtActionExecutor onDescriptorWrite(F2<BluetoothGatt, BluetoothGattDescriptor, Boolean> callback) {
actionQ.add(new BtCallback("onDescriptorWrite") {
@Override
public boolean onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor) {
- return callback.onDescriptorWrite(gatt, descriptor);
+ return callback.apply(gatt, descriptor);
}
});
return this;
}
- public synchronized BtActionExecutor onReliableWriteCompleted(OnReliableWriteCompleted callback) {
+ public synchronized BtActionExecutor onReliableWriteCompleted(Function<BluetoothGatt, Boolean> callback) {
actionQ.add(new BtCallback("onReliableWriteCompleted") {
@Override
public boolean onReliableWriteCompleted(BluetoothGatt gatt) {
- return callback.onReliableWriteCompleted(gatt);
+ return callback.apply(gatt);
}
});
return this;
}
- public synchronized BtActionExecutor onReadRemoteRssi(OnReadRemoteRssi callback) {
+ public synchronized BtActionExecutor onReadRemoteRssi(F2<BluetoothGatt, Integer, Boolean> callback) {
actionQ.add(new BtCallback("onReadRemoteRssi") {
@Override
public boolean onReadRemoteRssi(BluetoothGatt gatt, int rssi) {
- return callback.onReadRemoteRssi(gatt, rssi);
+ return callback.apply(gatt, rssi);
}
});
return this;
}
- public synchronized BtActionExecutor onFailure(OnFailure callback) {
- actionQ.add(new BtCallback("onFailure") {
+ public synchronized BtActionExecutor onFailure(Runnable callback) {
+ failureQ.add(new BtCallback("onFailure") {
@Override
public void onFailure() {
- callback.onFailure();
+ callback.run();
}
});
return this;
}
- public static interface OnConnectionStateChange {
- boolean onConnectionStateChange(BluetoothGatt gatt, int newState);
- }
-
- public static interface OnServicesDiscovered {
- boolean onServicesDiscovered(BluetoothGatt gatt);
- }
-
- public static interface OnCharacteristicRead {
- boolean onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
- }
-
- public static interface OnCharacteristicWrite {
- boolean onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
- }
-
- public static interface OnCharacteristicChanged {
- boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);
- }
-
- public static interface OnDescriptorRead {
- boolean onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor);
- }
-
- public static interface OnDescriptorWrite {
- boolean onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor);
- }
-
- public static interface OnReliableWriteCompleted {
- boolean onReliableWriteCompleted(BluetoothGatt gatt);
- }
-
- public static interface OnReadRemoteRssi {
- boolean onReadRemoteRssi(BluetoothGatt gatt, int rssi);
- }
-
- public static interface OnFailure {
- void onFailure();
- }
-
- public synchronized BtActionExecutor addFinally(BtCallback btCallback) {
- finallyQ.add(btCallback);
+ public synchronized BtActionExecutor onFinally(Runnable callback) {
+ finallyQ.add(new BtCallback("finally") {
+ @Override
+ public void onFinally() {
+ callback.run();
+ }
+ });
return this;
}
-// public synchronized BtActionExecutor onRemoteRssi(BluetoothGattCallback callback) {
-// remoteRssi.add(callback);
-// return this;
-// }
-
- void onEvent(EventType key, String values, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int status, int newState) {
- if (status != BluetoothGatt.GATT_SUCCESS) {
- Log.w(TAG, "Operation failed: " + key + ", " + values);
- doFinally();
- return;
- }
-
- Log.i(TAG, "Bt action completed successfully: callback=" + key);
-
- BtCallback btCallback;
- synchronized (this) {
- if (actionQ.isEmpty()) {
- Log.d(TAG, "All Bluetooth actions are done");
+ public String toString() {
+ StringBuilder s = new StringBuilder("Queue: ");
- doFinally();
- return;
- }
+ Iterator<BtCallback> it = actionQ.iterator();
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- // ignore
+ int i = 0;
+ while (it.hasNext()) {
+ BtCallback c = it.next();
+ if (i > 0) {
+ s.append(", ");
}
- btCallback = actionQ.remove();
- Log.i(TAG, "Executing bt action: " + btCallback.name);
+ s.append(c.name);
+ i++;
}
- try {
- boolean ok = callCallback(key, gatt, characteristic, descriptor, newState, btCallback);
-
- if (!ok) {
- Log.w(TAG, "The callback don't want to continue.");
- doFinally();
- }
-
- if (actionQ.isEmpty()) {
- Log.i(TAG, "The queue is empty");
- }
- } catch (NotOverriddenException e) {
- Log.w(TAG, "Unexpected callback by listener: " + key);
- doFinally();
- }
+ return s.toString();
}
- private void doFinally() {
- actionQ.clear();
-
- for (BtCallback callback = finallyQ.poll(); callback != null; callback = finallyQ.poll()) {
- try {
- callCallback(onFailure, null, null, null, 0, callback);
- } catch (NotOverriddenException e) {
- return;
- }
- }
+ public BluetoothGattCallback asCallback() {
+ return new MyBluetoothGattCallback();
}
enum EventType {
@@ -264,10 +174,13 @@ public class BtActionExecutor {
onDescriptorWrite,
onReliableWriteCompleted,
+ onReadRemoteRssi,
+
onFailure,
+ onFinally,
}
- private Boolean callCallback(EventType key, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int newState, BtCallback btCallback) {
+ private static Boolean callCallback(EventType key, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int newState, BtCallback btCallback) {
switch (key) {
case onConnectionStateChange:
return btCallback.onConnectionStateChange(gatt, newState);
@@ -289,78 +202,155 @@ public class BtActionExecutor {
case onFailure:
btCallback.onFailure();
return null;
+ case onFinally:
+ btCallback.onFinally();
+ return null;
default:
Log.w(TAG, "Unknown callback: " + key);
return null;
}
}
- public String toString() {
- StringBuilder s = new StringBuilder("Queue: ");
+ private class MyBluetoothGattCallback extends BluetoothGattCallback {
- Iterator<BtCallback> it = actionQ.iterator();
+ private Queue<BtCallback> initialActionQ = new ArrayDeque<>(actionQ);
+ private List<String> events = new ArrayList<>();
- int i = 0;
- while (it.hasNext()) {
- BtCallback c = it.next();
- if (i > 0) {
- s.append(", ");
- }
- s.append(c.name);
- i++;
- }
+ void onEvent(EventType key, String values, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, int status, int newState) {
+ boolean success = status == BluetoothGatt.GATT_SUCCESS;
+ events.add(key + ", " + values + ", success=" + success);
- return s.toString();
- }
+ Log.i(TAG, "Operation failed: " + key + ", " + values + ", success=" + success);
- public BluetoothGattCallback asCallback() {
- return new BluetoothGattCallback() {
- @Override
- public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
- onEvent(onConnectionStateChange, "status=" + status + ", newState=" + newState, gatt, null, null, status, newState);
+ if (!success) {
+ doFailure();
+ return;
}
- @Override
- public void onServicesDiscovered(BluetoothGatt gatt, int status) {
- onEvent(onServicesDiscovered, "status=" + status, gatt, null, null, status, 9);
- }
+ BtCallback btCallback;
+ synchronized (this) {
+ if (actionQ.isEmpty()) {
+ Log.d(TAG, "All Bluetooth actions are done");
- @Override
- public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
- onEvent(onCharacteristicRead, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0);
- }
+ doFinally();
+ return;
+ }
- @Override
- public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
- onEvent(onCharacteristicWrite, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ btCallback = actionQ.remove();
+ Log.i(TAG, "Executing bt action: " + btCallback.name);
}
- @Override
- public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
- onEvent(onCharacteristicChanged, "characteristic=" + characteristic.getUuid(), gatt, characteristic, null, BluetoothGatt.GATT_SUCCESS, 0);
+ try {
+ boolean ok = callCallback(key, gatt, characteristic, descriptor, newState, btCallback);
+
+ if (!ok) {
+ Log.w(TAG, "The callback don't want to continue.");
+ doFinally();
+ }
+
+ if (actionQ.isEmpty()) {
+ Log.i(TAG, "The queue is empty");
+ }
+ } catch (NotOverriddenException e) {
+ Log.w(TAG, "Unexpected callback by listener: " + key);
+ doFailure();
}
+ }
- @Override
- public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
- onEvent(onDescriptorRead, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0);
+ private void doFailure() {
+ StringBuilder msg = new StringBuilder();
+
+ msg.append("Expected events: \n");
+ for (BtCallback cb : initialActionQ) {
+ msg.append(" ").append(cb.name).append("\n");
}
- @Override
- public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
- onEvent(onDescriptorWrite, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0);
+ msg.append("Actual events: \n");
+ for (String event : events) {
+ msg.append(" ").append(event).append("\n");
}
- @Override
- public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
- onEvent(onReliableWriteCompleted, "status=" + status, gatt, null, null, status, 0);
+ Log.w(TAG, msg.toString());
+
+ Log.w(TAG, "Executing " + failureQ.size() + " failure handlers");
+
+ for (BtCallback callback = failureQ.poll(); callback != null; callback = failureQ.poll()) {
+ try {
+ callCallback(onFailure, null, null, null, 0, callback);
+ } catch (NotOverriddenException e) {
+ return;
+ }
}
- @Override
- public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
- for (BluetoothGattCallback callback : remoteRssi) {
- callback.onReadRemoteRssi(gatt, rssi, status);
+ doFinally();
+ }
+
+ private void doFinally() {
+ actionQ.clear();
+
+ Log.w(TAG, "Executing " + finallyQ.size() + " finally handlers");
+
+ for (BtCallback callback = finallyQ.poll(); callback != null; callback = finallyQ.poll()) {
+ try {
+ callCallback(onFinally, null, null, null, 0, callback);
+ } catch (NotOverriddenException e) {
+ return;
}
}
- };
+ }
+
+ // -----------------------------------------------------------------------
+ //
+ // -----------------------------------------------------------------------
+
+ @Override
+ public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
+ onEvent(onConnectionStateChange, "status=" + status + ", newState=" + newState, gatt, null, null, status, newState);
+ }
+
+ @Override
+ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+ onEvent(onServicesDiscovered, "status=" + status, gatt, null, null, status, 9);
+ }
+
+ @Override
+ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ onEvent(onCharacteristicRead, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0);
+ }
+
+ @Override
+ public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
+ onEvent(onCharacteristicWrite, "status=" + status + ", characteristic=" + characteristic.getUuid(), gatt, characteristic, null, status, 0);
+ }
+
+ @Override
+ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
+ onEvent(onCharacteristicChanged, "characteristic=" + characteristic.getUuid(), gatt, characteristic, null, BluetoothGatt.GATT_SUCCESS, 0);
+ }
+
+ @Override
+ public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
+ onEvent(onDescriptorRead, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0);
+ }
+
+ @Override
+ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
+ onEvent(onDescriptorWrite, "status=" + status + ", descriptor=" + descriptor.getUuid(), gatt, null, descriptor, status, 0);
+ }
+
+ @Override
+ public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
+ onEvent(onReliableWriteCompleted, "status=" + status, gatt, null, null, status, 0);
+ }
+
+ @Override
+ public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
+// onEvent(onReadRemoteRssi, "status=" + status, gatt, null, null, status, 0);
+ }
}
}
diff --git a/app/src/main/java/io/trygvis/android/bt/BtCallback.java b/app/src/main/java/io/trygvis/android/bt/BtCallback.java
index 7702962..29ea9e1 100644
--- a/app/src/main/java/io/trygvis/android/bt/BtCallback.java
+++ b/app/src/main/java/io/trygvis/android/bt/BtCallback.java
@@ -50,4 +50,8 @@ public class BtCallback {
public void onFailure() {
throw new NotOverriddenException();
}
+
+ public void onFinally() {
+ throw new NotOverriddenException();
+ }
}
diff --git a/app/src/main/java/io/trygvis/android/bt/BtDevice.java b/app/src/main/java/io/trygvis/android/bt/BtDevice.java
index ba10d2d..e34e9ea 100644
--- a/app/src/main/java/io/trygvis/android/bt/BtDevice.java
+++ b/app/src/main/java/io/trygvis/android/bt/BtDevice.java
@@ -3,6 +3,8 @@ package io.trygvis.android.bt;
import android.bluetooth.BluetoothDevice;
import android.util.Log;
+import io.trygvis.android.Function;
+
public class BtDevice<A> {
private final static String TAG = BtDevice.class.getSimpleName();
@@ -14,31 +16,22 @@ public class BtDevice<A> {
private boolean seenNow;
- private BtDeviceListener l = null;
-
- private BtDeviceListener listener = new BtDeviceListener() {
- };
+ public static interface BtDeviceWrapper<A> {
+ BtDevice<A> getBtDevice();
+ }
- public BtDevice(DefaultBtService btService, BluetoothDevice bluetoothDevice, A tag, Integer rssi, BtScanResult scanResult) {
+ BtDevice(DefaultBtService btService, BluetoothDevice bluetoothDevice, Function<BtDevice<A>, A> tagConstructor, Integer rssi, BtScanResult scanResult) {
this.btService = btService;
this.bluetoothDevice = bluetoothDevice;
- this.tag = tag;
+ this.tag = tagConstructor.apply(this);
this.rssi = rssi;
this.scanResult = scanResult;
}
- public void addListener(BtDeviceListener listener) {
- this.l = listener;
- }
-
public A getTag() {
return tag;
}
- public void setTag(A tag) {
- this.tag = tag;
- }
-
public String getAddress() {
return bluetoothDevice.getAddress();
}
@@ -65,4 +58,23 @@ public class BtDevice<A> {
public String toString() {
return "BtDevice{address=" + bluetoothDevice.getAddress() + '}';
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ BtDevice other = (BtDevice) o;
+
+ return getAddress().equals(other.getAddress());
+ }
+
+ @Override
+ public int hashCode() {
+ return getAddress().hashCode();
+ }
}
diff --git a/app/src/main/java/io/trygvis/android/bt/BtDeviceListener.java b/app/src/main/java/io/trygvis/android/bt/BtDeviceListener.java
deleted file mode 100644
index 57eabc6..0000000
--- a/app/src/main/java/io/trygvis/android/bt/BtDeviceListener.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package io.trygvis.android.bt;
-
-public interface BtDeviceListener {
-}
diff --git a/app/src/main/java/io/trygvis/android/bt/BtService.java b/app/src/main/java/io/trygvis/android/bt/BtService.java
index 123be3a..968a4a8 100644
--- a/app/src/main/java/io/trygvis/android/bt/BtService.java
+++ b/app/src/main/java/io/trygvis/android/bt/BtService.java
@@ -1,12 +1,17 @@
package io.trygvis.android.bt;
-import android.os.Binder;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
-import java.util.List;
+import java.util.Collection;
-public interface BtService<A> {
+import io.trygvis.android.Function;
- boolean initialize(BtServiceListener<A> btServiceListener, Supplier<A> dataSupplier);
+public interface BtService<A extends BtDevice.BtDeviceWrapper<A>> {
+
+ boolean initialize(Function<BtDevice<A>, A> tagConstructor);
void clearCache();
@@ -16,40 +21,35 @@ public interface BtService<A> {
void stopScanning();
-// BtDevice<A> getDevice(String macAddress);
+ BtDevice<A> getDevice(String address);
- List<BtDevice<A>> getDevices();
+ A getTag(String address);
- interface Supplier<A> {
- A get();
- }
+ Collection<BtDevice<A>> getDevices();
- interface BtServiceListener<A> {
- void onScanStarted();
+ Collection<A> getTags();
- void onNewDevice(BtDevice<A> device);
+ public static class BtServiceListenerBroadcastReceiver extends BroadcastReceiver {
- void onScanStopped();
- }
+ public static final String INTENT_NAME = BtServiceListenerBroadcastReceiver.class.getName();
- public abstract class AbstractBtServiceListener<A> implements BtServiceListener<A> {
+ public static final IntentFilter INTENT_FILTER = new IntentFilter(INTENT_NAME);
- public void onScanStarted() {
- }
+ public void onReceive(Context context, Intent intent) {
+ if (!intent.getAction().equals(INTENT_NAME)) {
+ return;
+ }
- public void onScanStopped() {
+ DefaultBtService.dispatchEvent(intent, this);
}
- }
- public class LocalBinder<A> extends Binder {
- private final BtService<A> service;
+ public void onScanStarted() {
+ }
- public LocalBinder(BtService<A> service) {
- this.service = service;
+ public void onNewDevice(String address) {
}
- public BtService<A> getService() {
- return service;
+ public void onScanStopped() {
}
}
}
diff --git a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java
index 8638544..51d84af 100644
--- a/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java
+++ b/app/src/main/java/io/trygvis/android/bt/DefaultBtService.java
@@ -13,12 +13,17 @@ import android.util.Log;
import android.widget.Toast;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import io.trygvis.android.Function;
+import io.trygvis.android.LocalBinder;
import io.trygvis.soilmoisture.R;
-public class DefaultBtService<A> extends Service implements BtService<A> {
+import static java.util.Collections.unmodifiableCollection;
+
+public class DefaultBtService<A extends BtDevice.BtDeviceWrapper<A>> extends Service implements BtService<A> {
private final static String TAG = DefaultBtService.class.getSimpleName();
private final IBinder binder = new LocalBinder<>(this);
@@ -29,19 +34,13 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
// State
// -----------------------------------------------------------------------
- private BtServiceListener<A> serviceListener = new AbstractBtServiceListener<A>() {
- @Override
- public void onNewDevice(BtDevice<A> device) {
- }
- };
-
- private Supplier<A> tagConstructor;
+ private Function<BtDevice<A>, A> tagConstructor;
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
- private final List<BtDevice<A>> devices = new ArrayList<>();
+ private final Set<BtDevice<A>> devices = new HashSet<>();
private boolean scanning = false;
@@ -50,17 +49,13 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
// -----------------------------------------------------------------------
@Override
- public boolean initialize(BtServiceListener<A> serviceListener, Supplier<A> dataSupplier) {
+ public boolean initialize(Function<BtDevice<A>, A> tagConstructor) {
if (bluetoothManager != null) {
- Log.e(TAG, "Already initialized");
+ Log.i(TAG, "Already initialized");
return false;
}
- this.tagConstructor = dataSupplier;
-
- if (serviceListener != null) {
- this.serviceListener = serviceListener;
- }
+ this.tagConstructor = tagConstructor;
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
@@ -85,7 +80,7 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
return false;
}
- Log.e(TAG, "Bluetooth initialized");
+ Log.i(TAG, "Bluetooth initialized");
return true;
}
@@ -100,13 +95,15 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
@Override
public boolean startScanning(long timeoutMs) {
+ Log.d(TAG, "startScanning, timeoutMs=" + timeoutMs);
+
if (timeoutMs > 0) {
handler.postDelayed(this::stopScanning, timeoutMs);
}
if (bluetoothAdapter.startLeScan(leScanCallback)) {
scanning = true;
- serviceListener.onScanStarted();
+ sendBroadcast(createScanStarted());
return true;
}
@@ -115,15 +112,16 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
@Override
public void stopScanning() {
+ Log.d(TAG, "stopScanning");
+
// This doesn't mind being called twice.
bluetoothAdapter.stopLeScan(leScanCallback);
scanning = false;
- serviceListener.onScanStopped();
+ sendBroadcast(createScanStopped());
}
-// @Override
public BtDevice<A> getDevice(String mac) {
BtDevice<A> device = findDevice(mac);
@@ -136,8 +134,22 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
}
@Override
- public List<BtDevice<A>> getDevices() {
- return Collections.unmodifiableList(devices);
+ public A getTag(String address) {
+ return getDevice(address).getTag();
+ }
+
+ @Override
+ public Collection<BtDevice<A>> getDevices() {
+ return unmodifiableCollection(devices);
+ }
+
+ @Override
+ public Collection<A> getTags() {
+ ArrayList<A> tags = new ArrayList<>();
+ for (BtDevice<A> device : devices) {
+ tags.add(device.getTag());
+ }
+ return tags;
}
// -----------------------------------------------------------------------
@@ -145,8 +157,6 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
// -----------------------------------------------------------------------
private BluetoothAdapter.LeScanCallback leScanCallback = (device, rssi, scanRecord) -> {
-// Log.i(TAG, "onLeScan()");
-
BtScanResult scanResult = new BtScanResult(scanRecord);
register(device, rssi, scanResult);
@@ -173,14 +183,48 @@ public class DefaultBtService<A> extends Service implements BtService<A> {
}
Log.i(TAG, "New device: " + bluetoothDevice.getAddress());
- btDevice = new BtDevice<>(this, bluetoothDevice, tagConstructor.get(), rssi, scanResult);
+ btDevice = new BtDevice<>(this, bluetoothDevice, tagConstructor, rssi, scanResult);
devices.add(btDevice);
- serviceListener.onNewDevice(btDevice);
+ sendBroadcast(createNewDevice(btDevice.getAddress()));
return btDevice;
}
+ private Intent createScanStarted() {
+ return new Intent(BtServiceListenerBroadcastReceiver.INTENT_NAME).
+ putExtra("event", "scanStarted");
+ }
+
+ private Intent createScanStopped() {
+ return new Intent(BtServiceListenerBroadcastReceiver.INTENT_NAME).
+ putExtra("event", "scanStopped");
+ }
+
+ private Intent createNewDevice(String address) {
+ return new Intent(BtServiceListenerBroadcastReceiver.INTENT_NAME).
+ putExtra("event", "newDevice").
+ putExtra("address", address);
+ }
+
+ public static void dispatchEvent(Intent intent, BtServiceListenerBroadcastReceiver listener) {
+ String event = intent.getStringExtra("event");
+ Log.i(TAG, "Dispatching event " + intent.getAction() + "/" + event);
+ switch (event) {
+ case "newDevice":
+ listener.onNewDevice(intent.getStringExtra("address"));
+ break;
+ case "scanStarted":
+ listener.onScanStarted();
+ break;
+ case "scanStopped":
+ listener.onScanStopped();
+ break;
+ default:
+ break;
+ }
+ }
+
private BtDevice<A> findDevice(String mac) {
for (BtDevice<A> d : devices) {
if (d.getAddress().equals(mac)) {