I have a widget that's created using jetpack glanc...
# glance
n
I have a widget that's created using jetpack glance API. It stops working once I do an app update. Can someone please help here? I will post the relevant code in the thread below
Copy code
<receiver
    android:name="ai.blox100.widgetReceiver.UsageResizableWidgetReceiver4x2"
    android:exported="true">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/usage_most_used_apps_widget_info" />
</receiver>
Copy code
@AndroidEntryPoint
class UsageResizableWidgetReceiver4x2 : GlanceAppWidgetReceiver() {
    @Inject
    lateinit var logUserEvent: LogAnalyticsUserProperty

    @Inject
    lateinit var logAnalyticsEvent: LogAnalyticsEvent

    override val glanceAppWidget: GlanceAppWidget = UsageResizableWidget()
    override fun onDeleted(context: Context, appWidgetIds: IntArray) {
        super.onDeleted(context, appWidgetIds)
        val props = JSONObject()
        props.put("source", "big_widget")
        props.put("action", "removed")
        logUserEvent(AnalyticsEvent.USER_PROPERTY_WIDGET_STATUS_BIG, "removed", props)
    }

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray,
    ) {
        super.onUpdate(context, appWidgetManager, appWidgetIds)
        val props = JSONObject()
        props.put("source", "big_widget")
        props.put("action", "added")
        logUserEvent(AnalyticsEvent.USER_PROPERTY_WIDGET_STATUS_BIG, "added", props)
    }

    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)
        if (intent.action == StringConstants.ACTION_WIDGET_PINNED) {
            Log.d("widgetPromo", "Widget pinned successfully!")
            val props = JSONObject()
            props.put("source", "big_widget")
            props.put("action", "success")
            logAnalyticsEvent(AnalyticsEvent.WIDGET_ADD_STATUS, props)
            // Handle the widget being successfully pinned
            Toast.makeText(context, "Widget pinned successfully in Home screen!", Toast.LENGTH_SHORT).show()
        }
    }
}
Copy code
class UsageResizableWidget : GlanceAppWidget() {

    companion object {
        private val SMALL_SQUARE = DpSize(130.dp, 120.dp)
        private val HORIZONTAL_RECTANGLE = DpSize(230.dp, 120.dp)
    }

    override val sizeMode = SizeMode.Responsive(
        setOf(
            SMALL_SQUARE,
            HORIZONTAL_RECTANGLE,
        ),
    )

    @EntryPoint
    @InstallIn(SingletonComponent::class)
    interface UsageWithMostUsedAppsWidgetProviderEntryPoint {
        fun usageWidgetRepository(): UsageWidgetRepository
    }

    override var stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition
    override suspend fun provideGlance(context: Context, id: GlanceId) {
        Log.d("GlanceUsageWithMostUsedAppsWidget", "provideGlance: called")
        val appContext = context.applicationContext ?: throw IllegalStateException()
        val usageWidgetEntryPoint =
            EntryPointAccessors.fromApplication(
                appContext,
                UsageWithMostUsedAppsWidgetProviderEntryPoint::class.java,
            )
        val usageWidgetRepository = usageWidgetEntryPoint.usageWidgetRepository()

        // set value
        val usageData = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
            Log.d("GlanceUsageWithMostUsedAppsWidget", "getUsageData: called")

            usageWidgetRepository.getUsageData()
        }

        Toast.makeText(
            context,
            "got usage data",
            Toast.LENGTH_SHORT,
        ).show()

        // display value
        provideContent {
            val prefs = currentState<Preferences>()
            val usageWidgetData = prefs[usageWidgetKey] ?: usageWidgetDataToJson(usageData)
            Toast.makeText(
                context,
                "provideContent: usageData",
                Toast.LENGTH_SHORT,
            ).show()
            val data = jsonToUsageWidgetData(usageWidgetData)
            Log.d("GlanceUsageWithMostUsedAppsWidget", "data: $data")
            val size = LocalSize.current

            if (data != null) {
                val usageScreenTimeString = DateTimeUtil.getHumanReadableString(
                    appUsageInMinutes = data.totalPhoneUsageInMillis.toMinutes(),
                    smallFormat = true,
                    highlight = true,
                )

                Toast.makeText(
                    context,
                    "data not null",
                    Toast.LENGTH_SHORT,
                ).show()
                val mostUsedApps = data.mostUsedApps
                Log.d(
                    "GlanceUsageWithMostUsedAppsWidget",
                    "UsageTime: $usageScreenTimeString, mostUsedApps: ${data.mostUsedApps}",
                )
                Row(
                    modifier = GlanceModifier
                        .fillMaxWidth()
                        .background(neutral5)
                        .cornerRadiusCompat(R.drawable.rounded_background, 16.dp, neutral5)
                        .padding(20.dp)
                        .clickable(
                            onClick = actionStartActivity<HomePageActivity>(
                                actionParametersOf(openAppUsageScreenKey to true),
                            ),
                        ),
                    horizontalAlignment = Alignment.Horizontal.Start,
                    verticalAlignment = Alignment.Vertical.CenterVertically,
                ) {
                    Column(
                        modifier = GlanceModifier.width(124.dp),
                    ) {
                        Box(
                            modifier = GlanceModifier
                                .cornerRadius(56.dp)
                                .padding(10.dp)
                                .background(primary_green_dark),
                        ) {
                            Image(
                                provider = ImageProvider(resId = R.drawable.logo_big),
                                contentDescription = null,
                                modifier = GlanceModifier.size(14.dp),
                            )
                        }
                        Spacer(modifier = GlanceModifier.height(12.dp))
                        GlanceTextWithVariableColors(
                            textSegments = glanceParseAndHighlightText(
                                text = usageScreenTimeString,
                                normalColor = neutral100,
                                highlightColor = neutral100,
                                normalStyle = glanceHeadlineSmallBold,
                                highlightStyle = glanceDisplaySmallBold,
                            ),
                        )
                        Spacer(modifier = GlanceModifier.height(2.dp))
                        GlanceText(
                            text = "Today's Usage",
                            color = primary_green,
                            textStyle = glanceBodyXs,
                        )
                    }
                    Spacer(modifier = GlanceModifier.defaultWeight())
                    if (size.width >= HORIZONTAL_RECTANGLE.width) {
                        Column(
                            modifier = GlanceModifier,
                            verticalAlignment = Alignment.CenterVertically,
                        ) {
                            if (mostUsedApps.isNotEmpty()) {
                                mostUsedApps.forEach { item ->
                                    AppUsageRow(appUsageData = item, context = context)
                                    if (item != mostUsedApps.last()) {
                                        Spacer(modifier = GlanceModifier.height(14.dp))
                                    }
                                }
                            }
                        }
                    }
                    Spacer(modifier = GlanceModifier.defaultWeight())
                }
            } else {
                Toast.makeText(
                    context,
                    "data null",
                    Toast.LENGTH_SHORT,
                ).show()
            }
        }
    }
}
Data is updated perfectly in the widget till the app update. if i reinstall the app it works fine
k
Did you have any widget related changes in the update? Like changing the receiver's package?
n
no. I am suspecting this could be due to proguard issue. In the below code, I am trying to get the glanceIds using UsageResizableWidget::class.java which could return empty if there is obfuscation. I am debugging in this direction. thanks for the reply 🙂
Copy code
GlanceAppWidgetManager(context = context).getGlanceIds(UsageResizableWidget::class.java)
    .forEach { glanceId ->
        Log.d("GlanceWidgetUpdate", "GlanceId usageWithMostUsed $glanceId")
        updateAppWidgetState(context, glanceId) { prefs ->
            prefs[usageWidgetKey] = usageData
        }
        UsageResizableWidget().update(context, glanceId)
    }
I confirm here that it was a proguard issue. Adding @Keep annotation to UsageResizableWidget fixed the issue
k
Good to hear you solved it 😊
n
Thanks for the great support 🙏
this issue reoccured again 😞
w
hey @Nizam, did you fix it?
n
No. This gets fixed if the user restarts the phone. Looks like some bug with glance library to me
w
Okay, thank you!