编写:heray1990 - 原文: http://developer.android.com/training/wearables/watch-faces/information.html
为了显示时间,Android Wear 设备以 cards、notifications 和其它可穿戴应用的形式向用户提供相关的信息。创建自定义表盘不仅可以以丰富的方式显示时间,还可以在用户扫视设备的时候显示相关的信息。
像其它可穿戴应用一样,我们的表盘可以通过可穿戴数据层 API 与可穿戴设备上的应用通信。某些情况下,我们需要在工程中的手持式应用模块里创建一个 activity,该 activity 从互联网或者用户的配置文件中检索数据,然后将数据分享给表盘。
Figure 1. 表盘集成数据的例子
在设计和实现上下文感知的表盘前,先回答下面几个问题:
Android Wear 设备通常与一个带有 GPS 或者蜂窝数据连接的配套设备配对,所以我们有无限的可能来整合不同数据到表盘中,例如位置、日历事件、社交媒体、图片、股票市场报价、新闻事件体育得分等等。然而,并不是所有类型的数据都适合表盘,所以我们需要考虑哪种类型的数据与用户最相关。当可穿戴没有配对的设备或者互联网连接断开时,表盘应该优雅地处理这些情况。
Android Wear 设备上活动的表盘是一个一直在运行的应用,所以我们必须使用高效节能的方法来获取数据。例如,我们每隔10分钟而不是每隔1分钟去获取当前的天气然后将结果保存到本地。当设备从环境模式切换到交互模式时,我们可以刷新上下文数据。这是因为在切换到交互模式时,用户很可能想瞥一眼手表。
由于屏幕的空间有限,并且用户看手表也只是一次看一两秒,所以我们应该在表盘上面将上下文信息归纳起来。有时表达上下文信息最好的方法是用图形和颜色来反应。例如,表盘可以根据当前的天气改变自身的背景图片。
Android SDK 中的 WatchFace 示例展示了如何在 CalendarWatchFaceService 类里从用户的配置文件中获得日程数据,然后显示接下来的24小时有多少个会议。这个示例位于 android-sdk/samples/android-21/wearable/WatchFace 目录下。
CalendarWatchFaceService
android-sdk/samples/android-21/wearable/WatchFace
Figure 2. 日程表盘
按照下面的步骤实现包含上下文数据的表盘:
下面的内容详细介绍了上述几个步骤。
在 CanvasWatchFaceService.Engine 实现里创建一个继承 [AsyncTask]() 的类。然后添加用于接收我们感兴趣的数据的代码。
CanvasWatchFaceService.Engine
下面是 CalendarWatchFaceService 类获取第二天会议数量的代码:
/* Asynchronous task to load the meetings from the content provider and * report the number of meetings back using onMeetingsLoaded() */ private class LoadMeetingsTask extends AsyncTask<Void, Void, Integer> { @Override protected Integer doInBackground(Void... voids) { long begin = System.currentTimeMillis(); Uri.Builder builder = WearableCalendarContract.Instances.CONTENT_URI.buildUpon(); ContentUris.appendId(builder, begin); ContentUris.appendId(builder, begin + DateUtils.DAY_IN_MILLIS); final Cursor cursor = getContentResolver() .query(builder.build(), null, null, null, null); int numMeetings = cursor.getCount(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Num meetings: " + numMeetings); } return numMeetings; } @Override protected void onPostExecute(Integer result) { /* get the number of meetings and set the next timer tick */ onMeetingsLoaded(result); } }
Wearable Support 库的 WearableCalendarContract 类可以直接存取配套设备用户的日历事件。
WearableCalendarContract
当任务检索完数据时,我们的代码会调用一个回调方法。下面的内容详细介绍了如何实现这个回调方法。
更多关于从日历获取数据的内容,请参考 Calendar Provider API 指南。
我们可以实现一个周期计数的自定义定时器来更新数据。CalendarWatchFaceService 类使用一个 Handler 实例通过线程的消息队列来发送和处理延时的消息:
private class Engine extends CanvasWatchFaceService.Engine { ... int mNumMeetings; private AsyncTask<Void, Void, Integer> mLoadMeetingsTask; /* Handler to load the meetings once a minute in interactive mode. */ final Handler mLoadMeetingsHandler = new Handler() { @Override public void handleMessage(Message message) { switch (message.what) { case MSG_LOAD_MEETINGS: cancelLoadMeetingTask(); mLoadMeetingsTask = new LoadMeetingsTask(); mLoadMeetingsTask.execute(); break; } } }; ... }
当可以看到表盘时,这个方法初始化了定时器:
@Override public void onVisibilityChanged(boolean visible) { super.onVisibilityChanged(visible); if (visible) { mLoadMeetingsHandler.sendEmptyMessage(MSG_LOAD_MEETINGS); } else { mLoadMeetingsHandler.removeMessages(MSG_LOAD_MEETINGS); cancelLoadMeetingTask(); } }
下面的内容介绍在 onMeetingsLoaded() 方法设置下一个定时器。
onMeetingsLoaded()
当任务检索完数据时,调用 invalidate() 方法使得系统可以重新绘制表盘。将数据保存到 Engine 类的成员变量,这样我们就可以在 onDraw() 方法中访问数据。
invalidate()
Engine
onDraw()
CalendarWatchFaceService 类提供一个回调方法给任务在检索完日程数据后调用:
private void onMeetingsLoaded(Integer result) { if (result != null) { mNumMeetings = result; invalidate(); } if (isVisible()) { mLoadMeetingsHandler.sendEmptyMessageDelayed( MSG_LOAD_MEETINGS, LOAD_MEETINGS_DELAY_MS); } }
回调方法将结果保存在一个成员变量中,销毁 view,和调度下一个定时器再次运行任务。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8