如何将数据发送到 Android Wear TileService

How to send data to Android Wear TileService

我真的不知道如何为我的 Wear OS 磁贴提供数据。目前,我正在尝试从 BroadcastReceiver 接收我的心率,它可以工作,但在 onTileRequest 中我的值始终为 0。

这是我的 TileService...

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

    private String currentHeartrate = "0";

    @Override          //onStartCommand never gets called
    public int onStartCommand(Intent intent, int flags, int startId) {
        int i = super.onStartCommand(intent, flags, startId);
        Log.d("HeartRate", "onStartCommand " + currentHeartrate);
        LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, new IntentFilter("heart-rate-to-activity"));
        return i;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        LocalBroadcastManager.getInstance(this).registerReceiver(messageReceiver, new IntentFilter("heart-rate-to-activity"));
    }

    @NonNull
    @Override
    protected ListenableFuture<TileBuilders.Tile> onTileRequest(
            @NonNull RequestBuilders.TileRequest requestParams
    ) {
        Log.d("HeartRate", "onTileRequest " + currentHeartrate);
        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(
                                                layout()
                                        ).build()
                                ).build()
                        ).build()
                ).build()
        );
    }

    private LayoutElementBuilders.LayoutElement layout() {
        return new LayoutElementBuilders.Row.Builder()
                .setWidth(wrap())
                .setHeight(expand())
                .setVerticalAlignment(LayoutElementBuilders.VERTICAL_ALIGN_CENTER)
                .addContent(new LayoutElementBuilders.Text.Builder()
                        .setText(currentHeartrate)
                        .build()
                ).build();
    }

    @NonNull
    @Override
    protected ListenableFuture<ResourceBuilders.Resources> onResourcesRequest(
            @NonNull RequestBuilders.ResourcesRequest requestParams
    ) {
        Log.d("HeartRate", "onResourcesRequest " + currentHeartrate);
        return Futures.immediateFuture(new ResourceBuilders.Resources.Builder()
                .setVersion(RESOURCES_VERSION)
                .build()
        );
    }

    private final BroadcastReceiver messageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("HeartRate", "message: " + currentHeartrate);
            currentHeartrate = intent.getExtras().getString("message");
        }
    };

}

这就是我得到的... 如您所见,onTileRequest 始终为 0。可能是因为每当调用 onTileRequest 时也会调用 onCreate,因此此时我的数据为 0。但是我怎样才能永久保存心率呢?难道我做错了什么?还是 tile 只是不打算接收 BroadcastReceiver 的数据。还有其他方法吗?我几乎没有发现任何有关使用 Internet 上的数据更新图块的信息。

I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 2
D/HeartRate: onCreate 0
W/t.myapplicatio: Accessing hidden field Ljava/nio/Buffer;->address:J (light greylist, reflection)
D/HeartRate: onTileRequest 0
D/HeartRate: onResourcesRequest 0
D/ViewRootImpl[MainActivity]: changeCanvasOpacity: opaque=false
D/HeartRate: onCreate 0
D/HeartRate: message: 0
D/HeartRate: message: 0
D/HeartRate: message: 81
D/HeartRate: message: 81
D/HeartRate: onCreate 0
D/HeartRate: message: 81
    message: 81
    message: 0
D/HeartRate: message: 81
I/chatty: uid=10096(com.pezcraft.myapplication) identical 1 line
D/HeartRate: message: 82
D/HeartRate: message: 72
I/chatty: uid=10096(com.pezcraft.myapplication) identical 1 line
D/HeartRate: message: 72
D/HeartRate: message: 73
I/chatty: uid=10096(com.pezcraft.myapplication) identical 1 line
D/HeartRate: message: 73
D/HeartRate: onCreate 0
D/HeartRate: onTileRequest 0
D/HeartRate: message: 75
I/chatty: uid=10096(com.pezcraft.myapplication) identical 1 line
D/HeartRate: message: 75
    message: 0
D/HeartRate: message: 75
I/chatty: uid=10096(com.pezcraft.myapplication) identical 2 lines
D/HeartRate: message: 75

TileService 的生命周期与您的应用程序不同。您的 tile 服务可能会被销毁并为其他请求创建一个新服务。为生成磁贴而创建的服务可能不太可能在收到心跳传感器数据时处于唤醒状态。

Android 小部件 https://twitter.com/marxallski/status/1454889465206513667 上的此线程也适用于 Wear Tiles 和 Complications。

Ideally data is cached in memory, if not, use a worker to refresh it and whenever data is cached it should notify the widget to update.

You should not keep data inside the GlanceAppWidget, it should be kept at the application scope

这里也是一样。

您的磁贴应该执行得非常快,有效地无状态

  • 未启动可能较长或失败的网络请求,或订阅后台数据
  • 返回内存中缓存的数据(应用程序范围)或从数据库(房间?)读取数据

尝试订阅磁贴外的数据。存储与应用程序相关的数据(您的应用程序子类中的一个字段),使用像 Koin/Hilt 这样的 DI,或者存储在您可以在收到 onTileRequest 请求时读取的数据库中。

我对健康数据或广播不太熟悉 - 但这似乎相关 https://developer.android.com/training/wearables/health-services/passive