diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 89db45c95b..8fb0dea2f6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -208,10 +208,6 @@
android:host="*"
android:pathPrefix="@string/path_rx_bridge"
android:scheme="wear" />
-
{
+ rxPath -> {
aapsLogger.debug(LTag.WEAR, "onMessageReceived rxPath: ${String(messageEvent.data)}")
val command = EventData.deserialize(String(messageEvent.data))
rxBus.send(command.also { it.sourceNodeId = messageEvent.sourceNodeId })
}
-
- exceptionPath -> logWearException(messageEvent)
}
}
}
- private fun logWearException(messageEvent: MessageEvent) {
- aapsLogger.debug(LTag.WEAR, "logWearException")
- val map = DataMap.fromByteArray(messageEvent.data)
- val bis = ByteArrayInputStream(map.getByteArray("exception"))
- try {
- val ois = ObjectInputStream(bis)
- fabricPrivacy.getInstance().apply {
- setCustomKey("wear_exception", true)
- setCustomKey("wear_board", map.getString("board") ?: "unknown")
- setCustomKey("wear_fingerprint", map.getString("fingerprint") ?: "unknown")
- setCustomKey("wear_sdk", map.getString("sdk") ?: "unknown")
- setCustomKey("wear_model", map.getString("model") ?: "unknown")
- setCustomKey("wear_manufacturer", map.getString("manufacturer") ?: "unknown")
- setCustomKey("wear_product", map.getString("product") ?: "unknown")
- }
- fabricPrivacy.logException(ois.readObject() as Throwable)
- } catch (e: IOException) {
- e.printStackTrace()
- } catch (e: ClassNotFoundException) {
- e.printStackTrace()
- }
- }
-
private var transcriptionNodeId: String? = null
private fun updateTranscriptionCapability() {
diff --git a/core/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.kt b/core/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.kt
index 7ec112ce9f..46a8813120 100644
--- a/core/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.kt
+++ b/core/src/main/java/info/nightscout/androidaps/utils/FabricPrivacy.kt
@@ -10,6 +10,10 @@ import info.nightscout.androidaps.core.R
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
+import info.nightscout.shared.weardata.EventData
+import java.io.ByteArrayInputStream
+import java.io.IOException
+import java.io.ObjectInputStream
import javax.inject.Inject
import javax.inject.Singleton
@@ -77,13 +81,9 @@ class FabricPrivacy @Inject constructor(
}
}
- fun getInstance(): FirebaseCrashlytics {
- return FirebaseCrashlytics.getInstance()
- }
-
// Crashlytics log message
fun logMessage(message: String) {
- aapsLogger.info(LTag.CORE,"Crashlytics log message: $message")
+ aapsLogger.info(LTag.CORE, "Crashlytics log message: $message")
FirebaseCrashlytics.getInstance().log(message)
}
@@ -96,4 +96,31 @@ class FabricPrivacy @Inject constructor(
fun fabricEnabled(): Boolean {
return sp.getBoolean(R.string.key_enable_fabric, true)
}
-}
\ No newline at end of file
+
+ fun logWearException(wearException: EventData.WearException) {
+ aapsLogger.debug(LTag.WEAR, "logWearException")
+ FirebaseCrashlytics.getInstance().apply {
+ setCustomKey("wear_exception", true)
+ setCustomKey("wear_board", wearException.board)
+ setCustomKey("wear_fingerprint", wearException.fingerprint)
+ setCustomKey("wear_sdk", wearException.sdk)
+ setCustomKey("wear_model", wearException.model)
+ setCustomKey("wear_manufacturer", wearException.manufacturer)
+ setCustomKey("wear_product", wearException.product)
+ }
+ logException(byteArrayToThrowable(wearException.exception))
+ }
+
+ private fun byteArrayToThrowable(wearExceptionData: ByteArray): Throwable {
+ val bis = ByteArrayInputStream(wearExceptionData)
+ try {
+ val ois = ObjectInputStream(bis)
+ return ois.readObject() as Throwable
+ } catch (e: IOException) {
+ e.printStackTrace()
+ } catch (e: ClassNotFoundException) {
+ e.printStackTrace()
+ }
+ return IllegalArgumentException("Wear Exception could not be de-serialized")
+ }
+}
diff --git a/shared/src/main/java/info/nightscout/shared/weardata/EventData.kt b/shared/src/main/java/info/nightscout/shared/weardata/EventData.kt
index c2d38b1d4d..6d78a1cd3e 100644
--- a/shared/src/main/java/info/nightscout/shared/weardata/EventData.kt
+++ b/shared/src/main/java/info/nightscout/shared/weardata/EventData.kt
@@ -25,6 +25,18 @@ sealed class EventData : Event() {
@Serializable
data class ActionPong(val timeStamp: Long, val apiLevel: Int) : EventData()
+ @Serializable
+ data class WearException(
+ val timeStamp: Long,
+ val exception: ByteArray,
+ val board: String,
+ val fingerprint: String,
+ val sdk: String,
+ val model: String,
+ val manufacturer: String,
+ val product: String
+ ) : EventData()
+
@Serializable
data class Error(val timeStamp: Long) : EventData() // ignored
@@ -134,9 +146,9 @@ sealed class EventData : Event() {
override fun equals(other: Any?): Boolean =
when {
- other !is SingleBg -> false
+ other !is SingleBg -> false
color != other.color -> false
- else -> timeStamp == other.timeStamp
+ else -> timeStamp == other.timeStamp
}
override fun hashCode(): Int {
diff --git a/shared/src/main/res/values/wear_paths.xml b/shared/src/main/res/values/wear_paths.xml
index defc5544a9..36d7325849 100644
--- a/shared/src/main/res/values/wear_paths.xml
+++ b/shared/src/main/res/values/wear_paths.xml
@@ -1,5 +1,4 @@
/rx_bridge
- /wear_error
-
+
\ No newline at end of file
diff --git a/wear/src/main/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml
index dba8a05295..3d10810e37 100644
--- a/wear/src/main/AndroidManifest.xml
+++ b/wear/src/main/AndroidManifest.xml
@@ -537,8 +537,6 @@
android:resource="@drawable/quick_wizard_tile_preview" />
-
-
+ Log.d("WEAR", "uncaughtException :" + ex.message)
+
+ // Pass the exception to the bus which will send the data upstream to your Smartphone/Tablet
+ val wearException = EventData.WearException(
+ timeStamp = System.currentTimeMillis(),
+ exception = exceptionToByteArray(ex),
+ board = Build.BOARD,
+ sdk = Build.VERSION.SDK_INT.toString(),
+ fingerprint = Build.FINGERPRINT,
+ model = Build.MODEL,
+ manufacturer = Build.MANUFACTURER,
+ product = Build.PRODUCT
+ )
+ rxBus.send(EventWearToMobile(wearException))
+
+ // Let the default UncaughtExceptionHandler take it from here
+ mDefaultUEH?.uncaughtException(thread, ex)
+ }
+
+ fun register() {
+ mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler()
+ Thread.setDefaultUncaughtExceptionHandler(mWearUEH)
+ }
+
+ private fun exceptionToByteArray(ex: Throwable): ByteArray {
+ ex.stackTrace // Make sure the stacktrace gets built up
+ val bos = ByteArrayOutputStream()
+ var oos: ObjectOutputStream? = null
+ try {
+ oos = ObjectOutputStream(bos)
+ oos.writeObject(ex)
+ return bos.toByteArray()
+
+ } catch (e: IOException) {
+ e.printStackTrace()
+ } finally {
+ try {
+ oos?.close()
+ } catch (exx: IOException) {
+ // Ignore close exception
+ }
+ try {
+ bos.close()
+ } catch (exx: IOException) {
+ // Ignore close exception
+ }
+ }
+ return byteArrayOf()
+ }
+
+}
diff --git a/wear/src/main/java/info/nightscout/androidaps/comm/ExceptionService.kt b/wear/src/main/java/info/nightscout/androidaps/comm/ExceptionService.kt
deleted file mode 100644
index cc9964f142..0000000000
--- a/wear/src/main/java/info/nightscout/androidaps/comm/ExceptionService.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-package info.nightscout.androidaps.comm
-
-import android.app.IntentService
-import android.content.Context
-import android.content.Intent
-import android.os.Build
-import android.os.Handler
-import android.os.HandlerThread
-import android.util.Log
-import com.google.android.gms.tasks.Tasks
-import com.google.android.gms.wearable.CapabilityClient
-import com.google.android.gms.wearable.CapabilityInfo
-import com.google.android.gms.wearable.DataMap
-import com.google.android.gms.wearable.Node
-import com.google.android.gms.wearable.Wearable
-import info.nightscout.androidaps.R
-import java.io.ByteArrayOutputStream
-import java.io.IOException
-import java.io.ObjectOutputStream
-
-class ExceptionService : IntentService(ExceptionService::class.simpleName) {
-
- private val messageClient by lazy { Wearable.getMessageClient(this) }
- private val capabilityClient by lazy { Wearable.getCapabilityClient(this) }
- private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
- private val exceptionPath get() = getString(R.string.path_log_exception)
- private var transcriptionNodeId: String? = null
-
- override fun onCreate() {
- super.onCreate()
-
- handler.post { updateTranscriptionCapability() }
- }
-
- private fun updateTranscriptionCapability() {
- val capabilityInfo: CapabilityInfo = Tasks.await(
- capabilityClient.getCapability(DataLayerListenerServiceWear.PHONE_CAPABILITY, CapabilityClient.FILTER_REACHABLE)
- )
- Log.d("WEAR", "Nodes: ${capabilityInfo.nodes.joinToString(", ") { it.displayName + "(" + it.id + ")" }}")
- pickBestNodeId(capabilityInfo.nodes)?.let { transcriptionNodeId = it }
- Log.d("WEAR", "Selected node: $transcriptionNodeId")
- }
-
- // Find a nearby node or pick one arbitrarily
- private fun pickBestNodeId(nodes: Set): String? =
- nodes.firstOrNull { it.isNearby }?.id ?: nodes.firstOrNull()?.id
-
- private fun sendMessage(path: String, data: ByteArray) {
- transcriptionNodeId?.also { nodeId ->
- messageClient
- .sendMessage(nodeId, path, data).apply {
- addOnSuccessListener { }
- addOnFailureListener {
- Log.d("WEAR", "sendMessage: $path failure")
- }
- }
- }
- }
-
- override fun onHandleIntent(intent: Intent?) {
- Log.d("WEAR", "onHandleIntent: ErrorService $intent")
-
- val bos = ByteArrayOutputStream()
- var oos: ObjectOutputStream? = null
- try {
- oos = ObjectOutputStream(bos)
- oos.writeObject(intent?.getSerializableExtra("exception"))
- val exceptionData = bos.toByteArray()
- val dataMap = DataMap()
-
- dataMap.putString("board", Build.BOARD)
- dataMap.putString("sdk", Build.VERSION.SDK_INT.toString())
- dataMap.putString("fingerprint", Build.FINGERPRINT)
- dataMap.putString("model", Build.MODEL)
- dataMap.putString("manufacturer", Build.MANUFACTURER)
- dataMap.putString("product", Build.PRODUCT)
- dataMap.putByteArray("exception", exceptionData)
-
- handler.post {
- sendMessage(exceptionPath, dataMap.toByteArray())
- }
- } catch (e: IOException) {
- e.printStackTrace()
- } finally {
- try {
- oos?.close()
- } catch (exx: IOException) {
- // ignore close exception
- }
- try {
- bos.close()
- } catch (exx: IOException) {
- // ignore close exception
- }
- }
- }
-
- init {
- setIntentRedelivery(true)
- }
-
- companion object {
- fun reportException(context: Context, ex: Throwable?) {
- val errorIntent = Intent(context, ExceptionService::class.java)
- errorIntent.putExtra("exception", ex)
- context.startService(errorIntent)
- }
- }
-
-}
diff --git a/wear/src/main/java/info/nightscout/androidaps/comm/ExceptionWear.kt b/wear/src/main/java/info/nightscout/androidaps/comm/ExceptionWear.kt
deleted file mode 100644
index 1bbc18ab8b..0000000000
--- a/wear/src/main/java/info/nightscout/androidaps/comm/ExceptionWear.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package info.nightscout.androidaps.comm
-
-import android.content.Context
-import android.util.Log
-
-class ExceptionWear(private val context: Context) {
-
- private var mDefaultUEH: Thread.UncaughtExceptionHandler? = null
-
- private val mWearUEH = Thread.UncaughtExceptionHandler { thread, ex ->
- Log.d("WEAR", "uncaughtException :" + ex.message)
- // Pass the exception to a Service which will send the data upstream to your Smartphone/Tablet
- ExceptionService.reportException(context, ex)
- // Let the default UncaughtExceptionHandler take it from here
- mDefaultUEH?.uncaughtException(thread, ex)
- }
-
- init {
- mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler()
- Thread.setDefaultUncaughtExceptionHandler(mWearUEH)
- }
-
-}