Android 在表盤(pán)上顯示信息

2018-08-02 17:55 更新

編寫(xiě):heray1990 - 原文: http://developer.android.com/training/wearables/watch-faces/information.html

為了顯示時(shí)間,Android Wear 設(shè)備以 cards、notifications 和其它可穿戴應(yīng)用的形式向用戶提供相關(guān)的信息。創(chuàng)建自定義表盤(pán)不僅可以以豐富的方式顯示時(shí)間,還可以在用戶掃視設(shè)備的時(shí)候顯示相關(guān)的信息。

像其它可穿戴應(yīng)用一樣,我們的表盤(pán)可以通過(guò)可穿戴數(shù)據(jù)層 API 與可穿戴設(shè)備上的應(yīng)用通信。某些情況下,我們需要在工程中的手持式應(yīng)用模塊里創(chuàng)建一個(gè) activity,該 activity 從互聯(lián)網(wǎng)或者用戶的配置文件中檢索數(shù)據(jù),然后將數(shù)據(jù)分享給表盤(pán)。

Figure 1. 表盤(pán)集成數(shù)據(jù)的例子

創(chuàng)建豐富的體驗(yàn)

在設(shè)計(jì)和實(shí)現(xiàn)上下文感知的表盤(pán)前,先回答下面幾個(gè)問(wèn)題:

  • 我們想要包含什么類(lèi)型的數(shù)據(jù)?
  • 我們可以從哪里獲得數(shù)據(jù)?
  • 數(shù)據(jù)多久會(huì)顯著變化?
  • 如何表達(dá)數(shù)據(jù),使得用戶瞥一眼就明白其中的意思?

Android Wear 設(shè)備通常與一個(gè)帶有 GPS 或者蜂窩數(shù)據(jù)連接的配套設(shè)備配對(duì),所以我們有無(wú)限的可能來(lái)整合不同數(shù)據(jù)到表盤(pán)中,例如位置、日歷事件、社交媒體、圖片、股票市場(chǎng)報(bào)價(jià)、新聞事件體育得分等等。然而,并不是所有類(lèi)型的數(shù)據(jù)都適合表盤(pán),所以我們需要考慮哪種類(lèi)型的數(shù)據(jù)與用戶最相關(guān)。當(dāng)可穿戴沒(méi)有配對(duì)的設(shè)備或者互聯(lián)網(wǎng)連接斷開(kāi)時(shí),表盤(pán)應(yīng)該優(yōu)雅地處理這些情況。

Android Wear 設(shè)備上活動(dòng)的表盤(pán)是一個(gè)一直在運(yùn)行的應(yīng)用,所以我們必須使用高效節(jié)能的方法來(lái)獲取數(shù)據(jù)。例如,我們每隔10分鐘而不是每隔1分鐘去獲取當(dāng)前的天氣然后將結(jié)果保存到本地。當(dāng)設(shè)備從環(huán)境模式切換到交互模式時(shí),我們可以刷新上下文數(shù)據(jù)。這是因?yàn)樵谇袚Q到交互模式時(shí),用戶很可能想瞥一眼手表。

由于屏幕的空間有限,并且用戶看手表也只是一次看一兩秒,所以我們應(yīng)該在表盤(pán)上面將上下文信息歸納起來(lái)。有時(shí)表達(dá)上下文信息最好的方法是用圖形和顏色來(lái)反應(yīng)。例如,表盤(pán)可以根據(jù)當(dāng)前的天氣改變自身的背景圖片。

添加數(shù)據(jù)到表盤(pán)

Android SDK 中的 WatchFace 示例展示了如何在 CalendarWatchFaceService 類(lèi)里從用戶的配置文件中獲得日程數(shù)據(jù),然后顯示接下來(lái)的24小時(shí)有多少個(gè)會(huì)議。這個(gè)示例位于 android-sdk/samples/android-21/wearable/WatchFace 目錄下。

Figure 2. 日程表盤(pán)

按照下面的步驟實(shí)現(xiàn)包含上下文數(shù)據(jù)的表盤(pán):

  1. 提供一個(gè)任務(wù)來(lái)檢索數(shù)據(jù)。
  2. 創(chuàng)建一個(gè)自定義定時(shí)器來(lái)周期性地調(diào)用任務(wù),或者當(dāng)外部數(shù)據(jù)變化時(shí)通知表盤(pán)服務(wù)。
  3. 用更新的數(shù)據(jù)重新繪制表盤(pán)。

下面的內(nèi)容詳細(xì)介紹了上述幾個(gè)步驟。

提供一個(gè)任務(wù)來(lái)檢索數(shù)據(jù)

在 CanvasWatchFaceService.Engine 實(shí)現(xiàn)里創(chuàng)建一個(gè)繼承 AsyncTask 的類(lèi)。然后添加用于接收我們感興趣的數(shù)據(jù)的代碼。

下面是 CalendarWatchFaceService 類(lèi)獲取第二天會(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 庫(kù)的 WearableCalendarContract 類(lèi)可以直接存取配套設(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 指南。

創(chuàng)建自定義定時(shí)器

我們可以實(shí)現(xiàn)一個(gè)周期計(jì)數(shù)的自定義定時(shí)器來(lái)更新數(shù)據(jù)。CalendarWatchFaceService 類(lèi)使用一個(gè) Handler 實(shí)例通過(guò)線程的消息隊(duì)列來(lái)發(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)可以看到表盤(pán)時(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í)器。

用更新的數(shù)據(jù)重新繪制表盤(pán)

當(dāng)任務(wù)檢索完數(shù)據(jù)時(shí),調(diào)用 invalidate() 方法使得系統(tǒng)可以重新繪制表盤(pán)。將數(shù)據(jù)保存到 Engine 類(lèi)的成員變量,這樣我們就可以在 onDraw() 方法中訪問(wèn)數(shù)據(jù)。

CalendarWatchFaceService 類(lèi)提供一個(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è)成員變量中,銷(xiāo)毀 view,和調(diào)度下一個(gè)定時(shí)器再次運(yùn)行任務(wù)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)