Android 在表盤上顯示信息

2018-08-02 17:55 更新

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

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

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

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

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

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

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

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

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

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

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

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

Figure 2. 日程表盤

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

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

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

提供一個任務(wù)來檢索數(shù)據(jù)

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

下面是 CalendarWatchFaceService 類獲取第二天會議數(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ù)時,我們的代碼會調(diào)用一個回調(diào)方法。下面的內(nèi)容詳細(xì)介紹了如何實(shí)現(xiàn)這個回調(diào)方法。

更多關(guān)于從日歷獲取數(shù)據(jù)的內(nèi)容,請參考 Calendar Provider API 指南。

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

我們可以實(shí)現(xiàn)一個周期計數(shù)的自定義定時器來更新數(shù)據(jù)。CalendarWatchFaceService 類使用一個 Handler 實(shí)例通過線程的消息隊列來發(fā)送和處理延時的消息:

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)可以看到表盤時,這個方法初始化了定時器:

@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è)置下一個定時器。

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

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

CalendarWatchFaceService 類提供一個回調(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é)果保存在一個成員變量中,銷毀 view,和調(diào)度下一個定時器再次運(yùn)行任務(wù)。


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號