Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:852)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:815)
at androidx.appcompat.app.AppCompatDelegateImpl.setContentView(AppCompatDelegateImpl.java:703)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:195)
at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:303)
at androidx.databinding.DataBindingUtil.setContentView(DataBindingUtil.java:284)
Getting this error while using the latest aar file of the 3.3.7 version.
`class MqttHelper(var context: Context, subscriptionTopic: String, subscriptionTopicPresence: String) {
lateinit var mqttAndroidClient: MqttAndroidClient
internal val serverUri = BuildConfig.MQTT_URL
internal val subscriptionTopic = subscriptionTopic
internal val presenceSubscriptionTopic = subscriptionTopicPresence
internal val username = BuildConfig.MQTT_USER
internal val password = BuildConfig.MQTT_PASSWORD
init {
try {
mqttAndroidClient = MqttAndroidClient(context, serverUri, generateMqttClientID())
mqttAndroidClient.setCallback(object : MqttCallbackExtended {
override fun connectComplete(b: Boolean, s: String) {
Log.e("MQTT", "Connect Complete: "+s)
}
override fun connectionLost(throwable: Throwable?) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(
Constant.MQTT_CONNECTION_LOST))
throwable?.let {
Log.e("MQTT", "Helper Class connection lost: $serverUri$throwable")
}
connect()
}
@kotlin.jvm.Throws(Exception::class)
override fun messageArrived(topic: String?, mqttMessage: MqttMessage?) {
var intentMsg = Intent(Constant.MQTT_MESSAGE_PAYLOAD)
intentMsg.putExtra(Constant.KEY_TOPIC, topic)
intentMsg.putExtra(Constant.KEY_PAYLOAD, mqttMessage?.payload)
override fun deliveryComplete(iMqttDeliveryToken: IMqttDeliveryToken?) {}
})
connect()
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun generateMqttClientID(): String{
return "android" + System.nanoTime()
}
/**
* This method will set the callback to the mqtt client
*/
fun setCallback(callback: MqttCallbackExtended) {
try {
mqttAndroidClient.setCallback(callback)
} catch (e: NullPointerException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* This method will connect the mqtt
*/
private fun connect() {
try {
val mqttConnectOptions = MqttConnectOptions()
mqttConnectOptions.isAutomaticReconnect = true
mqttConnectOptions.isCleanSession = true
mqttConnectOptions.userName = username
mqttConnectOptions.password = password.toCharArray()
if(BuildConfig.FLAVOR == "envProd") {
try {
val caCrtFile = context.resources.openRawResource(R.raw.ca)
val sslSocketFactory = getSingleSocketFactory(caCrtFile)
mqttConnectOptions.socketFactory = sslSocketFactory
} catch (e: Exception) {
AppLog.e("MQTT", e)
}
}
mqttAndroidClient.connect(mqttConnectOptions, context, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_CONNECTION_SUCCESS))
val disconnectedBufferOptions = DisconnectedBufferOptions()
disconnectedBufferOptions.isBufferEnabled = true
disconnectedBufferOptions.bufferSize = 100
disconnectedBufferOptions.isPersistBuffer = false
disconnectedBufferOptions.isDeleteOldestMessages = false
mqttAndroidClient.setBufferOpts(disconnectedBufferOptions)
Log.e("MQTT", "connected")
subscribeToTopic()
}
override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_CONNECTION_FAILURE))
Log.e("MQTT", "Failed to connect to: " + serverUri + exception.toString())
}
})
} catch (ex: MqttException) {
ex.printStackTrace()
Log.e("MQTT", ex.toString())
} catch (e: Exception) {
e.printStackTrace()
Log.e("MQTT", e.toString())
}
}
/**
* This method will subscribe to the topic to the mqtt client
*/
private fun subscribeToTopic() {
try {
mqttAndroidClient.subscribe(subscriptionTopic, 0, context, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_SUBSCRIBE_SUCCESS))
}
override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_SUBSCRIBE_FAILURE))
}
})
mqttAndroidClient.subscribe(presenceSubscriptionTopic, 0, context, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_SUBSCRIBE_SUCCESS))
}
override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_SUBSCRIBE_FAILURE))
}
})
} catch (ex: MqttException) {
Log.e("MQTT", ex.toString())
ex.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
Log.e("MQTT", e.toString())
}
}
/**
* This method will unsubscribe to the topic to the mqtt client
*/
fun unSubscribeToTopic() {
try {
mqttAndroidClient.unsubscribe(subscriptionTopic, context, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_UNSUBSCRIBE_SUCCESS))
}
override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_UNSUBSCRIBE_FAILURE))
}
})
mqttAndroidClient.unsubscribe(presenceSubscriptionTopic, context, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_UNSUBSCRIBE_SUCCESS))
}
override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(Constant.MQTT_UNSUBSCRIBE_FAILURE))
}
})
} catch (ex: MqttException) {
System.err.println("Exception subscribing")
Log.e("MQTT", ex.toString())
ex.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
Log.e("MQTT", e.toString())
}
}
/**
* This method will disconnect the mqtt client
*/
fun disconnectClient() {
mqttAndroidClient.unregisterResources()
mqttAndroidClient.close()
}
@kotlin.jvm.Throws(java.lang.Exception::class)
fun getSingleSocketFactory(caCrtFileInputStream: InputStream?): SSLSocketFactory? {
Security.addProvider(BouncyCastleProvider())
var caCert: java.security.cert.Certificate? = null
val bis = BufferedInputStream(caCrtFileInputStream)
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
while (bis.available() > 0) {
caCert = cf.generateCertificate(bis)
}
val caKs: KeyStore = KeyStore.getInstance(KeyStore.getDefaultType())
caKs.load(null, null)
caKs.setCertificateEntry("cert-certificate", caCert)
val tmf: TrustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(caKs)
val sslContext: SSLContext = SSLContext.getInstance("TLSv1.2")
sslContext.init(null, tmf.trustManagers, null)
return sslContext.socketFactory
}
@kotlin.jvm.Throws(java.lang.Exception::class)
fun getSocketFactory(
caCrtFile: InputStream?, crtFile: InputStream?, keyFile: InputStream?,
password: String
): SSLSocketFactory? {
Security.addProvider(BouncyCastleProvider())
// load CA certificate
var caCert: java.security.cert.Certificate? = null
var bis = BufferedInputStream(caCrtFile)
val cf = CertificateFactory.getInstance("X.509")
while (bis.available() > 0) {
caCert = cf.generateCertificate(bis)
}
// load client certificate
bis = BufferedInputStream(crtFile)
var cert: java.security.cert.Certificate? = null
while (bis.available() > 0) {
cert = cf.generateCertificate(bis)
}
// load client private cert
val pemParser = PEMParser(InputStreamReader(keyFile))
val pemParserObj = pemParser.readObject()
val converter = JcaPEMKeyConverter().setProvider("BC")
val key: KeyPair = converter.getKeyPair(pemParserObj as PEMKeyPair)
val caKs = KeyStore.getInstance(KeyStore.getDefaultType())
caKs.load(null, null)
caKs.setCertificateEntry("cert-certificate", caCert)
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
tmf.init(caKs)
val ks = KeyStore.getInstance(KeyStore.getDefaultType())
ks.load(null, null)
ks.setCertificateEntry("certificate", cert)
ks.setKeyEntry(
"private-cert",
key.getPrivate(),
password.toCharArray(),
arrayOf<java.security.cert.Certificate?>(cert)
)
val kmf: KeyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(ks, password.toCharArray())
val context = SSLContext.getInstance("TLSv1.2")
context.init(kmf.keyManagers, tmf.trustManagers, null)
return context.socketFactory
}
val mqttHelper = MqttHelper(requireContext(), subscriptionChannel, subscriptionChannelPresence)