Toss a Coin to your Widget! Or don’t…

Part 3 of 3

Sarah Will
intive Developers
5 min readAug 27, 2021

--

Written by Sarah Will, Jenni Thieroff and Miriam Cordes

A descriptive article image showing a blurred IDE, coins, a smartphone with an installed Home screen widget and a screaming emoji
Toss a Coin to your Widget! Or don’t…¹

Welcome to the final part of our three-part series on Android widgets. In the first part, we focused on the use of background processes in the context of widgets and in the second part we looked at the UI of widgets. In part three, we want to delve into debugging widgets, what to keep in mind as soon as your widget is live and more.

PendingIntents like to be unique

This is more of a general “problem” with PendingIntents, but since they’re an integral part of widgets, some information about them:

PendingIntents need to be unique and different extras (e.g., an id to open a product detail page) aren’t enough to make them unique. You can set an action for your PendingIntent to make it unique. Keep in mind that it also must be unique if the widget is updated and, e.g., another detail page must be opened when the widget is tapped .

Debugging woes

As widgets rely on RemoteViews, debugging might be quite a challenge at times. Classic step through debugging in the IDE is only possible with your part of the widget code, and errors that happen within the RemoteViews often seem hard to analyze. While implementing a new widget, there is the one widget state that everybody fears: the “Problem loading widget” state.

A screenshot of an Android widget on a phone home screen with an error message that says “Problem loading widget”
“Problem loading widget” error message

When your widget only shows this text instead of your layout, this usually means that something went wrong when trying to inflate a layout for the widget or updating the RemoteViews. Those kinds of errors are usually not displayed in the logs for your application but can only be seen when updating the Logcat filter to also show system logs. Usually, they should appear with the tag AppWidgetHostView and provide enough information about the error. In rarer cases the error might also be caused by the launcher installed on the device — read on for more information on that.

A screenshot of the Android Studio Logcat window showing an error log regarding Widget view inflation for the tag AppWidgetHostView
AppWidgetHostView error warning message in Logcat

Wayward Launchers

Depending on what kind of launcher app you have installed on your device, you might see erratic or inexplicable behavior with your widgets. We saw launchers that ignore the resizeMode flag and/or dimension restrictions completely, as well as launchers that seem to cache more widget information than others, weirdly enough even across different widget providers. This might lead to errors when updating your app with a newer or older version during development — even with a fresh install — like widgets trying to use layouts from other AppWidgetProviders, leading to the dreaded “Problem loading widget” state when ids are not found.

If you experience any behavior with your widgets that is not explainable by any obvious bugs in your code, try to clear your launcher cache and see if the problem persists or try out another launcher and see how your widgets behave there.

It’s all in a name

Another not-so-obvious piece of the widget puzzle is that once you’ve released a version with your new and shiny widget, you should not change the name of your widget provider classes or their location in the package structure again, or you risk breaking your users’ existing widgets.

Launchers identify a widget via its ComponentName (this is also the way how you can retrieve the ids for your Providers’ widgets in your code). Changing the name or package of a class extending AppWidgetProvider will change their ComponentName. Existing widgets with the older name can then no longer be referenced correctly, and therefore, no longer be updated. The only way to get a working widget again in this scenario is to add it to the launcher anew, but of course, users shouldn’t be required to do that.

Knowing this, you should ensure that the name and location of your provider class is fixed and won’t be changed in the future unless you are prepared to deal with the consequences.

If you are using obfuscation tools like Proguard/R8, using the default Android configuration should ensure that classes extending AppWidgetProvider are not renamed but be sure to double-check for renaming in case of custom configurations or tooling.

More changes after going live?

Changing the identifier of your widget provider is not the only thing that might affect your widgets that are already out in the wild in other ways than you would think. If you want to change widget attributes that are configured in the widget provider’s xml file, changes to some of those attributes will not affect already existing widgets. Instead, the old values will be used.
We observed these attributes to ignore changes:

  • minWidth
  • maxWidth
  • minHeight
  • maxHeight
  • updatePeriodMillis

Other attributes like the initialLayout and the resizeMode flags, however, will be applied to existing widget instances — at least that’s what we experienced on a standard Pixel launcher.

For those attributes that are not updated on existing widgets, to get the current version of the widget, it needs to be added again via the widget chooser. Therefore, if any of the changes are rolled out to fix bugs or unwanted behavior, it might be wise to inform your users about the changes and that the problems might only be fixed for them if they add the widget anew.

Overall, there are a lot of caveats and pitfalls when developing a widget for Android nowadays. It made us want to tear our hair more often than we would like to admit, so we decided to author this article so that you will not have to experience the same pain as we did.

At a first glance, the changes coming to widgets with Android 12 promise some improvements. We will stay tuned and are excited to get our hands dirty with the new APIs!

[1]: Emoji by Noto Emoji fonts, Photo of carrots by Chokniti Khongchum from Pexels

--

--