Avoid crash of Watchface (even on wrong type of data within json file)
This commit is contained in:
parent
f8dbcf2edd
commit
af2f18acd9
3 changed files with 87 additions and 84 deletions
|
@ -17,6 +17,7 @@ import info.nightscout.rx.events.EventLoopUpdateGui
|
||||||
import info.nightscout.rx.events.EventMobileToWear
|
import info.nightscout.rx.events.EventMobileToWear
|
||||||
import info.nightscout.rx.events.EventOverviewBolusProgress
|
import info.nightscout.rx.events.EventOverviewBolusProgress
|
||||||
import info.nightscout.rx.events.EventPreferenceChange
|
import info.nightscout.rx.events.EventPreferenceChange
|
||||||
|
import info.nightscout.rx.events.EventWearUpdateGui
|
||||||
import info.nightscout.rx.logging.AAPSLogger
|
import info.nightscout.rx.logging.AAPSLogger
|
||||||
import info.nightscout.rx.weardata.CustomWatchfaceData
|
import info.nightscout.rx.weardata.CustomWatchfaceData
|
||||||
import info.nightscout.rx.weardata.EventData
|
import info.nightscout.rx.weardata.EventData
|
||||||
|
@ -91,6 +92,10 @@ class WearPlugin @Inject constructor(
|
||||||
.toObservable(EventLoopUpdateGui::class.java)
|
.toObservable(EventLoopUpdateGui::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ dataHandlerMobile.resendData("EventLoopUpdateGui") }, fabricPrivacy::logException)
|
.subscribe({ dataHandlerMobile.resendData("EventLoopUpdateGui") }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventWearUpdateGui::class.java)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({ it.customWatchfaceData?.let { cwf -> savedCustomWatchface = cwf } }, fabricPrivacy::logException)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
|
|
|
@ -106,7 +106,7 @@
|
||||||
<androidx.gridlayout.widget.GridLayout
|
<androidx.gridlayout.widget.GridLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="0dp"
|
android:layout_marginTop="20dp"
|
||||||
android:padding="10dip"
|
android:padding="10dip"
|
||||||
app:columnCount="2">
|
app:columnCount="2">
|
||||||
|
|
||||||
|
|
|
@ -116,75 +116,79 @@ class CustomWatchface : BaseWatchFace() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateSecondVisibility() {
|
override fun updateSecondVisibility() {
|
||||||
binding.second.visibility = (enableSecond && showSecond).toVisibility()
|
binding.second.visibility = showSecond.toVisibility()
|
||||||
binding.secondHand.visibility = (enableSecond && showSecond).toVisibility()
|
binding.secondHand.visibility = showSecond.toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setWatchfaceStyle() {
|
private fun setWatchfaceStyle() {
|
||||||
val customWatchface = persistence.readCustomWatchface() ?: persistence.readCustomWatchface(true)
|
val customWatchface = persistence.readCustomWatchface() ?: persistence.readCustomWatchface(true)
|
||||||
customWatchface?.let {
|
customWatchface?.let {
|
||||||
val json = JSONObject(it.customWatchfaceData.json)
|
try {
|
||||||
val drawableDataMap = it.customWatchfaceData.drawableDatas
|
val json = JSONObject(it.customWatchfaceData.json)
|
||||||
enableSecond = (if (json.has("enableSecond")) json.getBoolean("enableSecond") else false) && sp.getBoolean(R.string.key_show_seconds, true)
|
val drawableDataMap = it.customWatchfaceData.drawableDatas
|
||||||
|
enableSecond = (if (json.has("enableSecond")) json.getBoolean("enableSecond") else false) && sp.getBoolean(R.string.key_show_seconds, true)
|
||||||
|
|
||||||
highColor = if (json.has("highColor")) Color.parseColor(json.getString("highColor")) else ContextCompat.getColor(this, R.color.dark_highColor)
|
highColor = if (json.has("highColor")) Color.parseColor(json.getString("highColor")) else ContextCompat.getColor(this, R.color.dark_highColor)
|
||||||
midColor = if (json.has("midColor")) Color.parseColor(json.getString("midColor")) else ContextCompat.getColor(this, R.color.inrange)
|
midColor = if (json.has("midColor")) Color.parseColor(json.getString("midColor")) else ContextCompat.getColor(this, R.color.inrange)
|
||||||
lowColor = if (json.has("lowColor")) Color.parseColor(json.getString("lowColor")) else ContextCompat.getColor(this, R.color.low)
|
lowColor = if (json.has("lowColor")) Color.parseColor(json.getString("lowColor")) else ContextCompat.getColor(this, R.color.low)
|
||||||
lowBatColor = if (json.has("lowBatColor")) Color.parseColor(json.getString("lowBatColor")) else ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty)
|
lowBatColor = if (json.has("lowBatColor")) Color.parseColor(json.getString("lowBatColor")) else ContextCompat.getColor(this, R.color.dark_uploaderBatteryEmpty)
|
||||||
carbColor = if (json.has("carbColor")) Color.parseColor(json.getString("carbColor")) else ContextCompat.getColor(this, R.color.carbs)
|
carbColor = if (json.has("carbColor")) Color.parseColor(json.getString("carbColor")) else ContextCompat.getColor(this, R.color.carbs)
|
||||||
gridColor = if (json.has("gridColor")) Color.parseColor(json.getString("gridColor")) else ContextCompat.getColor(this, R.color.carbs)
|
gridColor = if (json.has("gridColor")) Color.parseColor(json.getString("gridColor")) else ContextCompat.getColor(this, R.color.carbs)
|
||||||
pointSize = if (json.has("pointSize")) json.getInt("pointSize") else 2
|
pointSize = if (json.has("pointSize")) json.getInt("pointSize") else 2
|
||||||
bgColor = when (singleBg.sgvLevel) {
|
bgColor = when (singleBg.sgvLevel) {
|
||||||
1L -> highColor
|
1L -> highColor
|
||||||
0L -> midColor
|
0L -> midColor
|
||||||
-1L -> lowColor
|
-1L -> lowColor
|
||||||
else -> midColor
|
else -> midColor
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.mainLayout.forEach { view ->
|
binding.mainLayout.forEach { view ->
|
||||||
view.tag?.let { tag ->
|
view.tag?.let { tag ->
|
||||||
if (json.has(tag.toString())) {
|
if (json.has(tag.toString())) {
|
||||||
var viewjson = json.getJSONObject(tag.toString())
|
var viewjson = json.getJSONObject(tag.toString())
|
||||||
var wrapContent = LayoutParams.WRAP_CONTENT
|
var wrapContent = LayoutParams.WRAP_CONTENT
|
||||||
val width = if (viewjson.has("width")) (viewjson.getInt("width") * zoomFactor).toInt() else wrapContent
|
val width = if (viewjson.has("width")) (viewjson.getInt("width") * zoomFactor).toInt() else wrapContent
|
||||||
val height = if (viewjson.has("height")) (viewjson.getInt("height") * zoomFactor).toInt() else wrapContent
|
val height = if (viewjson.has("height")) (viewjson.getInt("height") * zoomFactor).toInt() else wrapContent
|
||||||
var params = FrameLayout.LayoutParams(width, height)
|
var params = FrameLayout.LayoutParams(width, height)
|
||||||
params.topMargin = if (viewjson.has("topmargin")) (viewjson.getInt("topmargin") * zoomFactor).toInt() else 0
|
params.topMargin = if (viewjson.has("topmargin")) (viewjson.getInt("topmargin") * zoomFactor).toInt() else 0
|
||||||
params.leftMargin = if (viewjson.has("leftmargin")) (viewjson.getInt("leftmargin") * zoomFactor).toInt() else 0
|
params.leftMargin = if (viewjson.has("leftmargin")) (viewjson.getInt("leftmargin") * zoomFactor).toInt() else 0
|
||||||
view.setLayoutParams(params)
|
view.setLayoutParams(params)
|
||||||
view.visibility = if (viewjson.has("visibility")) setVisibility(viewjson.getString("visibility")) else View.GONE
|
view.visibility = if (viewjson.has("visibility")) setVisibility(viewjson.getString("visibility")) else View.GONE
|
||||||
if (view is TextView) {
|
if (view is TextView) {
|
||||||
view.rotation = if (viewjson.has("rotation")) viewjson.getInt("rotation").toFloat() else 0F
|
view.rotation = if (viewjson.has("rotation")) viewjson.getInt("rotation").toFloat() else 0F
|
||||||
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, ((if (viewjson.has("textsize")) viewjson.getInt("textsize") else 22) * zoomFactor).toFloat())
|
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, ((if (viewjson.has("textsize")) viewjson.getInt("textsize") else 22) * zoomFactor).toFloat())
|
||||||
view.gravity = setGravity(if (viewjson.has("gravity")) viewjson.getString("gravity") else "center")
|
view.gravity = setGravity(if (viewjson.has("gravity")) viewjson.getString("gravity") else "center")
|
||||||
view.setTypeface(
|
view.setTypeface(
|
||||||
setFont(if (viewjson.has("font")) viewjson.getString("font") else "sans-serif"),
|
setFont(if (viewjson.has("font")) viewjson.getString("font") else "sans-serif"),
|
||||||
Style.fromKey( viewjson.getString("fontStyle")).typeface
|
setStyle(if (viewjson.has("fontStyle")) viewjson.getString("fontStyle") else "normal")
|
||||||
)
|
)
|
||||||
if (viewjson.has("fontColor"))
|
if (viewjson.has("fontColor"))
|
||||||
view.setTextColor(getColor(viewjson.getString("fontColor")))
|
view.setTextColor(getColor(viewjson.getString("fontColor")))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view is ImageView) {
|
if (view is ImageView) {
|
||||||
view.clearColorFilter()
|
view.clearColorFilter()
|
||||||
drawableDataMap[CustomWatchfaceDrawableDataKey.fromKey(tag.toString())]?.toDrawable(resources)?.also {
|
drawableDataMap[CustomWatchfaceDrawableDataKey.fromKey(tag.toString())]?.toDrawable(resources)?.also {
|
||||||
if (viewjson.has("color"))
|
if (viewjson.has("color"))
|
||||||
it.colorFilter = changeDrawableColor(getColor(viewjson.getString("color")))
|
it.colorFilter = changeDrawableColor(getColor(viewjson.getString("color")))
|
||||||
else
|
else
|
||||||
it.clearColorFilter()
|
it.clearColorFilter()
|
||||||
view.setImageDrawable(it)
|
view.setImageDrawable(it)
|
||||||
} ?: apply {
|
} ?: apply {
|
||||||
view.setImageDrawable(CustomWatchfaceDrawableDataKey.fromKey(tag.toString()).icon?.let { context.getDrawable(it) })
|
view.setImageDrawable(CustomWatchfaceDrawableDataKey.fromKey(tag.toString()).icon?.let { context.getDrawable(it) })
|
||||||
if (viewjson.has("color"))
|
if (viewjson.has("color"))
|
||||||
view.setColorFilter(getColor(viewjson.getString("color")))
|
view.setColorFilter(getColor(viewjson.getString("color")))
|
||||||
else
|
else
|
||||||
view.clearColorFilter()
|
view.clearColorFilter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateSecondVisibility()
|
||||||
|
} catch (e:Exception) {
|
||||||
|
persistence.store(defaultWatchface(), false) // relaod correct values to avoid crash of watchface
|
||||||
}
|
}
|
||||||
updateSecondVisibility()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +225,7 @@ class CustomWatchface : BaseWatchFace() {
|
||||||
.put("textsize", view.textSize.toInt())
|
.put("textsize", view.textSize.toInt())
|
||||||
.put("gravity", getGravity(view.gravity))
|
.put("gravity", getGravity(view.gravity))
|
||||||
.put("font", getFont(view.typeface))
|
.put("font", getFont(view.typeface))
|
||||||
.put("fontStyle", Style.fromTypeface(view.typeface.style).key)
|
.put("fontStyle", getStyle(view.typeface.style))
|
||||||
.put("fontColor", String.format("#%06X", 0xFFFFFF and view.currentTextColor))
|
.put("fontColor", String.format("#%06X", 0xFFFFFF and view.currentTextColor))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -321,32 +325,22 @@ class CustomWatchface : BaseWatchFace() {
|
||||||
else -> "default"
|
else -> "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Style(val key: String, val typeface: Int) {
|
private fun setStyle(style: String): Int = when (style) {
|
||||||
NORMAL("normal", Typeface.NORMAL),
|
"normal" -> Typeface.NORMAL
|
||||||
BOLD("bold", Typeface.BOLD),
|
"bold" -> Typeface.BOLD
|
||||||
BOLD_ITALIC("bold-italic", Typeface.BOLD_ITALIC),
|
"bold-italic" -> Typeface.BOLD_ITALIC
|
||||||
ITALIC("italic", Typeface.ITALIC);
|
"italic" -> Typeface.ITALIC
|
||||||
companion object {
|
else -> Typeface.NORMAL
|
||||||
private val keyToEnumMap = HashMap<String, Style>()
|
|
||||||
private val typefaceToEnumMap = HashMap<Int, Style>()
|
|
||||||
init {
|
|
||||||
for (value in values()) keyToEnumMap[value.key] = value
|
|
||||||
for (value in values()) typefaceToEnumMap[value.typeface] = value
|
|
||||||
}
|
|
||||||
fun fromKey(key: String?): Style =
|
|
||||||
if (keyToEnumMap.containsKey(key)) {
|
|
||||||
keyToEnumMap[key] ?:NORMAL
|
|
||||||
} else {
|
|
||||||
NORMAL
|
|
||||||
}
|
|
||||||
fun fromTypeface(typeface: Int?): Style =
|
|
||||||
if (typefaceToEnumMap.containsKey(typeface)) {
|
|
||||||
typefaceToEnumMap[typeface] ?:NORMAL
|
|
||||||
} else {
|
|
||||||
NORMAL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getStyle(style: Int): String = when (style) {
|
||||||
|
Typeface.NORMAL -> "normal"
|
||||||
|
Typeface.BOLD -> "bold"
|
||||||
|
Typeface.BOLD_ITALIC -> "bold-italic"
|
||||||
|
Typeface.ITALIC -> "italic"
|
||||||
|
else -> "normal"
|
||||||
|
}
|
||||||
|
|
||||||
fun getResourceByteArray(resourceId: Int): ByteArray? {
|
fun getResourceByteArray(resourceId: Int): ByteArray? {
|
||||||
val inputStream = resources.openRawResource(resourceId)
|
val inputStream = resources.openRawResource(resourceId)
|
||||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||||
|
@ -387,7 +381,11 @@ class CustomWatchface : BaseWatchFace() {
|
||||||
if (color == "bgColor")
|
if (color == "bgColor")
|
||||||
return bgColor
|
return bgColor
|
||||||
else
|
else
|
||||||
return Color.parseColor(color)
|
return try {
|
||||||
|
Color.parseColor(color)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.GRAY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue