如何向 Android Wear TileService 发送数据

Posted

技术标签:

【中文标题】如何向 Android Wear TileService 发送数据【英文标题】:How to send data to Android Wear TileService 【发布时间】:2021-12-19 21:07:37 【问题描述】:

我真的不知道如何为我的 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。但是我怎样才能永久保存心率呢?难道我做错了什么?或者瓷砖只是不打算接收广播接收器的数据。还有其他方法吗?我真的没有发现任何关于使用互联网上的数据更新磁贴的信息。

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

【问题讨论】:

【参考方案1】:

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

android Widgets https://twitter.com/marxallski/status/1454889465206513667 上的此线程也适用于 Wear Tiles 和 Complications。

理想情况下,数据缓存在内存中,如果没有,请使用 worker 刷新它,每当缓存数据时,它应该通知小部件更新。

您不应该将数据保存在 GlanceAppWidget 中,它应该保存在应用程序范围内

这里也一样。

您的 tile 应该非常快速、有效地无状态地执行

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

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

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

【讨论】:

以上是关于如何向 Android Wear TileService 发送数据的主要内容,如果未能解决你的问题,请参考以下文章

与 Android Wear 的 React-Native 通信

如何在睡眠模式下唤醒 Android Wear?

如何以编程方式打开 Android Wear 键盘?

[在Android Studio中,构建一个Android Wear项目,如何在两个模块中包含相同的文件

从真实设备卸载 Android Wear 应用程序

Android Wear 模拟器有传感器吗?