diff options
-rw-r--r-- | java/BluetoothAdapter.java | 12 | ||||
-rw-r--r-- | java/BluetoothDevice.java | 19 | ||||
-rw-r--r-- | java/BluetoothGattCharacteristic.java | 6 | ||||
-rw-r--r-- | java/BluetoothGattDescriptor.java | 3 | ||||
-rw-r--r-- | java/BluetoothNotification.java | 5 | ||||
-rw-r--r-- | java/jni/BluetoothAdapter.cxx | 201 | ||||
-rw-r--r-- | java/jni/BluetoothDevice.cxx | 255 | ||||
-rw-r--r-- | java/jni/BluetoothGattCharacteristic.cxx | 24 | ||||
-rw-r--r-- | java/jni/BluetoothGattDescriptor.cxx | 52 | ||||
-rw-r--r-- | java/jni/JNIMem.cxx | 10 | ||||
-rw-r--r-- | java/jni/JNIMem.hpp | 65 | ||||
-rw-r--r-- | src/BluetoothDevice.cpp | 4 |
12 files changed, 642 insertions, 14 deletions
diff --git a/java/BluetoothAdapter.java b/java/BluetoothAdapter.java index 5b96c5b..45c3e95 100644 --- a/java/BluetoothAdapter.java +++ b/java/BluetoothAdapter.java @@ -117,6 +117,9 @@ public class BluetoothAdapter extends BluetoothObject */ public native boolean getPowered(); + public native void enablePoweredNotifications(BluetoothNotification<Boolean> powered); + public native void disablePoweredNotifications(); + /** Sets the power state the adapter. */ public native void setPowered(boolean value); @@ -126,6 +129,9 @@ public class BluetoothAdapter extends BluetoothObject */ public native boolean getDiscoverable(); + public native void enableDiscoverableNotifications(BluetoothNotification<Boolean> discoverable); + public native void disableDiscoverableNotifications(); + /** Sets the discoverable state the adapter. */ public native void setDiscoverable(boolean value); @@ -145,6 +151,9 @@ public class BluetoothAdapter extends BluetoothObject */ public native boolean getPairable(); + public native void enablePairableNotifications(BluetoothNotification<Boolean> pairable); + public native void disablePairableNotifications(); + /** Sets the discoverable state the adapter. */ public native void setPairable(boolean value); @@ -165,6 +174,9 @@ public class BluetoothAdapter extends BluetoothObject */ public native boolean getDiscovering(); + public native void enableDiscoveringNotifications(BluetoothNotification<Boolean> discovering); + public native void disableDiscoveringNotifications(); + /** Returns the UUIDs of the adapter. * @return Array containing the UUIDs of the adapter, ends with NULL. */ diff --git a/java/BluetoothDevice.java b/java/BluetoothDevice.java index 96b6329..0c1061b 100644 --- a/java/BluetoothDevice.java +++ b/java/BluetoothDevice.java @@ -150,11 +150,17 @@ public class BluetoothDevice extends BluetoothObject */ public native boolean getPaired(); + public native void enablePairedNotifications(BluetoothNotification<Boolean> paired); + public native void disablePairedNotifications(); + /** Returns the trusted state the device. * @return The trusted state of the device. */ public native boolean getTrusted(); + public native void enableTrustedNotifications(BluetoothNotification<Boolean> trusted); + public native void disableTrustedNotifications(); + /** Sets the trusted state the device. */ public native void setTrusted(boolean value); @@ -164,6 +170,9 @@ public class BluetoothDevice extends BluetoothObject */ public native boolean getBlocked(); + public native void enableBlockedNotifications(BluetoothNotification<Boolean> blocked); + public native void disableBlockeddNotifications(); + /** Sets the blocked state the device. */ public native void setBlocked(boolean value); @@ -176,17 +185,23 @@ public class BluetoothDevice extends BluetoothObject /** Returns the Received Signal Strength Indicator of the device. * @return The Received Signal Strength Indicator of the device. */ - public native short getRssi(); + public native short getRSSI(); + + public native void enableRSSINotifications(BluetoothNotification<Short> rssi); + public native void disableRSSINotifications(); /** Returns the connected state of the device. * @return The connected state of the device. */ public native boolean getConnected(); + public native void enableConnectedNotifications(BluetoothNotification<Boolean> connected); + public native void disableConnectedNotifications(); + /** Returns the UUIDs of the device. * @return Array containing the UUIDs of the device, ends with NULL. */ - public native String[] getUuids(); + public native String[] getUUIDs(); /** Returns the local ID of the adapter. * @return The local ID of the adapter. diff --git a/java/BluetoothGattCharacteristic.java b/java/BluetoothGattCharacteristic.java index 359fbb7..c46c70b 100644 --- a/java/BluetoothGattCharacteristic.java +++ b/java/BluetoothGattCharacteristic.java @@ -74,6 +74,9 @@ public class BluetoothGattCharacteristic extends BluetoothObject */ public native byte[] readValue(); + public native void enableValueNotifications(BluetoothNotification<byte[]> callback); + public native void disableValueNotifications(); + /** Writes the value of this characteristic. * @param[in] arg_value The data as vector<uchar> * to be written packed in a GBytes struct @@ -81,9 +84,6 @@ public class BluetoothGattCharacteristic extends BluetoothObject */ public native boolean writeValue(byte[] argValue); - public native boolean enableValueNotifications(Runnable runnable); - - public native boolean disableValueNotifications(); /* D-Bus property accessors: */ /** Get the UUID of this characteristic. diff --git a/java/BluetoothGattDescriptor.java b/java/BluetoothGattDescriptor.java index 8a0f89f..9a5b00f 100644 --- a/java/BluetoothGattDescriptor.java +++ b/java/BluetoothGattDescriptor.java @@ -50,6 +50,9 @@ public class BluetoothGattDescriptor extends BluetoothObject */ public native boolean writeValue(byte[] argValue); + public native void enableValueNotifications(BluetoothNotification<byte[]> value); + public native void disableValueNotifications(); + /* D-Bus property accessors: */ /** Get the UUID of this descriptor. * @return The 128 byte UUID of this descriptor, NULL if an error occurred diff --git a/java/BluetoothNotification.java b/java/BluetoothNotification.java new file mode 100644 index 0000000..41fe52c --- /dev/null +++ b/java/BluetoothNotification.java @@ -0,0 +1,5 @@ +package tinyb; + +public interface BluetoothNotification<T> { + public void run(T value); +} diff --git a/java/jni/BluetoothAdapter.cxx b/java/jni/BluetoothAdapter.cxx index 91e274f..d690d92 100644 --- a/java/jni/BluetoothAdapter.cxx +++ b/java/jni/BluetoothAdapter.cxx @@ -28,6 +28,7 @@ #include "tinyb_BluetoothAdapter.h" +#include "JNIMem.hpp" #include "helper.hpp" using namespace tinyb; @@ -277,6 +278,56 @@ void Java_tinyb_BluetoothAdapter_setPowered(JNIEnv *env, jobject obj, jboolean v } } +void Java_tinyb_BluetoothAdapter_enablePoweredNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_adapter->enable_powered_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothAdapter_disablePoweredNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + obj_adapter->disable_powered_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + jboolean Java_tinyb_BluetoothAdapter_getDiscoverable(JNIEnv *env, jobject obj) { try { @@ -317,6 +368,56 @@ void Java_tinyb_BluetoothAdapter_setDiscoverable(JNIEnv *env, jobject obj, jbool } } +void Java_tinyb_BluetoothAdapter_enableDiscoverableNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_adapter->enable_discoverable_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothAdapter_disableDiscoverableNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + obj_adapter->disable_discoverable_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + jlong Java_tinyb_BluetoothAdapter_getDiscoverableTimeout(JNIEnv *env, jobject obj) { try { @@ -380,6 +481,56 @@ jboolean Java_tinyb_BluetoothAdapter_getPairable(JNIEnv *env, jobject obj) return JNI_FALSE; } +void Java_tinyb_BluetoothAdapter_enablePairableNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_adapter->enable_pairable_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothAdapter_disablePairableNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + obj_adapter->disable_pairable_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + void Java_tinyb_BluetoothAdapter_setPairable(JNIEnv *env, jobject obj, jboolean val) { try { @@ -463,6 +614,56 @@ jboolean Java_tinyb_BluetoothAdapter_getDiscovering(JNIEnv *env, jobject obj) return JNI_FALSE; } +void Java_tinyb_BluetoothAdapter_enableDiscoveringNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_adapter->enable_discovering_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothAdapter_disableDiscoveringNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothAdapter *obj_adapter = + getInstance<BluetoothAdapter>(env, obj); + obj_adapter->disable_discovering_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + jobjectArray Java_tinyb_BluetoothAdapter_getUuids(JNIEnv *env, jobject obj) { try { diff --git a/java/jni/BluetoothDevice.cxx b/java/jni/BluetoothDevice.cxx index ba195a8..145b062 100644 --- a/java/jni/BluetoothDevice.cxx +++ b/java/jni/BluetoothDevice.cxx @@ -29,6 +29,7 @@ #include "tinyb_BluetoothDevice.h" +#include "JNIMem.hpp" #include "helper.hpp" using namespace tinyb; @@ -385,6 +386,56 @@ jboolean Java_tinyb_BluetoothDevice_getPaired(JNIEnv *env, jobject obj) return JNI_FALSE; } +void Java_tinyb_BluetoothDevice_enablePairedNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_device->enable_paired_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothDevice_disablePairedNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + obj_device->disable_paired_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + jboolean Java_tinyb_BluetoothDevice_getTrusted(JNIEnv *env, jobject obj) { try { @@ -425,6 +476,56 @@ void Java_tinyb_BluetoothDevice_setTrusted(JNIEnv *env, jobject obj, jboolean va } } +void Java_tinyb_BluetoothDevice_enableTrustedNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_device->enable_trusted_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothDevice_disableTrustedNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + obj_device->disable_trusted_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + jboolean Java_tinyb_BluetoothDevice_getBlocked(JNIEnv *env, jobject obj) { try { @@ -465,6 +566,56 @@ void Java_tinyb_BluetoothDevice_setBlocked(JNIEnv *env, jobject obj, jboolean va } } +void Java_tinyb_BluetoothDevice_enableBlockedNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_device->enable_blocked_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothDevice_disableBlockedNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + obj_device->disable_blocked_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + jboolean Java_tinyb_BluetoothDevice_getLegacyPairing(JNIEnv *env, jobject obj) { try { @@ -485,7 +636,7 @@ jboolean Java_tinyb_BluetoothDevice_getLegacyPairing(JNIEnv *env, jobject obj) return JNI_FALSE; } -jshort Java_tinyb_BluetoothDevice_getRssi(JNIEnv *env, jobject obj) +jshort Java_tinyb_BluetoothDevice_getRSSI(JNIEnv *env, jobject obj) { try { BluetoothDevice *obj_device = getInstance<BluetoothDevice>(env, obj); @@ -505,6 +656,56 @@ jshort Java_tinyb_BluetoothDevice_getRssi(JNIEnv *env, jobject obj) return 0; } +void Java_tinyb_BluetoothDevice_enableRSSINotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_device->enable_rssi_notifications([ callback_ptr ] (int16_t v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass short_cls = search_class(*jni_env, "java/lang/Short"); + jmethodID constructor = search_method(*jni_env, short_cls, "<init>", "(S)V", false); + + jobject result = jni_env->NewObject(short_cls, constructor, (jshort) v); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothDevice_disableRSSINotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + obj_device->disable_rssi_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + jboolean Java_tinyb_BluetoothDevice_getConnected(JNIEnv *env, jobject obj) { try { @@ -525,7 +726,57 @@ jboolean Java_tinyb_BluetoothDevice_getConnected(JNIEnv *env, jobject obj) return JNI_FALSE; } -jobjectArray Java_tinyb_BluetoothDevice_getUuids(JNIEnv *env, jobject obj) +void Java_tinyb_BluetoothDevice_enableConnectedNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_device->enable_connected_notifications([ callback_ptr ] (bool v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + jclass boolean_cls = search_class(*jni_env, "java/lang/Boolean"); + jmethodID constructor = search_method(*jni_env, boolean_cls, "<init>", "(Z)V", false); + + jobject result = jni_env->NewObject(boolean_cls, constructor, v ? JNI_TRUE : JNI_FALSE); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothDevice_disableConnectedNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothDevice *obj_device = + getInstance<BluetoothDevice>(env, obj); + obj_device->disable_connected_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +jobjectArray Java_tinyb_BluetoothDevice_getUUIDs(JNIEnv *env, jobject obj) { try { BluetoothDevice *obj_device = getInstance<BluetoothDevice>(env, obj); diff --git a/java/jni/BluetoothGattCharacteristic.cxx b/java/jni/BluetoothGattCharacteristic.cxx index cc8b15c..e64e176 100644 --- a/java/jni/BluetoothGattCharacteristic.cxx +++ b/java/jni/BluetoothGattCharacteristic.cxx @@ -29,6 +29,7 @@ #include "tinyb_BluetoothGattCharacteristic.h" +#include "JNIMem.hpp" #include "helper.hpp" using namespace tinyb; @@ -130,12 +131,24 @@ jboolean Java_tinyb_BluetoothGattCharacteristic_writeValue(JNIEnv *env, jobject return JNI_FALSE; } -jboolean Java_tinyb_BluetoothGattCharacteristic_enableValueNotifications(JNIEnv *env, jobject obj, jobject runnable) +void Java_tinyb_BluetoothGattCharacteristic_enableValueNotifications(JNIEnv *env, jobject obj, jobject callback) { try { BluetoothGattCharacteristic *obj_gatt_char = getInstance<BluetoothGattCharacteristic>(env, obj); - return JNI_FALSE; + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_gatt_char->enable_value_notifications([ callback_ptr ] (std::vector<unsigned char> &v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + unsigned int size = v.size(); + + jbyteArray result = jni_env->NewByteArray((jsize)size); + jni_env->SetByteArrayRegion(result, 0, (jsize)size, (const jbyte *)&v[0]); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); } catch (std::bad_alloc &e) { raise_java_oom_exception(env, e); } catch (BluetoothException &e) { @@ -147,15 +160,14 @@ jboolean Java_tinyb_BluetoothGattCharacteristic_enableValueNotifications(JNIEnv } catch (std::exception &e) { raise_java_exception(env, e); } - return JNI_FALSE; } -jboolean Java_tinyb_BluetoothGattCharacteristic_disableValueNotifications(JNIEnv *env, jobject obj) +void Java_tinyb_BluetoothGattCharacteristic_disableValueNotifications(JNIEnv *env, jobject obj) { try { BluetoothGattCharacteristic *obj_gatt_char = getInstance<BluetoothGattCharacteristic>(env, obj); - return JNI_FALSE; + obj_gatt_char->disable_value_notifications(); } catch (std::bad_alloc &e) { raise_java_oom_exception(env, e); } catch (BluetoothException &e) { @@ -167,7 +179,6 @@ jboolean Java_tinyb_BluetoothGattCharacteristic_disableValueNotifications(JNIEnv } catch (std::exception &e) { raise_java_exception(env, e); } - return JNI_FALSE; } jstring Java_tinyb_BluetoothGattCharacteristic_getUuid(JNIEnv *env, jobject obj) @@ -344,4 +355,3 @@ void Java_tinyb_BluetoothGattCharacteristic_delete(JNIEnv *env, jobject obj) raise_java_exception(env, e); } } - diff --git a/java/jni/BluetoothGattDescriptor.cxx b/java/jni/BluetoothGattDescriptor.cxx index e6d2b2f..db81a34 100644 --- a/java/jni/BluetoothGattDescriptor.cxx +++ b/java/jni/BluetoothGattDescriptor.cxx @@ -28,6 +28,7 @@ #include "tinyb_BluetoothGattDescriptor.h" +#include "JNIMem.hpp" #include "helper.hpp" using namespace tinyb; @@ -203,6 +204,57 @@ jbyteArray Java_tinyb_BluetoothGattDescriptor_getValue(JNIEnv *env, jobject obj) return nullptr; } +void Java_tinyb_BluetoothGattDescriptor_enableValueNotifications(JNIEnv *env, jobject obj, jobject callback) +{ + try { + BluetoothGattDescriptor *obj_gatt_desc = + getInstance<BluetoothGattDescriptor>(env, obj); + std::shared_ptr<JNIGlobalRef> callback_ptr(new JNIGlobalRef(callback)); + obj_gatt_desc->enable_value_notifications([ callback_ptr ] (std::vector<unsigned char> &v) + { + jclass notification = search_class(*jni_env, JAVA_PACKAGE "/BluetoothNotification"); + jmethodID method = search_method(*jni_env, notification, "run", "(Ljava/lang/Object;)V", false); + unsigned int size = v.size(); + + jbyteArray result = jni_env->NewByteArray((jsize)size); + jni_env->SetByteArrayRegion(result, 0, (jsize)size, (const jbyte *)&v[0]); + + jni_env->CallVoidMethod(**callback_ptr, method, result); + + }); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + +void Java_tinyb_BluetoothGattDescriptor_disableValueNotifications(JNIEnv *env, jobject obj) +{ + try { + BluetoothGattDescriptor *obj_gatt_desc = + getInstance<BluetoothGattDescriptor>(env, obj); + obj_gatt_desc->disable_value_notifications(); + } catch (std::bad_alloc &e) { + raise_java_oom_exception(env, e); + } catch (BluetoothException &e) { + raise_java_bluetooth_exception(env, e); + } catch (std::runtime_error &e) { + raise_java_runtime_exception(env, e); + } catch (std::invalid_argument &e) { + raise_java_invalid_arg_exception(env, e); + } catch (std::exception &e) { + raise_java_exception(env, e); + } +} + + void Java_tinyb_BluetoothGattDescriptor_delete(JNIEnv *env, jobject obj) { try { diff --git a/java/jni/JNIMem.cxx b/java/jni/JNIMem.cxx new file mode 100644 index 0000000..7c34a98 --- /dev/null +++ b/java/jni/JNIMem.cxx @@ -0,0 +1,10 @@ +#include "JNIMem.hpp" + + +JavaVM* vm; +thread_local JNIEnvContainer jni_env; + +jint JNI_OnLoad(JavaVM *initVM, void *reserved) { + vm = initVM; + return JNI_VERSION_1_8; +} diff --git a/java/jni/JNIMem.hpp b/java/jni/JNIMem.hpp new file mode 100644 index 0000000..3b20e05 --- /dev/null +++ b/java/jni/JNIMem.hpp @@ -0,0 +1,65 @@ +#pragma once +#include <jni.h> +#include <stdexcept> + +extern JavaVM* vm; + +class JNIEnvContainer { +private: + JNIEnv *env = nullptr; + +public: + JNIEnv *operator*() { + attach(); + return env; + } + + JNIEnv *operator->() { + attach(); + return env; + } + + JNIEnvContainer() { + } + + ~JNIEnvContainer() { + detach(); + } + + void attach() { + if (env != nullptr) + return; + jint err = vm->AttachCurrentThreadAsDaemon((void **)&env, NULL); + if (err != JNI_OK) + throw std::runtime_error("Attach to VM failed"); + } + + void detach() { + if (env == nullptr) + return; + vm->DetachCurrentThread(); + env = nullptr; + } +}; + +extern thread_local JNIEnvContainer jni_env; + +class JNIGlobalRef { +private: + jobject object; + +public: + + JNIGlobalRef(jobject object) { + this->object = jni_env->NewGlobalRef(object); + } + + ~JNIGlobalRef() { + jni_env->DeleteGlobalRef(object); + } + + jobject operator*() { + return object; + } +}; + diff --git a/src/BluetoothDevice.cpp b/src/BluetoothDevice.cpp index 943efc6..ad040d8 100644 --- a/src/BluetoothDevice.cpp +++ b/src/BluetoothDevice.cpp @@ -310,6 +310,10 @@ void BluetoothDevice::enable_paired_notifications( void *userdata) { paired_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata); } +void BluetoothDevice::enable_paired_notifications( + std::function<void(bool)> callback) { + paired_callback = callback; +} void BluetoothDevice::disable_paired_notifications() { paired_callback = nullptr; } |