publishJNI(instance, topic, data, dataLen, protocol, qos, retain);
}
+ /**
+ * JNI Interface API to set will info data to specified MQTT topic
+ *
+ * @param topic String to which message needs to be published
+ * @param data Byte message to be published
+ * @param dataLen Size/length of the message to be published
+ * @param qos QoS at which the message should be delivered
+ * @param retain Boolean to decide whether or not the message should be retained by the broker
+ */
+ public void setWillInfo(final String topic, final byte[] data, long dataLen, int qos, boolean retain) {
+ setWillInfoJNI(instance, topic, data, dataLen, qos, retain);
+ }
+
/**
* JNI Interface API to unsubscribe the given topic
* @param aittSubId Subscribe ID of the topics to be unsubscribed
/* Native API for publishing to a topic */
private native void publishJNI(long instance, final String topic, final byte[] data, long dataLen, int protocol, int qos, boolean retain);
+ /* Native API for set will info to a topic */
+ private native void setWillInfoJNI(long instance, final String topic, final byte[] data, long dataLen, int qos, boolean retain);
+
/* Native API for subscribing to a topic */
private native long subscribeJNI(long instance, final String topic, int protocol, int qos);
env->ReleaseByteArrayElements(data, reinterpret_cast<jbyte *>((char *) cdata), 0);
}
+/**
+ * JNI API to set will info data to a given MQTT topic
+ * @param env JNI interface pointer
+ * @param jni_interface_object JNI interface object
+ * @param handle AittNativeInterface object
+ * @param topic subscribe topic
+ * @param data data to be published
+ * @param data_len data length of a publishing data
+ * @param protocol publishing protocol
+ * @param qos publishing qos
+ * @param retain Currently used in MQTT to inform broker to retain data or not
+ */
+void AittNativeInterface::SetWillInfo(JNIEnv *env, jobject jni_interface_object, jlong handle,
+ jstring topic, jbyteArray data, jlong data_len, jint qos, jboolean retain)
+{
+ if (!CheckParams(env, jni_interface_object)) {
+ return;
+ }
+
+ auto *instance = reinterpret_cast<AittNativeInterface *>(handle);
+ std::string mqttTopic = GetStringUTF(env, topic);
+ if (mqttTopic.empty()) {
+ return;
+ }
+
+ const char *cdata = (char *)env->GetByteArrayElements(data, nullptr);
+ if (cdata == nullptr) {
+ JNI_LOG(ANDROID_LOG_ERROR, TAG, "Failed to get byte array elements");
+ return;
+ }
+ const void *_data = reinterpret_cast<const void *>(cdata);
+
+ auto _qos = static_cast<AittQoS>(qos);
+ bool _retain = (bool) retain;
+
+ try {
+ instance->aitt.SetWillInfo(mqttTopic, _data, (int) data_len, _qos, _retain);
+ } catch (std::exception &e) {
+ JNI_LOG(ANDROID_LOG_ERROR, TAG, "Failed to SetWillInfo");
+ JNI_LOG(ANDROID_LOG_ERROR, TAG, e.what());
+ }
+ env->ReleaseByteArrayElements(data, reinterpret_cast<jbyte *>((char *) cdata), 0);
+}
+
/**
* JNI API to disconnect from MQTT broker
* @param env JNI interface pointer
return JNI_ERR;
}
static JNINativeMethod aitt_jni_methods[] = {
- {"initJNI", "(Ljava/lang/String;Ljava/lang/String;Z)J", reinterpret_cast<void *>(AittNativeInterface::Init)},
- {"connectJNI", "(JLjava/lang/String;I)V", reinterpret_cast<void *>(AittNativeInterface::Connect)},
- {"subscribeJNI", "(JLjava/lang/String;II)J", reinterpret_cast<void *>(AittNativeInterface::Subscribe)},
- {"publishJNI", "(JLjava/lang/String;[BJIIZ)V", reinterpret_cast<void *>(AittNativeInterface::Publish)},
- {"unsubscribeJNI", "(JJ)V", reinterpret_cast<void *>(AittNativeInterface::Unsubscribe)},
- {"disconnectJNI", "(J)V", reinterpret_cast<void *>(AittNativeInterface::Disconnect)},
- {"setConnectionCallbackJNI", "(J)V", reinterpret_cast<void *>(AittNativeInterface::SetConnectionCallback)},
- {"setDiscoveryCallbackJNI", "(JLjava/lang/String;)I", reinterpret_cast<void *>(AittNativeInterface::SetDiscoveryCallback)},
- {"removeDiscoveryCallbackJNI", "(JI)V", reinterpret_cast<void *>(AittNativeInterface::RemoveDiscoveryCallback)},
- {"updateDiscoveryMessageJNI", "(JLjava/lang/String;[BJ)V", reinterpret_cast<void *>(AittNativeInterface::UpdateDiscoveryMessage)}};
+ {"initJNI", "(Ljava/lang/String;Ljava/lang/String;Z)J", reinterpret_cast<void *>(AittNativeInterface::Init)},
+ {"connectJNI", "(JLjava/lang/String;I)V", reinterpret_cast<void *>(AittNativeInterface::Connect)},
+ {"subscribeJNI", "(JLjava/lang/String;II)J", reinterpret_cast<void *>(AittNativeInterface::Subscribe)},
+ {"publishJNI", "(JLjava/lang/String;[BJIIZ)V", reinterpret_cast<void *>(AittNativeInterface::Publish)},
+ {"setWillInfoJNI", "(JLjava/lang/String;[BJIZ)V", reinterpret_cast<void *>(AittNativeInterface::SetWillInfo)},
+ {"unsubscribeJNI", "(JJ)V", reinterpret_cast<void *>(AittNativeInterface::Unsubscribe)},
+ {"disconnectJNI", "(J)V", reinterpret_cast<void *>(AittNativeInterface::Disconnect)},
+ {"setConnectionCallbackJNI", "(J)V", reinterpret_cast<void *>(AittNativeInterface::SetConnectionCallback)},
+ {"setDiscoveryCallbackJNI", "(JLjava/lang/String;)I", reinterpret_cast<void *>(AittNativeInterface::SetDiscoveryCallback)},
+ {"removeDiscoveryCallbackJNI", "(JI)V", reinterpret_cast<void *>(AittNativeInterface::RemoveDiscoveryCallback)},
+ {"updateDiscoveryMessageJNI", "(JLjava/lang/String;[BJ)V", reinterpret_cast<void *>(AittNativeInterface::UpdateDiscoveryMessage)}};
if (env->RegisterNatives(klass, aitt_jni_methods,
sizeof(aitt_jni_methods) / sizeof(aitt_jni_methods[0]))) {
env->DeleteLocalRef(klass);
private static final String TAG = "AITT_ANDROID";
private static final String INVALID_TOPIC = "Invalid topic";
+ private static final String INVALID_WILL_INFO = "Invalid will info";
private static final String HOST_STRING = "host";
private final Map<String, HostTable> publishTable = new HashMap<>();
publishTransportProtocols(topic, message, protocols);
}
+ /**
+ * Method to set will info message to a specific mqtt topic with qos, and retain
+ *
+ * @param topic String to which message needs to be published
+ * @param data Byte message that needs to be published
+ * @param qos QoS at which the message should be delivered
+ * @param retain Boolean to decide whether or not the message should be retained by the broker
+ */
+ public void setWillInfo(String topic, byte[] data, QoS qos, boolean retain) {
+ if (topic == null || topic.isEmpty()) {
+ throw new IllegalArgumentException(INVALID_TOPIC);
+ }
+ if (data == null || data.length <= 0) {
+ throw new IllegalArgumentException(INVALID_WILL_INFO);
+ }
+ mJniInterface.setWillInfo(topic, data, data.length, qos.ordinal(), retain);
+ }
+
/**
* Method to publish message to a specific topic with transport protocols
*
}
}
+ @Test
+ public void testSetWillInfoMqtt_P() {
+ try {
+ String willInfo = "Test Will info data";
+ shadowJniInterface.setInitReturn(true);
+ Aitt aitt = new Aitt(appContext, aittId);
+ byte[] data = willInfo.getBytes();
+ aitt.setWillInfo(topic, data, Aitt.QoS.AT_MOST_ONCE, false);
+ aitt.connect(brokerIp, port);
+ aitt.disconnect();
+ } catch (Exception e) {
+ fail("Failed testSetWillInfoMqtt_P " + e);
+ }
+ }
+
+ @Test
+ public void testWithoutWillInfo_N() {
+ try {
+ String willInfo = "";
+ shadowJniInterface.setInitReturn(true);
+ Aitt aitt = new Aitt(appContext, aittId);
+ byte[] data = willInfo.getBytes();
+ assertThrows(IllegalArgumentException.class, () -> aitt.setWillInfo(topic, data, Aitt.QoS.AT_MOST_ONCE, false));
+ aitt.connect(brokerIp, port);
+ aitt.disconnect();
+ } catch (Exception e) {
+ fail("Failed testWithoutWillInfo_N " + e);
+ }
+ }
+
+ @Test
+ public void testWillInfoWithoutTopic_N() {
+ try {
+ String _topic = "";
+ String willInfo = "Test Will info data";
+ shadowJniInterface.setInitReturn(true);
+ Aitt aitt = new Aitt(appContext, aittId);
+ byte[] data = willInfo.getBytes();
+ assertThrows(IllegalArgumentException.class, () -> aitt.setWillInfo(_topic, data, Aitt.QoS.AT_MOST_ONCE, false));
+ aitt.connect(brokerIp, port);
+ aitt.disconnect();
+ } catch (Exception e) {
+ fail("Failed testWillInfoWithoutTopic_N " + e);
+ }
+ }
+
@Test
public void testConnectWithoutIP_P() {
try {