鴻蒙軟總線的簡單使用
軟總線是什么?
分布式軟總線是手機、平板、智能穿戴、智慧屏、車機等分布式設備的通信基座,為設備之間的互聯互通提供了統一的分布式通信能力。
本篇講到的知識點:
- 啟動遠程FA(Feature Ability)
- 連接遠程PA(Particle Ability),發送控制命令&遠端處理數據(場景1:傳遞加法數據,遠端計算后返回給客戶端。場景2:傳遞數據,遠端Service接收后更新遠端的UI。)
- FA跨設備遷移(可回遷)
- 混合打包
- 其他奇怪的知識
技術要求和環境要求:
基本組件熟練使用,ServiceAbility,CommonEventManager(公共事件開發)
兩臺HarmonyOS 2.0的真機 或 DevEco Studio 2.2 Beta1(分布式模擬器的自動開啟,可同時模擬運行兩臺設備,且自動組網)。
其他
- 真機分布式通信要求:同一局域網內,登錄相同華為賬號,開啟藍牙 (可行方案),這樣在 設定-超級終端 中 附近我的設備 即可查看到另外一臺設備。
- 分布式模擬器 會自動組網,不需要手動做其他操作。(設定的超級終端中看不出來已經組網成功)
- 運行到真機上需要進行簽名,模擬器則不需要。
代碼下載
先看下效果



代碼結構

- adapter:DevicesListAdapter,用于向ListContainer控件中填充設備數據。
- component:SelectDeviceDialog封裝了設備選擇彈框
- proxy:定義了連接遠程和調用遠程service(PA)的接口、實現類以及代理。
- service:RemoteService為被控制端service,供手機端遠程調用。
申請權限
在entry\src\main\config.json中申請以下4個權限:
- ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE:用于允許監聽分布式組網內的設備狀態變化。
- ohos.permission.GET_DISTRIBUTED_DEVICE_INFO:用于允許獲取分布式組網內的設備列表和設備信息。
- ohos.permission.GET_BUNDLE_INFO:用于查詢其他應用的信息。
- ohos.permission.DISTRIBUTED_DATASYNC:用于允許不同設備間的數據交換。
此外,還需要在實現Ability的代碼中顯式聲明需要使用多設備協同訪問的權限,示例代碼如下:

獲取組網內在線的其他設備DeviceInfo(Id&Name)

獲取自身設備的Id

啟動遠程FA

和普通畫面的啟動類似,withDeviceId("") 為本地畫面跳轉。
跨設備啟動需要攜帶 遠程設備的DeviceID,以及設置 "支持分布式調度系統中的多設備啟動"Flag。
連接遠程PA,發送控制命令&遠端處理數據
第一步: 客戶端創建遠程連接代理類
- public class MyRemoteProxy implements IRemoteBroker {
- /**
- * 遠端響應成功的標識
- */
- public static final int ERR_OK = 0;
- private static final String TAG = MyRemoteProxy.class.getSimpleName();
- private final IRemoteObject remote;
- public MyRemoteProxy(IRemoteObject remote) {
- this.remote = remote;
- }
- @Override
- public IRemoteObject asObject() {
- return remote;
- }
- // 攜帶數據向遠端Sevice發送請求
- public int senDataToRemote(int requestType, Map paramMap) {
- MessageParcel data = MessageParcel.obtain();
- MessageParcel reply = MessageParcel.obtain();
- MessageOption option = new MessageOption(MessageOption.TF_SYNC);
- int ec = 1;
- int result = -1;
- try {
- if (paramMap.get("inputString") instanceof String) {
- String inputString = (String) paramMap.get("inputString");
- data.writeInt(requestType);
- data.writeString(inputString);
- remote.sendRequest(requestType, data, reply, option);
- }
- ec = reply.readInt();
- if (ec != ERR_OK) {
- LogUtils.error(TAG, "RemoteException:");
- } else {
- if (requestType == ConnectManagerIml.REQUEST_PLUS) {
- result = reply.readInt(); // 返回成功后拿到遠端計算的結果。
- }
- }
- } catch (RemoteException e) {
- LogUtils.error(TAG, "RemoteException:");
- } finally {
- ec = ERR_OK;
- if (result != -1) {
- ec = result;
- }
- data.reclaim();
- reply.reclaim();
- }
- return ec;
- }
- }
- 實現IRemoteBroker接口, asObject返回遠程RemoteObject對象
- 創建構造方法(參數為connectAbility成功時回調方法onAbilityConnectDone中的遠程操作對象)
- 封裝向遠端發送請求的方法,便于后續進行控制 (本例中是簡單的加法請求)

MessageOption.TF_SYNC代表同步,意味著會在sendRequest時阻塞等待來自遠端Service的返回。
遠端Service返回值是 reply,reply.readInt() 默認會返回0,代表請求成功。若是想攜帶其他返回值,需要在遠端Service中進行處理,下一步會講到。
第二步: 遠端Service中,創建RemoteObject并處理請求
- public class MyRemote extends RemoteObject implements IRemoteBroker {
- private MyRemote() {
- super("===MyService_Remote");
- }
- @Override
- public IRemoteObject asObject() {
- return this;
- }
- @Override
- public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
- LogUtils.info(TAG, "===onRemoteRequest......");
- int requestType = data.readInt();
- String inputString = "";
- if (code == REQUEST_SEND_DATA) {
- inputString = data.readString();
- publishInput(requestType, inputString);
- } else if (code == REQUEST_PLUS) {
- int a = data.readInt();
- int b = data.readInt();
- reply.writeInt(ERR_OK);
- reply.writeInt(a + b);
- publishPlusResult(requestType, String.valueOf(a + b));
- }
- return true;
- }
- }
- @Override
- protected IRemoteObject onConnect(Intent intent) {
- super.onConnect(intent);
- return remote.asObject();
- }
onRemoteRequest 接收來自 sendRequest(requestType, data, reply, option); 傳遞過來的請求類型,數據,返回值,請求類型。
一般不需要處理reply,客戶端reply.readInt() 也會拿到0(表示請求成功),若是需要在遠端接收到請求后,需要額外返回數據給客戶端,則需要進行write操作。
第三步: 連接遠端Service

重點都標記了下,這塊沒啥好講的,ServiceAbility的基本連接操作。
第四步: 發送命令,遠端Service處理數據(返回數據、更新UI)
場景1:傳遞加法數據,遠端計算后返回給客戶端

場景2:傳遞數據,遠端Service接收后更新遠端的UI

遠端Service在onRemoteRequest中處理更新UI的請求,遠端利用公共事件,進行UI的更新。(意味著也就可以 控制音樂的播放,暫停 等等)

FA跨設備遷移(可回遷)
跨端遷移開發指導 目的: 實現正在編輯的頁面,流轉的另外一臺設備,利用分布式的能力提高用戶的體驗。
步驟一
想要遷移的Ability以及其下所有的AbilitySlice都必須需要實現一個接口: IAbilityContinuation
坑點1:哪怕你知識想將Ability其中一個Slice進行遷移,也必須將Ability的所有的slice都要實現該接口

onStartContinuation FA請求遷移后,系統首先回調此方法,開發者可以在此回調中決策當前是否可以執行遷移,比如,彈框讓用戶確認是否開始遷移。
onSaveData(IntentParams saveData) 如果onStartContinuation()返回true,則系統回調此方法,開發者在此回調中保存必須傳遞到目標端設備上,用于恢復FA狀態的數據。
onRestoreData(IntentParams restoreData) 發起端設備上FA完成保存數據后,系統在目標端設備上回調此方法,開發者在此回調中接受用于恢復FA狀態的數據。
onCompleteContinuation(int result) 目標端設備上恢復數據一旦完成,系統就會在發起端設備上回調FA的此方法,以便通知應用遷移流程已結束。
坑點2: 不要忘記 return true; Ability中也要。
坑點3: onRestoreData進行UI的恢復時,需要切換到UI線程,否則...(沒報錯Log)
步驟二
可回遷的遷移

回遷(若是已經回遷了,再進行回遷,會報錯。 先try-catch了)

混合打包
目前鴻蒙上的應用有以下三種
- 直接運行的 安卓應用
- 使用DevEco Studio編寫的鴻蒙應用
- 已有開發好的 安卓應用,想擁有 鴻蒙的一些特性,從而進行混合打包。apk邏輯無需變化,即可擁有鴻蒙特性,例如 服務卡片。
如何進行混合打包?
篇幅原因,將會在另外一篇中詳細介紹。 請移步: 安卓應用如何混合打包擁有鴻蒙的卡片服務?
奇怪的知識
針對:分布式數據服務開發指導
設計字段:
單版本分布式數據庫的介紹比較簡單。存儲key-value, value若是復雜點沒介紹。若想value中存儲很多其他數據,可進行以下操作。

以上時創建單版本分布式數據庫時,設置Schema對象,從而設計了數據庫中的字段。
數據存儲:

存入的時候,需要以json的格式進行寫入。
查詢:
