feat(wear): let every tile be added more than once - #85
Merged
Merged
Conversation
Wear will only offer a second copy of a tile whose provider declares two private clockwork metadata keys: MULTI_INSTANCES_SUPPORTED, and PROVIDER_CONFIG_ACTION naming an action handled by an activity registered under the tiles PROVIDER_CONFIG category. The flag alone does nothing, which is why our tiles sat at one apiece however much per-instance state they kept. Nothing in androidx.wear.tiles hints at this; it was found by reading a shipping app's manifest. The plumbing was mostly here already. Every request has carried a tileId and the member-set tiles have always stored their roster against it, so the work was declaring the keys, adding an action per tile type to the existing member picker, and teaching it the system's launch shape: the tile id arrives as com.google.android.clockwork.EXTRA_PROVIDER_CONFIG_TILE_ID rather than our own extra, and which tile to refresh has to come from the action rather than a class hint the system does not send. Actions are fully qualified rather than the bare strings the reference app uses. An implicit action matches device-wide, and "ConfigQuickSwitchTile" is one collision away from dropping somebody into another app's settings. So that configuring a tile is not a screen that does nothing, the four tiles that had no configuration now honour the same roster the other two always have: orderedFronters takes a tile id and narrows to that copy's members, an empty roster meaning everybody, which is what an unconfigured tile has and therefore what every tile did before. History keeps an entry if anyone on the roster appears in it, so a co-front involving one of them stays in their history. The fronters-list tile joins its own names now instead of reading the pre-joined blob, which is the whole system's list and not necessarily this tile's. The avatar tiles declare their images in a separate request, and that had to follow the same filter: a superset only wastes a decode, but a subset renders blank. Group and tag filters, hiding custom fronts, and sort order are the rest of this and are not here. They need the watch's member model widened first - it carries no is_custom_front, no privacy, no tags and no group membership, and the watch fetches neither groups nor tags. The member roster came free because it already had storage and a picker. These are private keys, so whether the picker honours them varies by OEM and Wear version. Verified in the built manifest; needs a watch to confirm the picker behaviour.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Wear will only offer a second copy of a tile whose provider declares two private clockwork metadata keys:
Both are required - the flag alone does nothing, which is why our tiles sat at one apiece however much per-instance state they kept. Nothing in
androidx.wear.tileshints at this; it came from reading a shipping app's manifest.The plumbing was mostly here already: every request has carried a
tileIdand the member-set tiles have always stored their roster against it. The work was declaring the keys, adding an action per tile type to the existing member picker, and teaching it the system's launch shape - the tile id arrives ascom.google.android.clockwork.EXTRA_PROVIDER_CONFIG_TILE_IDrather than our own extra, and which tile to refresh has to come from the action, since the system sends no class hint.Actions are fully qualified rather than the bare strings the reference app uses. An implicit action matches device-wide, and
ConfigQuickSwitchTileis one collision away from dropping somebody into another app's settings.So that configuring a tile isn't a screen that does nothing
The four tiles that had no configuration now honour the same roster the other two always have.
orderedFronterstakes a tile id and narrows to that copy's members, an empty roster meaning everybody - which is what an unconfigured tile has, and therefore what every tile did before this. History keeps an entry if anyone on the roster appears in it, so a co-front involving one of them stays in their history. The fronters-list tile joins its own names now instead of reading the pre-joined blob, which is the whole system's list and not necessarily this tile's.The avatar tiles declare their images in a separate request, and that had to follow the same filter: a superset only wastes a decode, but a subset renders blank.
Not in this PR
Group and tag filters, hiding custom fronts, and sort order. Those need the watch's member model widened and the bulk membership reads landing in server 1.5.1, and are the next piece of work. The member roster came free here because it already had storage and a picker.
Checked
aapt2: six tiles declaring multi-instance, six config actions, sixPROVIDER_CONFIGintent-filters, and still six tile services, so no extra rows in the picker.