1

I have made a tile that should show the current heart rate. The tile gets the heart rate from shared preferences and it works perfectly but I need to refresh it like every second. Currently, I can only refresh it every minute using .setFreshnessIntervalMillis(1000*60)

The documentation says that I can update my tile from any place in my application using this...

TileService.getUpdater(context)
       .requestUpdate(HeartRateTileService.class);

But this does nothing. I tried it in several locations like in onItemSelected inside my MainActivity, inside a BroadcastReceiver and inside a foreground service. Is this a context problem or something? I also tried

HeartRateTileService.getUpdater(this/getApplicationContext())
       .requestUpdate(HeartRateTileService.class);

This is my tile...

public class HeartRateTileService extends TileService {
    private static final String RESOURCES_VERSION = "1";

    private String currentHeartrate = "0";
    private PrefManager prefManager;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int i = super.onStartCommand(intent, flags, startId);

        Log.d("HeartRate", "onStartCommand " + prefManager.getHeartrate());

        return i;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        prefManager = new PrefManager(this);
        Log.d("HeartRate", "onCreate " + prefManager.getHeartrate());
    }

    @NonNull
    @Override
    protected ListenableFuture<TileBuilders.Tile> onTileRequest(
            @NonNull RequestBuilders.TileRequest requestParams
    ) {
        Log.d("HeartRate", "onTileRequest " + prefManager.getHeartrate());
        return Futures.immediateFuture(new TileBuilders.Tile.Builder()
                .setResourcesVersion(RESOURCES_VERSION)
                .setFreshnessIntervalMillis(1000*60)
                .setTimeline(new TimelineBuilders.Timeline.Builder()
                        .addTimelineEntry(new TimelineBuilders.TimelineEntry.Builder()
                                .setLayout(new LayoutElementBuilders.Layout.Builder()
                                        .setRoot(
                                                layoutHeartRate()
                                        ).build()
                                ).build()
                        ).build()
                ).build()
        );
    }

    private LayoutElementBuilders.LayoutElement layoutPlay() {
        return new LayoutElementBuilders.Box.Builder()
                .setWidth(wrap())
                .setHeight(expand())
                .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
                .addContent(new LayoutElementBuilders.Row.Builder()
                        .addContent(
                                IconButton.buildIconButton(
                                        this,
                                        "ic_play",
                                        R.color.colorAccent,
                                        "start measuring heart rate",
                                        new ModifiersBuilders.Clickable.Builder()
                                                .setOnClick(new ActionBuilders.LaunchAction.Builder()
                                                        .setAndroidActivity(new ActionBuilders.AndroidActivity.Builder()
                                                                .setClassName(MainActivity.class.getName())
                                                                .setPackageName(this.getPackageName())
                                                                .build()
                                                        ).build()
                                                )
                                                .build()
                                )
                        ).build()
                )
                .build();
    }

    private LayoutElementBuilders.LayoutElement layoutHeartRate() {
        prefManager = new PrefManager(this);
        currentHeartrate = prefManager.getHeartrate();
        return new LayoutElementBuilders.Box.Builder()
                .setWidth(wrap())
                .setHeight(expand())
                .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
                .addContent(new LayoutElementBuilders.Row.Builder()
                        .addContent(
                                IconButton.buildIconButton(
                                        this,
                                        "",
                                        R.color.colorAccent,
                                        "start measuring heart rate",
                                        new ModifiersBuilders.Clickable.Builder()
                                                .setOnClick(new ActionBuilders.LaunchAction.Builder()
                                                        .setAndroidActivity(new ActionBuilders.AndroidActivity.Builder()
                                                                .setClassName(MainActivity.class.getName())
                                                                .setPackageName(this.getPackageName())
                                                                .build()
                                                        ).build()
                                                )
                                                .build()
                                )
                        ).build()
                )
                .addContent(new LayoutElementBuilders.Text.Builder()
                        .setText(prefManager.getHeartrate())
                        .build()
                )
                .build();
    }

    @NonNull
    @Override
    protected ListenableFuture<ResourceBuilders.Resources> onResourcesRequest(
            @NonNull RequestBuilders.ResourcesRequest requestParams
    ) {
        Log.d("HeartRate", "onResourcesRequest " + prefManager.getHeartrate());
        return Futures.immediateFuture(new ResourceBuilders.Resources.Builder()
                .setVersion(RESOURCES_VERSION)
                .addIdToImageMapping("ic_play", new ResourceBuilders.ImageResource.Builder()
                        .setAndroidResourceByResId(new ResourceBuilders.AndroidImageResourceByResId.Builder()
                                .setResourceId(R.drawable.ic_play)
                                .build()
                        ).build()
                )
                .build()
        );
    }

}
Pezcraft
  • 270
  • 3
  • 15

1 Answers1

3

There is a minimum time of 20 seconds.

See https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:wear/tiles/tiles-renderer/src/main/java/androidx/wear/tiles/manager/UpdateScheduler.java;l=31?q=20%20f:androidx%2Fwear%2Ftiles&start=51

    @VisibleForTesting static final long MIN_INTER_UPDATE_INTERVAL_MILLIS = SECONDS.toMillis(20);
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
  • I realized that a manual refresh actually works, but with a 20sec delay, as you said. This in fact is really sad. So third-party apps will never be able to create any timing tile. I will add a refresh button to my tile now so the user can refresh it more often. – Pezcraft Jan 03 '22 at 13:19
  • I ran into the same limitation and it's absolutely bewildering that this limit exists, for tiles of all things. Something that can't possibly be on screen for any long time period is inexplicably restricted from showing up-to-date information, and has to rely on manual input. – Toumal Oct 11 '22 at 16:24