如何實現跨裝置的雙向連線? Labo塗鴉鴻蒙親子版分散式開發技術分享

AUX01發表於2021-07-02

近期,首屆HarmonyOS開發者創新大賽正式落下帷幕。大賽共歷時5個月,超過3000支隊伍的10000多名選手參賽,25000多位開發者參與了大賽學習,最終23支參賽隊伍斬獲獎項,產出了多款有創新、有創意、有價值的優秀作品。其中由“Labo Lado兒童藝術創想”團隊打造的《Labo塗鴉鴻蒙親子版》就是其中之一,其創造性地通過HarmonyOS分散式技術,實現了多裝置下的親子互動塗鴉功能,最終摘得大賽一等獎。

在很早以前,“Labo Lado兒童藝術創想”團隊就做過一款塗鴉遊戲的應用,該應用可以讓孩子和父母在一個平板或者手機上進行繪畫比賽,比賽的方式就是螢幕一分為二,兩人各在裝置的一邊進行塗鴉。這種方式雖然有趣,但是對於繪畫而言,螢幕尺寸限制了使用者的發揮和操作。因此團隊希望這類玩法能通過多個裝置完成,於是他們研究了ZeroConf、iOS的Multipeer Connectivity、Google Nearby等近距離互聯的技術, 結果發現這些技術在裝置發現和應用拉起方面實現的都不理想,尤其是當目標使用者是兒童的情況下,操作起來不夠簡便也不易上手。

HarmonyOS的出現給團隊帶來了希望。他們發現HarmonyOS的分散式技術有著很大的應用潛力,這項技術讓裝置的發現和應用拉起變的非常的簡單自然,互聯的過程也很流暢,很好地解決了單機操作的限制,讓跨裝置聯機功能能夠非常容易地實現。此外,HarmonyOS的開發也給團隊留下了很深刻的印象,以往繁瑣的開發步驟,在 HarmonyOS 中僅需幾個配置、幾行程式碼即可完成,無需花費太多精力。在《Labo塗鴉鴻蒙親子版》裡面的5個分散式玩法的開發只用了團隊一名開發者不到兩個月的時間,其中還包括了學習上手、解決文件不全和各種疑難問題的過程。

以下是“Labo Lado兒童藝術創想”團隊基於HarmonyOS的分散式開發關鍵技術的簡單分享:

一、分散式技術實踐

HarmonyOS的分散式能力是在系統層面實現的,在裝置雙方同屬一個區域網的情況下,裝置都可以快速的發現和進行流暢的通訊。下面將從HarmonyOS裝置的發現、應用的拉起、應用通訊和雙向通訊幾個部分來進行分享。

1、裝置的發現

假設裝置A想要邀請另外一個裝置B加入,AB任何一方都無需啟動特別的廣播服務,只要發起方裝置A在應用內呼叫裝置發現程式碼,就可以列出附近符合條件可用的的裝置。

以下是獲取裝置列表的示例程式碼:

public static List getRemoteDevice() {

List deviceInfoList = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);

return deviceInfoList;

}

列出裝置之後,使用者就可以通過裝置名選擇想要邀請的裝置了。

(左側裝置A發現右側名為“ye”的裝置B的介面展示)

2、應用的拉起

裝置A邀請了裝置B之後,如果裝置B上應用沒啟動,裝置A可直接通過呼叫startAbility方法來拉起裝置B上的應用。雙方應用都啟動了之後,就可以進行RPC通訊了。如果需要事先檢查裝置B上的應用是否已經啟動或者是否在後臺,可通過在應用中增加一個PA來實現。在拉起之前,裝置A先連線裝置B的應用中的PA可以實現更復雜精準的遠端應用啟動控制。

3、應用通訊

在應用中啟動一個PA,專門用作通訊的伺服器端。當裝置B的應用被拉起之後,裝置A就會通過connectAbility與裝置B的PA進行連線,通訊採用RPC方式實現,並使用IDL定義通訊介面。

4、雙向通訊

RPC的通訊方式使用簡單,但是隻能支援單向通訊。為了實現雙向通訊,可在裝置A與裝置B發起建立連線成功之後,再讓裝置B與裝置A發起建立一個連線,用兩個連線實現了雙向通訊。下面是這兩個連線建立過程的示意時序圖:

在裝置A與裝置B建立連線的時候,裝置A必須將自己的DeviceId傳送給裝置B,然後裝置B才可以主動發起一個與裝置A的連線,獲取當前裝置的DeviceId方法如下:

KvManagerFactory.getInstance().createKvManager(new KvManagerConfig(this)).getLocalDeviceInfo().getId()

應用中,FA主要實現了介面層邏輯,PA部分用做資料通訊的服務端。為了防止拉起應用導致使用者當前面的操作被中斷,可通過PA來查詢當前FA的狀態,如果FA已經啟動了,就跳過拉起,直接進行下一步操作即可。

二、資料介面與資料結構定義

使用了IDL定義了兩個通用的介面,分別用來進行非同步和同步呼叫:

int sendSyncCommand([in] int command, [in] String params);

void sendAsyncCommand([in] int command, [in] String params, [in] byte[] content);

大部分情況下,遠端呼叫大部分都通過同步的方式進行,使用者之間的繪畫資料通過非同步介面傳輸,資料在使用者繪製的時候採集,每50ms左右傳送一次,這個頻率可以大概保證使用者視覺上沒有卡頓,而又不至於因為介面過度呼叫導致卡頓或者耗電量過大。採集的繪畫資料的資料結構大致如下:

enum action //動作,表示落筆、移動、提筆等動作

int tagId //多點觸控識別標記

int x //x座標

int y //y座標

enum brushType //筆刷型別

int brushSize //筆刷大小

enum brushColor //筆刷顏色

int layer //圖層

這款應用是支援多點觸控的,所以每個觸控點在落筆的的時候,都使用了tagId進行標記。這些資料除了通訊外,還會完整地儲存在檔案中,這樣使用者就可以通過應用內的播放功能播放該資料,回看繪畫的整個過程。

三、教程錄製與曲線平滑

1、教程製作

這款產品的特色之一是教程是動態的,使用者可以自己拼裝或者通過遊戲生成教程角色。目前應用內建六種教程。這些教程預先由設計師在photoshop中畫好並標記各個部位,然後再通過專門的photoshop指令碼匯出到教程錄製應用中,再由設計師按部位逐個進行臨摹繪製,繪製完成,應用會將設計師的繪製過程資料儲存為json檔案,通過將這些json的檔案裡的部位互換,我們就實現了使用者自己拼裝教程的功能了。

2、曲線平滑

繪製過程,為了讓使用者繪製的曲線更加平滑,採用二次貝塞爾曲線演算法進行差值(Quadratic Bezier Curve),該演算法簡單效率也非常不錯:

public Point quadraticBezier(Point p0, Point p1, Point p2, float t) {

Point pFinal = new Point();

pFinal.x = (float) (Math.pow(1 - t, 2) * p0.x + (1 - t) * 2 * t * p1.x + t * t * p2.x);

pFinal.y = (float) (Math.pow(1 - t, 2) * p0.y + (1 - t) * 2 * t * p1.y + t * t * p2.y);

return pFinal;

}

基於HarmonyOS的分散式特性,《Labo塗鴉鴻蒙親子版》完成了一次已有應用的自我嘗試和突破,大大的增加了使用者在使用過程中的樂趣,為使用者帶來了全新的跨裝置親子互動體驗,“Labo Lado兒童藝術創想”團隊在未來將與更多的HarmonyOS開發者一起,為使用者創作出更多更有趣的兒童創造類應用。

近一段時間以來,HarmonyOS 2的釋出吸引了廣大開發者的關注。作為一款面向萬物互聯時代的智慧終端作業系統,HarmonyOS 2帶來了諸多新特性、新功能和新玩法,等待開發者去探索、去學習、去實踐。也歡迎廣大開發者繼續發揮創造力和想象力,基於HarmonyOS開發出更多有創新、有創意、有價值的作品,打造出專屬於萬物互聯時代的創新產品。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章