深度解析HarmonyOS SDK實況窗服務原始碼,Get不同場景下的多種模板

HarmonyOS_SDK發表於2024-08-28

HarmonyOS SDK實況窗服務(Live View Kit)作為一個實時呈現應用服務資訊變化的小視窗,遍佈於裝置的各個使用介面,它的魅力在於將複雜的應用場景資訊簡潔提煉並實時重新整理,在不影響當前其他應用操作的情況下,時刻向使用者展示最新的資訊動態,使用者也可以點選實況窗卡片或膠囊進入應用落地頁檢視詳細資訊,享受來自應用的高效資訊同步服務。

image

實況窗服務為不同場景定製了多樣化的卡片模板,包括進度視覺化模板、強調文字模板、左右文字模板、賽事比分模板、導航模板,除了這5種卡片形態的模板外,實況窗還有實況膠囊和實況計時器兩種形態。下面,本文將詳細展示這些模板,介紹其適用的場景,並講解模板的具體實現步驟。

開發準備

在建立本地實況窗之前,需要先完成基本的準備工作,並開通實況窗服務權益。開通實況窗權益大致分為5個步驟,詳細的申請步驟可參考實況窗服務的開發指南

開發步驟

下面將以在本地建立、更新和結束實況窗為例,展示具體的開發步驟。

1.匯入liveViewManager。

在建立本地實況窗前,需要在專案中匯入liveViewManager,並新建實況窗控制類,構造isLiveViewEnabled()方法,用於校驗實況窗開關是否開啟。開啟實況窗開關是建立實況窗的前提條件。示例程式碼如下:

import { liveViewManager } from '@kit.LiveViewKit';

export class LiveViewController {
private static async isLiveViewEnabled(): Promise<boolean> {
return await liveViewManager.isLiveViewEnabled();
  }
}

2.建立實況窗。

實況窗根據擴充套件區不同共有5種樣式模板:進度視覺化模板、強調文字模板、左右文字模板、賽事比分模板和導航模板。

進度視覺化模板

進度視覺化模板可適用於叫車、外賣等需要呈現完整程序及當前節點的場景,透過進度視覺化模板的實況窗,使用者可一眼檢視應用的服務程序和實時變化。這裡以即時配送場景為例,展示具體的示例程式碼。

image

在構建LiveViewController後,需要在程式碼中初始化LiveViewController並呼叫liveViewManager.startLiveView()方法建立實況窗。其中event的取值為DELIVERY則代表即時配送場景,若取值為TAXI則表示出行叫車場景。

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "DELIVERY", // 實況窗的應用場景。DELIVERY:即時配送(外賣、生鮮)
      liveViewData: {
        primary: {
          title: "騎手已接單",
          content: [
            { text: "距商家 " },
            { text: "300 ", textColor: "#FF007DFF" },
            { text: "米 | " },
            { text: "3 ", textColor: "#FF007DFF" },
            { text: "分鐘到店" }
          ], // 所有文字僅能設定為一種顏色,不設定textColor時,預設展示#FF000000
          keepTime: 15,
          clickAction: await LiveViewController.buildWantAgent(),
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PROGRESS,
            progress: 40,
            color: "#FF317AF7",
            backgroundColor: "#f7819ae0",
            indicatorType: liveViewManager.IndicatorType.INDICATOR_TYPE_UP,
            indicatorIcon: "indicator.png", // 進度條指示器圖示,取值為
"/resources/rawfile"路徑下的檔名
            lineType: liveViewManager.LineType.LINE_TYPE_DOTTED_LINE,
            nodeIcons: ["icon_1.png", "icon_2.png", "icon_3.png"] // 進度條每個節點圖示,
取值為"/resources/rawfile"路徑下的檔名
          }
        }
      }
    };
  }

  private static async isLiveViewEnabled(): Promise<boolean> {
    return await liveViewManager.isLiveViewEnabled();
  }

  private static async buildWantAgent(): Promise<Want> {
    const wantAgentInfo: wantAgent.WantAgentInfo = {
      wants: [
        {
          bundleName: 'xxx.xxx.xxx', // 應用實際bundleName
          abilityName: 'EntryAbility'
        } as Want
      ],
      operationType: wantAgent.OperationType.START_ABILITIES,
      requestCode: 0,
      wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
    };
    const agent = await wantAgent.getWantAgent(wantAgentInfo);
    return agent;
  }
}

強調文字模板

強調文字模板適用於取餐、排隊等需要強調部分文字資訊的場景。透過強調文字模板實況窗,使用者可以快速獲取取餐碼、排號情況等重要資訊,這裡以取餐場景為例,展示具體的示例程式碼。

image

在強調文字模板中,event取值為PICK_UP則代表取餐場景,若取值為QUEUE則代表排隊場景。

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "PICK_UP", // 實況窗的應用場景。PICK_UP:取餐。
      liveViewData: {
        primary: {
          title: "餐品已備好",
          content: [
            { text: "請前往", textColor: "#FF000000" },
            { text: "XXX店取餐", textColor: "#FF000000" }
          ],
          keepTime: 15,
          clickAction: await LiveViewController.buildWantAgent(),
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PICKUP,
            title: "取餐碼",
            content: "72988",
            underlineColor: "#FF0A59F7",
            descPic: "coffee.png"
          }
        }
      }
    };
  }
  ... ...
}

左右文字模板

左右文字模板適用於高鐵、航班等左右資訊對稱的場景,透過該模板,使用者可以快速獲取始發地、目的地、開始和結束時間等出行資訊。這裡以高鐵列車票場景為例,展示具體的示例程式碼。

image

在左右文字模板中,event取值為TRAIN則代表高鐵/火車場景,若取值為FLIGHT則代表航班場景。

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "TRAIN", // 實況窗的應用場景。TRAIN:高鐵/火車。
      liveViewData: {
        primary: {
          title: "列車檢票提醒",
          content: [
            { text: "檢票口 " },
            { text: "6B ", textColor: "#FF007DFF" },
            { text: "| 座位 " },
            { text: "03車 12F", textColor: "#FF007DFF" }
          ],// 所有文字僅能設定為一種顏色,不設定textColor時,預設展示#FF000000
          keepTime: 15,
          clickAction: await LiveViewController.buildWantAgent(), // 點選實況窗預設動作。
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_FLIGHT,
            firstTitle: "09:00",
            firstContent: "上海虹橋",
            lastTitle: "14:20",
            lastContent: "漢口",
            spaceIcon: "icon.png",
            isHorizontalLineDisplayed: true,
            additionalText: "以上資訊僅供參考" // 擴充套件區底部內容,僅可用於左右文字模板。
          }
        }
      }
    };
  }
  ... ...
}

賽事比分模板

賽事比分模板適用於競技比賽的場景,透過該模板,使用者可以快速獲取比賽隊伍、當前比分、場次等比賽資訊。

image

在賽事比分模板中,SCORE代表賽事比分場景。

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "SCORE", // 實況窗的應用場景。SCORE:賽事比分。
      liveViewData: {
        primary: {
          title: "第四節比賽中",
          content: [
            { text: "XX VS XX" },
            { text: " | ", textColor: "#f7b7b1b3"},
            { text: "小組賽第五場"}
          ],
          keepTime: 1,
          clickAction: await LiveViewController.buildWantAgent(),
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_SCORE,
            hostName: "隊名A",
            hostIcon: "host.png",
            hostScore: "110",
            guestName: "隊名B",
            guestIcon: "guest.png",
            guestScore: "102",
            competitionDesc: [
              { text: "●", textColor: "#FFFF0000" },
              { text: "Q4" }
            ],
            competitionTime: "02:16",
            isHorizontalLineDisplayed: true
          }
        }
      }
    };
  }
  ... ...
}

導航模板

導航模板適用於出行導航場景。透過該模板,使用者可以快速獲取所需導航的目的地大致方位資訊。在導航模板中,event取值為NAVIGATION則代表導航場景。

image

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "NAVIGATION", // 實況窗的應用場景。NAVIGATION:導航。
      liveViewData: {
        primary: {
          title: "178米後左轉",
          content: [
            { text: "去往", textColor: "#FF000000" },
            { text: " 南京東路", textColor: "#FF000000" }
          ],
          keepTime: 15,
          clickAction: await LiveViewController.buildWantAgent(),
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_NAVIGATION,
            currentNavigationIcon: "navigation.png",
            navigationIcons: ["left.png","straight.png","straight.png","right.png"]
          }
        }
      }
    };
  }
  ... ...
}

實況膠囊

實況膠囊是在裝置熄屏和狀態列中展示的區別於卡片態的另一種實況形態,膠囊內需顯示最精簡、最重要的內容,保證使用者一瞥即得重要資訊。並且,膠囊形態各模板引數固定,與建立實況窗時的模板型別無關。

image

在同步建立實況窗膠囊時,需要在liveViewManager.LiveView結構體中攜帶膠囊所需的引數capsule,不同膠囊型別攜帶不同的引數。可建立的膠囊型別有:文字膠囊、計時器膠囊和進度膠囊。這裡以文字膠囊為例,展示具體的示例程式碼。

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "DELIVERY", // 實況窗的應用場景。DELIVERY:即時配送(外賣、生鮮)。
      liveViewData: {
        primary: {
          title: "餐品待支付",
          content: [
            { text: "咖啡 ", textColor: "#FF000000" },
            { text: "等2件商品", textColor: "#FF000000" }
          ],
          keepTime: 15,
          clickAction: await LiveViewController.buildWantAgent(),
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PICKUP,
            title: "待支付金額",
            content: "25.5元",
            underlineColor: "#FF0A59F7",
            descPic: "coffee.png"
          }
        },
        // 實況膠囊相關引數
        capsule: {
          type: liveViewManager.CapsuleType.CAPSULE_TYPE_TEXT,
          status: 1,
          icon: "capsule_store.png",
          backgroundColor: "#ff0676e7",
          title: "待支付"
        }
      }
    };
  }
  ... ...
}

實況窗計時器

實況窗計時器適用於排隊、搶票等場景。開發者若需要使用實況窗計時器,則需在liveViewManager.LiveView結構體中的配置timer欄位,並在當前支援的欄位中使用佔位符:${placeholder.timer}。

image

具體的示例程式碼如下:

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "QUEUE", // 實況窗的應用場景。QUEUE:排隊
      timer: {
        time: 620000,
        isCountdown: false,
        isPaused: false
      },
      liveViewData: {
        primary: {
          title: "大桌4人等位  32桌",
          content: [
            { text: "已等待 " }, 
            { text: "${placeholder.timer}", textColor:"#ff10c1f7" },
            { text: " | 預計還需>30分鐘" }
          ], // 所有文字僅能設定為一種顏色,不設定textColor時,預設展示#FF000000
          keepTime: 15,
          clickAction: await LiveViewController.buildWantAgent(),
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PROGRESS,
            progress: 0,
            color: "#FFFF0000",
            backgroundColor: "#FF000000",
            indicatorType: liveViewManager.IndicatorType.INDICATOR_TYPE_OVERLAY,
            indicatorIcon: "indicator.png", // 進度條指示器圖示,取值為
"/resources/rawfile"路徑下的檔名
            lineType: liveViewManager.LineType.LINE_TYPE_DOTTED_LINE,
            nodeIcons: ["icon_1.png","icon_2.png"] // 進度條每個節點圖示,取值為
"/resources/rawfile"路徑下的檔名
          }
        }
      }
    };
  }
  ... ...
}

3.本地更新和結束實況窗。

在本地建立完實況窗後,若應用業務狀態發生變化,則需要呼叫liveViewManager的updateLiveView()更新實況窗,更新時對請求體中需要修改的對應引數進行修改。在該應用的服務程序結束時,需要呼叫stopLiveView()來結束實況窗。這裡以即時配送場景的進度視覺化模板為例,來說明更新和結束實況窗及實況膠囊的方法,具體示例程式碼如下:

import { liveViewManager } from '@kit.LiveViewKit';
import { Want, wantAgent } from '@kit.AbilityKit';

export class LiveViewController {
  private static contentColor: string = '#FF000000';
  private static capsuleColor: string = '#FF308977';

  public async startLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 建立實況窗
    const defaultView = await LiveViewController.buildDefaultView();
    return await liveViewManager.startLiveView(defaultView);
  }

  public async updateLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 修改實況窗內容
    const defaultView = await LiveViewController.buildDefaultView();
    defaultView.liveViewData.primary.title = "預計23:49送達";
    defaultView.liveViewData.primary.content = [
      { text: "等待商家接單,",
        textColor: LiveViewController.contentColor },
      { text: "03:20未接單自動取消",
        textColor: LiveViewController.contentColor }
    ];
    defaultView.liveViewData.primary.layoutData = {
      layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PROGRESS,
      progress: 0,
      lineType: 0,
      nodeIcons: [ // 進度條每個節點圖示,取值為"/resources/rawfile"路徑下的檔名
        'icon_store_white.png',
        'icon_finish.png'
      ]
    };
    defaultView.liveViewData.capsule = {
      type: liveViewManager.CapsuleType.CAPSULE_TYPE_TEXT,
      status: 1,
      icon: 'capsule_store.png',
      backgroundColor: LiveViewController.capsuleColor,
      title: "待接單"
    };
    // 更新實況窗
    return await liveViewManager.updateLiveView(defaultView);
  }

  public async stopLiveView(): Promise<liveViewManager.LiveViewResult> {
    // 校驗實況窗開關是否開啟
    if (!LiveViewController.isLiveViewEnabled()) {
      throw new Error("Live view is disabled.");
    }
    // 修改實況窗內容
    const defaultView = await LiveViewController.buildDefaultView();
    defaultView.liveViewData.primary.title = '商品已送達';
    defaultView.liveViewData.primary.content = [
      { text: '感謝您的認可,',
        textColor: LiveViewController.contentColor },
      { text: '期待下一次光臨',
        textColor: LiveViewController.contentColor }
    ];
    defaultView.liveViewData.primary.layoutData = {
      layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PROGRESS,
      progress: 100,
      lineType: 0,
      nodeIcons: [ // 進度條每個節點圖示,取值為"/resources/rawfile"路徑下的檔名
        'icon_order.png',
        'icon_finish.png'
      ]
    };
    defaultView.liveViewData.capsule = {
      type: liveViewManager.CapsuleType.CAPSULE_TYPE_TEXT,
      status: 1,
      icon: 'capsule_gps.png',
      backgroundColor: LiveViewController.capsuleColor,
      title: '已送達'
    };
    // 結束實況窗
    return await liveViewManager.stopLiveView(defaultView);
  }

  private static async buildDefaultView(): Promise<liveViewManager.LiveView> {
    return {
      // 構造實況窗請求體
      id: 0, // 實況窗ID,開發者生成。
      event: "DELIVERY", // 實況窗的應用場景。DELIVERY:即時配送(外賣、生鮮)
      liveViewData: {
        primary: {
          title: "餐品待支付",
          content: [
            { text: "咖啡 ", textColor: "#FF000000" },
            { text: "等2件商品", textColor: "#FF000000" }
          ],
          keepTime: 15,
          clickAction: await LiveViewController.buildWantAgent(),
          layoutData: {
            layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PICKUP,
            title: "待支付金額",
            content: "25.5元",
            underlineColor: "#FF0A59F7",
            descPic: "coffee.png"
          }
        },
        // 實況膠囊相關引數
        capsule: {
          type: liveViewManager.CapsuleType.CAPSULE_TYPE_TEXT,
          status: 1,
          icon: "capsule_store.png",
          backgroundColor: "#FF308977",
          title: "待支付",
          content: "..."
        }
      }
    };
  }
  ... ...
}

瞭解更多詳情>>

獲取實況窗服務開發指導文件

相關文章