A Hands-On Workshop with Jetpack Compose Glance & Gemini -

Activity Instructions & Code Snippets

Slides

Widgets Are So Hot Right Now! - Google Slides

Widget Fever Workshop - Google Slides

Need help??

Join the GDG A/NZ Slack, join the #android channel, there are many developers who can answer your questions! You can find me there with the username @Katie.

Preparation work

  1. Create your Developer Profile
  2. Download Android Studio
    • Any recent version is fine - stable one is Ladybug

Activity 1 - Set up

  1. Clone the sample project MotivateMe using git and checkout the main branch
  2. Open it in Android Studio
  3. Sync MotivateMe and run it on an emulator (any emulator is fine)
  4. Feel free to update the sample data!

Activity 2 - Hello Widget!

  1. Add the glance dependencies to the app module build.gradle file (you can uncomment what has been provided)
    Click to see example code

  2. Sync the project
  3. Create a simple GlanceAppWidget that displays some text. You can do this in QuoteWidget.kt.

Tip: Also update MainActivity to update QuoteWidget on every launch using QuoteWidget().updateAll(this@MainActivity)

Click to see example code

Click to see example code - imports

  1. Create a simple GlanceAppWidgetReceiver that just has an override for glanceAppWidget, set it to your QuoteWidget. You can do this in QuoteWidgetReceiver.kt

    Click to see example code

    Click to see example code - imports

  2. Update the AndroidManifest.xml to include a receiver that:

    • Sets android:name to your .widget.QuoteWidgetReceiver
    • Has android:exported="true"
    • Has an intent filter of android:name="android.appwidget.action.APPWIDGET_UPDATE"
    • Has a meta-data object for android.appwidget.provider with the resource of @xml/quote_widget_info (a basic quote_widget_info.xml has been provided)
      Click to see example code

  3. Run your app on your emulator

  4. Long press on your home screen to add your new widget!


Activity 3 - Basic configuration

  1. Modify QuoteWidget to change the text or text colour, run your app again to see the change on the widget. See while the app is deploying that the app icon is displayed on the widget.
  2. Modify QuoteWidget to add a clickable modifier with actionStartActivity(intent) to open the MainActivity on click of the widget. Run the app and try it out.
  3. Modify the quote_widget_info.xml to add an initialLayout with the default loading layout @layout/glance_default_loading_layout. Run the app and see the loading layout is now a spinner.
    Click to see example code

  4. Modify the quote_widget_info.xml to add an android:targetCellWidth="4" and android:targetCellHeight="1". Also add android:resizeMode="horizontal|vertical" to allow your widget to resize. Run the app and see the default size is now a horizontal rectangle. Try resizing it.
    Click to see example code


Activity 4 - Set theme & update UI

  1. Update QuoteWidget to include a background modifier to the Box in QuoteWidgetContent so it is easier to see the against the wallpaper
    Click to see example code

    Run the app and see the colour change

Note: you may need to remove and re-add the widget.

  1. Uncomment the code provided in MotivateMeGlanceColorScheme.kt
    Click to see example code

    Click to see example code - imports

  2. Add a GlanceTheme implementation in MotivateMeGlanceTheme.kt that uses the colours from MotivateMeGlanceColorScheme

Don’t forget the preview!

  1. Replace GlanceTheme with MotivateMeGlanceTheme in QuoteWidget. Update the background and the text to use the themed colours: Background = GlanceTheme.colors.widgetBackground Text = GlanceTheme.colors.primary
    Click to see example code

    Click to see example code - imports

    Run the app and see the colour change

Note: you may need to remove and re-add the widget

  1. Change the emulator settings from dark to light theme and see the widget colours respond

Activity 5 - Set sample data

  1. Modify QuoteWidget to set the displayText variable from the static sampleData as:

val displayText = sampleData.first().quotes.first().text
Click to see example code

2. Run the app, see how the text reflows as the widget changes size & shape. 3. What happens when the text is too long for the space?

Activity 6 - Add widget configuration & data state

  1. Update QuoteWidget to add the stringPreferencesKey values for the topic and quote states
    Click to see example code

    Click to see example code - imports

  2. Update QuoteWidgetConfigurationActivity to set the widget topic & quote as text state values
    Click to see example code

    Click to see example code - imports

  3. Modify quote_widget_info.xml to add android:widgetFeatures="reconfigurable" and android:configure="dev.motivateme.widget.QuoteWidgetConfigurationActivity" to allow the widget to be configured
    Click to see example code

  4. Update QuoteWidget to read the state and use that value in the widget
    Click to see example code

    Click to see example code - imports

  5. Modify QuoteWidget to add a button to the widget UI that will randomly select a quote to show.

Activity 7 - Add Gemini

  1. Open AI Studio and get an API key
  2. Add Gemini SDK
    Click to see example code

  3. Use Gemini to create a new topic & be able to generate quotes in the main app
    Click to see example code

  4. Save the topic to default shared preferences (the quotes don’t need to be saved - we can generate them fresh each time)
    Click to see example code

  5. Have a go changing the prompts, can you make the motivational quotes more punny?

Activity 8 - Add on demand data refresh using CoroutineWorker

  1. Update widget configuration to use one of the new topic name, generate a quote and save it in widget state
    Click to see example code

  2. Modify QuoteWidget refresh button to call Gemini SDK, read the saved topic name & get a new quote on the IO thread
    Click to see example code


Activity 9 - Add periodic data refresh using CoroutineWorker

  1. Create QuoteWidgetWorker to periodically fetch new values from Gemini SDK every 15 min
    Click to see example code

  2. Update to QuoteWidgetReceiver to set up the periodic data updating with QuoteWidgetWorker
    Click to see example code

  3. Wait for 15 minutes to see if your widget updates! Or, change your device time to trigger the update.

Extensions

Activity 10 (Extension) - Polishing the final result

  1. Modify the quote_widget_info.xml to add an android:description="@string/widget_description"
    Click to see example code

  2. Take a screenshot of your widget, trim the size & remove background using any image editor and import it into the app as a drawable with the name quote_widget_preview.png

Tip: I set a white background on my emulator, then take a screenshot and use photopea.com to crop the image and remove the background

  1. Modify the quote_widget_info.xml to add an android:previewImage="@drawable/quote_widget_preview".
    Click to see example code

  2. Modify QuoteWidget to add an error layout if the composition fails
    Click to see example code

  3. Run the app and see the widget selection looks much more inviting

Activity 11 (Extension) - Update the GlanceTheme to use the device theme

  1. Update the MotivateMeGlanceTheme to use the device theme

Activity 12 (Extension) - Respond to the wallpaper

  1. Update MotivateMeGlanceTheme to monitor the wallpaper using WallpaperManager.OnColorsChangedListener & pass a Boolean to the content composable if it should use dark text
  2. Update QuoteWidget to enable a transparent background & respond to the wallpaper

Tip: To monitor the wallpaper colours, you will need to increase the minimum sdk to 27


Activity 13 (Extension) - Fine tune Gemini

  1. Update the Gemini SDK prompt to get it to remove any quote characters from the output
  2. Can you get a better motivational quote? What other things would you like to display on your home screen?