編寫:heray1990 - 原文: http://developer.android.com/training/wearables/watch-faces/information.html
為了顯示時(shí)間,Android Wear 設(shè)備以 cards、notifications 和其它可穿戴應(yīng)用的形式向用戶提供相關(guān)的信息。創(chuàng)建自定義表盤不僅可以以豐富的方式顯示時(shí)間,還可以在用戶掃視設(shè)備的時(shí)候顯示相關(guān)的信息。
像其它可穿戴應(yīng)用一樣,我們的表盤可以通過可穿戴數(shù)據(jù)層 API 與可穿戴設(shè)備上的應(yīng)用通信。某些情況下,我們需要在工程中的手持式應(yīng)用模塊里創(chuàng)建一個(gè) activity,該 activity 從互聯(lián)網(wǎng)或者用戶的配置文件中檢索數(shù)據(jù),然后將數(shù)據(jù)分享給表盤。
http://wiki.jikexueyuan.com/project/android-training-geek/images/Render_Episode.png" alt="" />
Figure 1. 表盤集成數(shù)據(jù)的例子
在設(shè)計(jì)和實(shí)現(xiàn)上下文感知的表盤前,先回答下面幾個(gè)問題:
Android Wear 設(shè)備通常與一個(gè)帶有 GPS 或者蜂窩數(shù)據(jù)連接的配套設(shè)備配對(duì),所以我們有無限的可能來整合不同數(shù)據(jù)到表盤中,例如位置、日歷事件、社交媒體、圖片、股票市場(chǎng)報(bào)價(jià)、新聞事件體育得分等等。然而,并不是所有類型的數(shù)據(jù)都適合表盤,所以我們需要考慮哪種類型的數(shù)據(jù)與用戶最相關(guān)。當(dāng)可穿戴沒有配對(duì)的設(shè)備或者互聯(lián)網(wǎng)連接斷開時(shí),表盤應(yīng)該優(yōu)雅地處理這些情況。
Android Wear 設(shè)備上活動(dòng)的表盤是一個(gè)一直在運(yùn)行的應(yīng)用,所以我們必須使用高效節(jié)能的方法來獲取數(shù)據(jù)。例如,我們每隔10分鐘而不是每隔1分鐘去獲取當(dāng)前的天氣然后將結(jié)果保存到本地。當(dāng)設(shè)備從環(huán)境模式切換到交互模式時(shí),我們可以刷新上下文數(shù)據(jù)。這是因?yàn)樵谇袚Q到交互模式時(shí),用戶很可能想瞥一眼手表。
由于屏幕的空間有限,并且用戶看手表也只是一次看一兩秒,所以我們應(yīng)該在表盤上面將上下文信息歸納起來。有時(shí)表達(dá)上下文信息最好的方法是用圖形和顏色來反應(yīng)。例如,表盤可以根據(jù)當(dāng)前的天氣改變自身的背景圖片。
Android SDK 中的 WatchFace 示例展示了如何在 CalendarWatchFaceService 類里從用戶的配置文件中獲得日程數(shù)據(jù),然后顯示接下來的24小時(shí)有多少個(gè)會(huì)議。這個(gè)示例位于 android-sdk/samples/android-21/wearable/WatchFace 目錄下。
http://wiki.jikexueyuan.com/project/android-training-geek/images/preview_calendar.png" alt="" />
Figure 2. 日程表盤
按照下面的步驟實(shí)現(xiàn)包含上下文數(shù)據(jù)的表盤:
下面的內(nèi)容詳細(xì)介紹了上述幾個(gè)步驟。
在 CanvasWatchFaceService.Engine 實(shí)現(xiàn)里創(chuàng)建一個(gè)繼承 AsyncTask () 的類。然后添加用于接收我們感興趣的數(shù)據(jù)的代碼。
下面是 CalendarWatchFaceService 類獲取第二天會(huì)議數(shù)量的代碼:
/* 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 類可以直接存取配套設(shè)備用戶的日歷事件。
當(dāng)任務(wù)檢索完數(shù)據(jù)時(shí),我們的代碼會(huì)調(diào)用一個(gè)回調(diào)方法。下面的內(nèi)容詳細(xì)介紹了如何實(shí)現(xiàn)這個(gè)回調(diào)方法。
更多關(guān)于從日歷獲取數(shù)據(jù)的內(nèi)容,請(qǐng)參考 Calendar Provider API 指南。
我們可以實(shí)現(xiàn)一個(gè)周期計(jì)數(shù)的自定義定時(shí)器來更新數(shù)據(jù)。CalendarWatchFaceService 類使用一個(gè) Handler 實(shí)例通過線程的消息隊(duì)列來發(fā)送和處理延時(shí)的消息:
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;
}
}
};
...
}
當(dāng)可以看到表盤時(shí),這個(gè)方法初始化了定時(shí)器:
@Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
if (visible) {
mLoadMeetingsHandler.sendEmptyMessage(MSG_LOAD_MEETINGS);
} else {
mLoadMeetingsHandler.removeMessages(MSG_LOAD_MEETINGS);
cancelLoadMeetingTask();
}
}
下面的內(nèi)容介紹在 onMeetingsLoaded() 方法設(shè)置下一個(gè)定時(shí)器。
當(dāng)任務(wù)檢索完數(shù)據(jù)時(shí),調(diào)用 invalidate() 方法使得系統(tǒng)可以重新繪制表盤。將數(shù)據(jù)保存到 Engine 類的成員變量,這樣我們就可以在 onDraw() 方法中訪問數(shù)據(jù)。
CalendarWatchFaceService 類提供一個(gè)回調(diào)方法給任務(wù)在檢索完日程數(shù)據(jù)后調(diào)用:
private void onMeetingsLoaded(Integer result) {
if (result != null) {
mNumMeetings = result;
invalidate();
}
if (isVisible()) {
mLoadMeetingsHandler.sendEmptyMessageDelayed(
MSG_LOAD_MEETINGS, LOAD_MEETINGS_DELAY_MS);
}
}
回調(diào)方法將結(jié)果保存在一個(gè)成員變量中,銷毀 view,和調(diào)度下一個(gè)定時(shí)器再次運(yùn)行任務(wù)。