編寫: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
目錄下。
Figure 2. 日程表盤
按照下面的步驟實現包含上下文數據的錶盤:
下面的內容詳細介紹了上述幾個步驟。
在 CanvasWatchFaceService.Engine
實現裡創建一個繼承 AsyncTask 的類。然後添加用於接收我們感興趣的數據的代碼。
下面是 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
類可以直接存取配套設備用戶的日曆事件。
當任務檢索完數據時,我們的代碼會調用一個回調方法。下面的內容詳細介紹瞭如何實現這個回調方法。
更多關於從日曆獲取數據的內容,請參考 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()
方法設置下一個定時器。
當任務檢索完數據時,調用 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,和調度下一個定時器再次運行任務。