
We plan on removing the fake R classes from the javac output in a future cl. This means every java target has to specify a resources_package if it uses resources (so that a dummy R class is put on its classpath). Every java target also needs to depend on resource targets it uses rather than relying on transitive deps from other java dependencies. Bug: 1230136 Change-Id: Iee6ccea58d4d8f735f7c2c1337fb6985d57d72dc Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4385474 Auto-Submit: Mohamed Heikal <mheikal@chromium.org> Commit-Queue: Andrew Grieve <agrieve@chromium.org> Owners-Override: Andrew Grieve <agrieve@chromium.org> Reviewed-by: Andrew Grieve <agrieve@chromium.org> Cr-Commit-Position: refs/heads/main@{#1126217}
Messages UI
Message UI is an alternative to InfoBar UI on Android. It provides a set of APIs and a consistent, ephemeral and trustworthy UI with various lifecycles and priorities.
[TOC]
Overview
Each message should include at least 3 properties: title, primary icon and primary button text.
Each message will automatically be displayed, hidden and dismissed according to given scope (see details below) and can be dismissed automatically or manually. By default, each message will be automatically dismissed after around 10s after it is displayed. The timer will be reset if the text or icon on the UI is changed or if the Message is re-shown. Also, users can dismiss the message by swiping the UI upwards, leftwards and rightwards. The feature clients can also manually dismiss the message through provided APIs if necessary.
Developing a new Message UI Feature
You need to do the following things to enable your message UI, all described in detail below.
- Declare your message UI by adding a Message Identifier.
- Build a message model.
- Enqueue your message model.
Declare your message UI
You need to create a MessageIdentifier
that represents your Message UI, which
distinguishes it from other message UIs and enables some feature-specific metrics
to be recorded.
The MessageIdentifier is defined as an enum
and a string, which should be
appended in following files (you can refer to
this CL as an example):
components/messages/android/message_enums.h
[1]- MessageIdentifier in
tools/metrics/histograms/enums.xml
[1] - MessageIdentifier in
tools/metrics/histograms/metadata/android/histograms.xml
[1] - MessageIdentifier string in
components/messages/android/java/src/org/chromium/components/messages/MessagesMetrics.java
[1]
Build a message model
All available model properties are defined in components/messages/android/…/MessageBannerProperties.java
Only some of them are required:
- TITLE: the main text of the message UI
- ICON / ICON_RESOURCE_ID: the primary icon of the message UI, located at the start side of the UI.
- PRIMARY_BUTTON_TEXT: the label of the primary button, located at the end of the message UI.
The rest are optional, but some of those are very commonly used:
- DESCRIPTION: the description / subtitle of the message UI, usually used to help explain the purpose of the message UI.
- ON_PRIMARY_ACTION: the callback function triggered when the user clicks on the primary button. Only called once. After this function is triggered, the message itself will be dismissed.
- ON_SECONDARY_ACTION / SECONDARY_BUTTON_MENU_TEXT / SECONDARY_ICON_CONTENT_DESCRIPTION
/ SECONDARY_ICON / SECONDARY_ICON_RESOURCE_ID: these are used to set a
secondary action / menu. If SECONDARY_BUTTON_MENU_TEXT is configured, clicking
on the secondary button will trigger a single-menu-item popup menu.
Clicking on the secondary icon does not guarantee that the message will be
automatically dismissed. We recommend the feature code to manually dismiss
the message when secondary action callback is triggered.
- Note: there are changes in-flight to allow multiple menu items. Documentation will be updated once that lands.
- ON_DISMISSED: the callback function triggered when the message UI is dismissed. Dismiss means the message has been removed from the queue and will not be displayed again.
You can refer to this CL as an example on the Java side and this CL as an example on the Native side.
Some other, less commonly used properties are:
- ICON_TINT_COLOR: the default icon color is blue. Use this to update the icon color and set TINT_NONE to disable the icon tint color.
- DESCRIPTION_MAX_LINES: set max lines of the description. The default when this property isn't set is to show all the description texts, which may occupy too much screen space.
Enqueue your message model
After the model is defined and ready to be displayed, it should be enqueued by calling MessageDispatcher#enqueueMessage and providing the model, scope, and priority.
MessageDispatcher
MessageDispatcher is per-window object. In Java, use MessageDispatcherProvider#from to get a dispatcher available in the current window, which can be null if native initialization is not finished yet. In C++, use messages::MessageDispatcherBridge::Get() instead.
Scope
Message scope can also be seen as the life cycle of a message UI. It pre-defines when and where messages should be displayed and dismissed. There are 3 scopes in total (components/messages/android/message_enums.h):
- Navigation: messages of navigation will be displayed only on the web page for which they are enqueued. It will be hidden (not dismissed) when the user switches to another tab and displayed again when the user returns to the target tab. It will be dismissed when user navigates to another page, such as navigating to https://chromium.org from https://google.com or navigating to https://google.com/about from https://google.com/settings, and also dismissed when the tab where the page lives is closed. This should be used when the content and purpose of the Message is tightly related to a certain page. For example, password messages should be only displayed on the page where the user submits the password and dismissed if the user navigates to another page.
- Window: messages of window scope will be displayed as long as the current window is alive (current window is dead usually when app is closed or user merges windows). It can be displayed on any tab and web page. So this scope should be used only when the content and purpose of the message is unrelated to the web page. For example, Sync Error message is related to the app rather than the page and works as an app-level notification. Use #EnqueueWindowScopedMessage to enqueue a window-scoped message.
- Web_Contents: this one is rarely used and usually not recommended unless really necessary. The only difference between web_contents scope and navigation scope is that messages of web_contents scope do not dismiss when the user navigates to another page; i.e. it is only dismissed when its associated tab is closed.
Priority
There are two types of priority: urgent (a.k.a high) and normal (a.k.a low).
Urgent messages will be displayed ASAP, in spite of enqueued messages of normal properties. Urgent should only be used when the message is so important that you want users to take an action ASAP, such as a serious security risk found on the page the user is visiting. Otherwise, use normal in most cases.
Dismiss your message
As explained in Overview, by default, the message will be dismissed in the following cases:
- Timeout
- Swiping gesture
- Primary action button is clicked
- The given scope is destroyed
In addition, messages can be dismissed by feature client code so that the message won’t be displayed any more. Use MessageDispatcher#dismissMessage to dismiss the message. The dismiss callback will still be triggered.
Ownership in native
In native, MessageDispatcherBridge#EnqueueMessage will return a MessageWrapper object. The feature client is responsible for managing it. We recommend dismissing the message manually if the MessageWrapper object is still alive when the owner of the MessageWrapper object is destroyed.
Test
On the Java side, components/messages/android/test/…/messages/MessagesTestHelper.java is available to get all current enqueued messages and get the property model of a certain message.
In native, components/messages/android/mock_message_dispatcher_bridge.h is available to test whether a message is enqueued and trigger some callbacks manually. You can refer to this CL as an example.
Built-in Metrics
Some metrics have been pre-defined to help evaluate the effectiveness of a message.
Android.Messages.Enqueued
Records the message identifier each time a message is enqueued through MessageDispatcher. This histogram can be used for getting a count of messages broken down by message identifier.
Android.Messages.Dismissed.{MessageIdentifier}
Records the reason why this message is dismissed, such as primary action, timer, gesture and so on.
Android.Messages.TimeToAction.Dismiss.{MessageIdentifier}
Records the time interval the message was displayed on the screen before the user dismissed it with a gesture. The metric is NOT recorded when the user presses primary or secondary button or when the message is auto-dismissed based on timer.
Android.Messages.TimeToAction.{MessageIdentifier}
Records the time interval the message was displayed on the screen before the user explicitly dismissed it. The metric is recorded when the user presses the primary or secondary button, or dismisses the message with a gesture.