<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

OpenHarmony開發案例:【分布式遙控器】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-16 16:44 ? 次閱讀

1.概述

目前家庭電視機主要通過其自帶的遙控器進行操控,實現的功能較為單一。例如,當我們要在TV端搜索節目時,電視機在遙控器的操控下往往只能完成一些字母或數字的輸入,而無法輸入其他復雜的內容。分布式遙控器將手機的輸入能力和電視遙控器的遙控能力結合為一體,從而快速便捷操控電視。

分布式遙控器的實現基于OpenHarmony的分布式能力和RPC通信能力,UI使用eTS進行開發。如下圖所示,分別用兩塊開發板模擬TV端和手機端。

  1. 分布式組網后可以通過TV端界面的Controller按鈕手動拉起手機端的遙控界面,在手機端輸入時會將輸入的內容同步顯示在TV端搜索框,點擊搜索按鈕會根據輸入的內容搜索相關節目。
  2. 還可以通過點擊方向鍵(上下左右)將焦點移動到我們想要的節目上,再點擊播放按鈕進行播放,按返回按鈕返回TV端主界面。
  3. 同時還可以通過手機遙控端關機按鈕同時關閉TV端和手機端界面。

UI效果圖如下:

圖1 TV端主頁默認頁面

  • 圖2 手機端遙控頁面

說明: 本示例涉及使用系統接口,需要手動替換Full SDK才能編譯通過,具體操作可參考[替換指南]。

2.搭建OpenHarmony環境

完成本篇Codelab我們首先要完成開發環境的搭建,本示例以RK3568開發板為例,參照以下步驟進行:

  1. [獲取OpenHarmony系統版本]:標準系統解決方案(二進制)。
    以3.1版本為例:
  2. 搭建燒錄環境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開發板的燒錄]
    3. 鴻蒙開發文檔指導:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]
  3. 搭建開發環境。
    1. 開始前請參考[工具準備],完成DevEco Studio的安裝和開發環境配置。
    2. 開發環境配置完成后,請參考[使用工程向導]創建工程(模板選擇“Empty Ability”),選擇JS或者eTS語言開發。
    3. 工程創建完成后,選擇使用[真機進行調測])。
      搜狗高速瀏覽器截圖20240326151450.png

3.分布式組網

本章節以系統自帶的音樂播放器為例(具體以實際的應用為準),介紹如何完成兩臺設備的分布式組網。

  1. 硬件準備:準備兩臺燒錄相同的版本系統的RK3568開發板A、B。

  2. 開發板A、B連接同一個WiFi網絡。
    打開設置-->WLAN-->點擊右側WiFi開關-->點擊目標WiFi并輸入密碼。

  3. 將設備A,B設置為互相信任的設備。

    • 找到系統應用“音樂”。
    • 設備A打開音樂,點擊左下角流轉按鈕,彈出列表框,在列表中會展示遠端設備的id。選擇遠端設備B的id,另一臺開發板(設備B)會彈出驗證的選項框。
    • 設備B點擊允許,設備B將會彈出隨機PIN碼,將設備B的PIN碼輸入到設備A的PIN碼填入框中。

    配網完畢。

4.代碼結構解讀

本篇Codelab只對核心代碼進行講解,首先來介紹下整個工程的代碼結構:

  • MainAbility:
    • model:數據模型。
      • RemoteDeviceModel.ets:獲取組網內的設備列表模型。
      • PicData.ets:圖片信息數據。
      • PicDataModel.ets:圖片信息模型。
      • ConnectModel.ets:連接遠端Service和發送消息模型。
    • pages:存放TV端各個頁面。
      • TVindex.ets:TV端主頁面。
      • VideoPlay.ets:TV端視頻播放頁面。
  • PhoneAbility:存放應用手機控制端主頁面。
    • pages/PhoneIndex.ets:手機控制端主頁面。
  • ServiceAbility:存放ServiceAbility相關文件。
    • service.ts:service服務,用于跨設備連接后通訊。
  • resources :存放工程使用到的資源文件。
    • resources/rawfile:存放工程中使用的圖片資源文件。
  • config.json:配置文件。

5.實現TV端界面

在本章節中,您將學會開發TV端默認界面和TV端視頻播放界面,示意圖參考第一章圖1和圖3所示。

建立數據模型,將圖片ID、圖片源、圖片名稱和視頻源綁定成一個數據模型。詳情代碼可以查看MainAbility/model/PicData.ets和MainAbility/model/PicDataModel.ets兩個文件。

  1. 實現TV端默認頁面布局和樣式。
    • 在MainAbility/pages/TVIndex.ets 主界面文件中添加入口組件。頁面布局代碼如下:
      // 入口組件
      @Entry
      @Component
      struct Index {
        private letters: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
        private source: string
        @State text: string = ''
        @State choose: number = -1
      
        build() {
          Flex({ direction: FlexDirection.Column }) {
            TextInput({text: this.text, placeholder: 'Search' })
              .onChange((value: string) = > {
                this.text = value
              })
      
            Row({space: 30}) {
              Text('Clear')
                .fontSize(16)
                .backgroundColor('#ABB0BA')
                .textAlign(TextAlign.Center)
                .onClick(() = > {
                  this.text = ''
                })
                .clip(true)
                .borderRadius(10)
      
              Text('Backspace')
                .fontSize(16)
                .backgroundColor('#ABB0BA')
                .textAlign(TextAlign.Center)
                .onClick(() = > {
                  this.text = this.text.substring(0, this.text.length - 1)
                })
                .clip(true)
                .borderRadius(10)
      
              Text('Controller')
                .fontSize(16)
                .backgroundColor('#ABB0BA')
                .textAlign(TextAlign.Center)
                .onClick(() = > {
                  ......
                })
                .clip(true)
                .borderRadius(10)
      
            }
      
            Grid() {
              ForEach(this.letters, (item) = > {
                GridItem() {
                  Text(item)
                    .fontSize(20)
                    .backgroundColor('#FFFFFF')
                    .textAlign(TextAlign.Center)
                    .onClick(() = > {
                      this.text += item
                      })
                    .clip(true)
                    .borderRadius(5)
                }
              }, item = > item)
      
            }
            .rowsTemplate('1fr 1fr 1fr 1fr')
            .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr')
            .columnsGap(8)
            .rowsGap(8)
            .width('75%')
            .height('25%')
            .margin(5)
            .backgroundColor('#D2D3D8')
            .clip(true)
            .borderRadius(10)
      
            Grid() {
              ForEach(this.picItems, (item: PicData) = > {
                GridItem() {
                  PicGridItem({ picItem: item })
                }
              }, (item: PicData) = > item.id.toString())
            }
            .rowsTemplate('1fr 1fr 1fr')
            .columnsTemplate('1fr 1fr')
            .columnsGap(5)
            .rowsGap(8)
            .width('90%')
            .height('58%')
            .backgroundColor('#FFFFFF')
            .margin(5)
          }
          .width('98%')
          .backgroundColor('#FFFFFF')
        }
      }
      
    • 其中PicGridItem將PicItem的圖片源和圖片名稱綁定,實現代碼如下:
      // 九宮格拼圖組件
      @Component
      struct PicGridItem {
        private picItem: PicData
        build() {
          Column() {
            Image(this.picItem.image)
              .objectFit(ImageFit.Contain)
              .height('85%')
              .width('100%')
              .onClick(() = > {
                ......
                })
              })
            Text(this.picItem.name)
              .fontSize(20)
              .fontColor('#000000')
          }
          .height('100%')
          .width('90%')
        }
      }
      
  2. 實現TV端視頻播放界面。
    • 在MainAbility/pages/VideoPlay.ets 文件中添加組件。頁面布局代碼如下:
      import router from '@system.router'
      @Entry
      @Component
      struct Play {
      // 取到Index頁面跳轉來時攜帶的source對應的數據。
        private source: string = router.getParams().source
      
        build() {
          Column() {
            Video({
              src: this.source,
            })
              .width('100%')
              .height('100%')
              .autoPlay(true)
              .controls(true)
          }
        }
      }
      
    • 在MainAbility/pages/TVIndex.ets中,給PicGridItem的圖片添加點擊事件,點擊圖片即可播放PicItem的視頻源。實現代碼如下:
      Image(this.picItem.image)
              ......
              .onClick(() = > {
                router.push({
                  uri: 'pages/VideoPlay',
                  params: { source: this.picItem.video }
                })
              })
      

6.實現手機遙控端界面

在本章節中,您將學會開發手機遙控端默認界面,示意圖參考第一章圖2所示。

  • PhoneAbility/pages/PhoneIndex.ets 主界面文件中添加入口組件。頁面布局代碼如下:
    @Entry
    @Component
    struct Index {
      build() {
        Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
          Row() {
            Image($rawfile('TV.png'))
              .width(25)
              .height(25)
            Text('華為智慧屏').fontSize(20).margin(10)
          }
          // 文字搜索框
          TextInput({ placeholder: 'Search' })
            .margin(20)
            .onChange((value: string) = > {
              if (connectModel.mRemote){
                ......
              }
            })
    
          Grid() {
            GridItem() {
          // 向上箭頭
              Button({ type: ButtonType.Circle, stateEffect: true }) {
                Image($rawfile('up.png')).width(80).height(80)
              }
              .onClick(() = > {
                ......
              })
              .width(80)
              .height(80)
              .backgroundColor('#FFFFFF')
            }
            .columnStart(1)
            .columnEnd(5)
    
            GridItem() {
          // 向左箭頭
              Button({ type: ButtonType.Circle, stateEffect: true }) {
                Image($rawfile('left.png')).width(80).height(80)
              }
              .onClick(() = > {
                ......
              })
              .width(80)
              .height(80)
              .backgroundColor('#FFFFFF')
            }
    
            GridItem() {
          // 播放鍵
              Button({ type: ButtonType.Circle, stateEffect: true }) {
                Image($rawfile('play.png')).width(60).height(60)
              }
              .onClick(() = > {
                ......
              })
              .width(80)
              .height(80)
              .backgroundColor('#FFFFFF')
            }
    
            GridItem() {
          // 向右箭頭
              Button({ type: ButtonType.Circle, stateEffect: true }) {
                Image($rawfile('right.png')).width(70).height(70)
              }
              .onClick(() = > {
                ......
              })
              .width(80)
              .height(80)
              .backgroundColor('#FFFFFF')
            }
    
            GridItem() {
          // 向下箭頭
              Button({ type: ButtonType.Circle, stateEffect: true }) {
                Image($rawfile('down.png')).width(70).height(70)
              }
              .onClick(() = > {
                ......
              })
              .width(80)
              .height(80)
              .backgroundColor('#FFFFFF')
            }
            .columnStart(1)
            .columnEnd(5)
          }
          .rowsTemplate('1fr 1fr 1fr')
          .columnsTemplate('1fr 1fr 1fr')
          .backgroundColor('#FFFFFF')
          .margin(10)
          .clip(new Circle({ width: 325, height: 325 }))
          .width(350)
          .height(350)
    
          Row({ space:100 }) {
            // 返回鍵
            Button({ type: ButtonType.Circle, stateEffect: true }) {
              Image($rawfile('return.png')).width(40).height(40)
            }
            .onClick(() = > {
              ......
            })
            .width(100)
            .height(100)
            .backgroundColor('#FFFFFF')
    
            // 關機鍵
            Button({ type: ButtonType.Circle, stateEffect: true }) {
              Image($rawfile('off.png')).width(40).height(40)
            }
            .onClick(() = > {
              ......
            })
            .width(100)
            .height(100)
            .backgroundColor('#FFFFFF')
    
            // 搜索鍵
            Button({ type: ButtonType.Circle, stateEffect: true }) {
              Image($rawfile('search.png')).width(40).height(40)
            }
            .onClick(() = > {
              ......
            })
            .width(100)
            .height(100)
            .backgroundColor('#FFFFFF')
          }
          .padding({ left:100 })
        }
        .backgroundColor('#E3E3E3')
      }
    }
    

7.實現分布式拉起和RPC通信

在本章節中,您將學會如何拉起在同一組網內的設備上的FA,并且連接遠端Service服務。

  1. 首先通過TV端拉起手機端界面,并將本端的deviceId發送到手機端。

    • 點擊TV端主頁上的"Controller"按鈕,增加.onClick()事件。調用RegisterDeviceListCallback()發現設備列表,并彈出設備列表選擇框CustomDialogExample,選擇設備后拉起遠端FA。CustomDialogExample()代碼如下:
      // 設備列表彈出框
      @CustomDialog
      struct CustomDialogExample {
        @State editFlag: boolean = false
        controller: CustomDialogController
        cancel: () = > void
        confirm: () = > void
      
        build() {
          Column() {
            List({ space: 10, initialIndex: 0 }) {
              ForEach(DeviceIdList, (item) = > {
                ListItem() {
                  Row() {
                    Text(item)
                      .width('87%')
                      .height(50)
                      .fontSize(10)
                      .textAlign(TextAlign.Center)
                      .borderRadius(10)
                      .backgroundColor(0xFFFFFF)
                      .onClick(() = > {
                        onStartRemoteAbility(item);
                        this.controller.close();
                      })
                  }
                }.editable(this.editFlag)
              }, item = > item)
            }
          }.width('100%').height(200).backgroundColor(0xDCDCDC).padding({ top: 5 })
        }
      }
      
    • 點擊設備彈出框內的Text組件會調用onStartRemoteAbility()方法拉起遠端FA(手機端),將TV端的deviceId傳給手機端,并連接手機端的Service。因此在featureAbility.startAbility()成功的回調中也要調用onConnectRemoteService()方法。這里將連接遠端Service和發送消息抽象為ConnectModel,詳細代碼可查看MainAbility/model/ConnectModel.ets文件中onConnectRemoteService()方法。onStartRemoteAbility()方法的代碼如下:
      function onStartRemoteAbility(deviceId) {
        AuthDevice(deviceId);
        let numDevices = remoteDeviceModel.deviceList.length;
        if (numDevices === 0) {
          prompt.showToast({
            message: "onStartRemoteAbility no device found"
          });
          return;
        }
      
        var params = {
          remoteDeviceId: localDeviceId
        }
      
        var wantValue = {
          bundleName: 'com.example.helloworld0218',
          abilityName: 'com.example.helloworld0218.PhoneAbility',
          deviceId: deviceId,
          parameters: params
        };
      
        featureAbility.startAbility({
          want: wantValue
        }).then((data) = > {
          // 拉起遠端后,連接遠端service
          connectModel.onConnectRemoteService(deviceId)
        });
      }
      
    • 需要注意的是,配置文件config.json中ServiceAbility的屬性visible要設置為true,代碼如下:
      "abilities": [
            ...
            {
              "visible": true,
              "srcPath": "ServiceAbility",
              "name": ".ServiceAbility",
              "icon": "$media:icon",
              "srcLanguage": "ets",
              "description": "$string:description_serviceability",
              "type": "service"
            }
      ],
      
  2. 成功拉起手機端界面后,通過接收TV端傳過來的deviceId連接TV端的Service。在手機端的生命周期內增加aboutToAppear()事件,在界面被拉起的時候讀取對方的deviceId并調用onConnectRemoteService()方法,連接對方的Service,實現代碼如下:

    async aboutToAppear() {
        await featureAbility.getWant((error, want) = > {
          // 遠端被拉起后,連接對端的service
          if (want.parameters.remoteDeviceId) {
            let remoteDeviceId = want.parameters.remoteDeviceId
            connectModel.onConnectRemoteService(remoteDeviceId)
          }
        });
      }
    
  3. 建立一個ServiceAbility處理收到的消息并發布公共事件,詳細代碼請看ServiceAbility/service.ts文件。TV端訂閱本端Service的公共事件,并接受和處理消息。

    • 創建SubscribeEvent(),實現代碼如下:
    subscribeEvent() {
        let self = this;
        // 用于保存創建成功的訂閱者對象,后續使用其完成訂閱及退訂的動作
        var subscriber;
        // 訂閱者信息
        var subscribeInfo = {
          events: ["publish_change"],
          priority: 100
        };
    
        // 設置有序公共事件的結果代碼回調
        function SetCodeCallBack() {
        }
        // 設置有序公共事件的結果數據回調
        function SetDataCallBack() {
        }
        // 完成本次有序公共事件處理回調
        function FinishCommonEventCallBack() {
        }
        // 訂閱公共事件回調
        function SubscribeCallBack(err, data) {
          let msgData = data.data;
          let code = data.code;
          // 設置有序公共事件的結果代碼
          subscriber.setCode(code, SetCodeCallBack);
          // 設置有序公共事件的結果數據
          subscriber.setData(msgData, SetDataCallBack);
          // 完成本次有序公共事件處理
          subscriber.finishCommonEvent(FinishCommonEventCallBack)
          // 處理接收到的數據data
          ......
    
        // 創建訂閱者回調
        function CreateSubscriberCallBack(err, data) {
          subscriber = data;
          // 訂閱公共事件
          commonEvent.subscribe(subscriber, SubscribeCallBack);
        }
    
        // 創建訂閱者
        commonEvent.createSubscriber(subscribeInfo, CreateSubscriberCallBack);
      }
    }
    
    • 在TV端的生命周期內增加aboutToAppear()事件,訂閱公共事件,實現代碼如下:
    async aboutToAppear() {
        this.subscribeEvent();
      }
    
  4. 成功連接遠端Service服務后,在手機遙控器端進行按鈕或者輸入操作都會完成一次跨設備通訊,消息的傳遞是由手機遙控器端的FA傳遞到TV端的Service服務。這里將連接遠端Service和發送消息抽象為ConnectModel,詳細代碼可查看MainAbility/model/ConnectModel.ets文件中sendMessageToRemoteService()方法。

8.設置遙控器遠端事件

手機端應用對TV端能做出的控制有:向上移動、向下移動、向左移動、向右移動、確定、返回、關閉。在手機端按鍵上增加點擊事件,通過sendMessageToRemoteService()的方法發送到TV端Service。TV端根據發送code以及數據,進行數據處理,這里只展示TV端數據處理部分的核心代碼:

// code = 1時,將手機遙控端search框內數據同步到TV端
if (code == 1) {
  self.text = data.parameters.dataList;
}
// code = 2時,增加選中圖片效果
if (code == 2) {
  // 如果在圖片序號范圍內就選中圖片,否則不更改
  var tmp: number = +data.parameters.dataList;
  if ((self.choose + tmp <= 5) && (self.choose + tmp >= 0)) {
    self.choose += tmp;
  }
}
// code = 3時,播放選中圖片對應的視頻
if (code == 3) {
  self.picItems.forEach(function (item) {
    if (item.id == self.choose) {
      router.push({
        uri: 'pages/VideoPlay',
        params: { source: item.video }
      })
    }
  })
}
// code = 4時,回到TV端默認頁面
if (code == 4) {
  router.push({
    uri: 'pages/TVIndex',
  })
}
// code = 5時,關閉程序
if (code == 5) {
  featureAbility.terminateSelf()
}
// code = 6時,搜索圖片名稱并增加選中特效
if (code == 6) {
  self.picItems.forEach(function (item) {
    if (item.name == self.text) {
      self.choose = Number(item.id)
    }
  })
}

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 遙控器
    +關注

    關注

    18

    文章

    814

    瀏覽量

    64329
  • 分布式
    +關注

    關注

    1

    文章

    769

    瀏覽量

    74139
  • 鴻蒙
    +關注

    關注

    55

    文章

    1769

    瀏覽量

    42153
  • HarmonyOS
    +關注

    關注

    79

    文章

    1878

    瀏覽量

    29335
  • OpenHarmony
    +關注

    關注

    23

    文章

    3380

    瀏覽量

    15194
收藏 人收藏

    評論

    相關推薦

    OpenHarmony南向開發案例:【分布式畫板】

    使用OpenHarmony3.1-Release開發的應用。通過OpenHarmony分布式技術,使多人能夠一起畫畫。
    的頭像 發表于 04-12 14:40 ?559次閱讀
    <b class='flag-5'>OpenHarmony</b>南向<b class='flag-5'>開發案</b>例:【<b class='flag-5'>分布式</b>畫板】

    HarmonyOS應用開發-分布式設計

    不同終端設備之間的極速連接、硬件協同、資源共享,為用戶提供最佳的場景體驗。分布式設計指南可以幫助應用開發者了解如何充分發揮“One Super Device”的能力,提供獨特的跨設備交互體驗。說明:本設計指南后續舉例中將包括手機、智慧屏、手表等多種設備,其中手機均指 EM
    發表于 09-22 17:11

    OpenHarmony 2.2 Beta2 版本發布,具備典型的分布式能力和媒體類產品開發能力

    。OpenHarmony 具備了典型的分布式能力和媒體類產品開發能力。即日起,全球開發者可通過 Gitee 和鏡像站點下載完整代碼(https://gitee.com/
    發表于 08-09 15:15

    OpenHarmony分布式軟總線流程分析

    OpenHarmony分布式軟總線流程分析,大神總結,大家可以下載去學習了~.~
    發表于 11-19 15:56

    基于潤和DAYU200開發套件的OpenHarmony分布式音樂播放

    :參考DevEco Studio(OpenHarmony)使用指南搭建OpenHarmony應用開發環境、并導入本工程進行編譯、運行。運行結果截圖:【分布式流轉體驗】硬件準備:準備兩臺
    發表于 03-14 09:07

    OpenHarmony標準設備應用開發(三)——分布式數據管理

    (以下內容來自開發者分享,不代表 OpenHarmony 項目群工作委員會觀點)邢碌上一章,我們通過分布式音樂播放、分布式***、
    發表于 04-07 18:48

    OpenHarmony3.1分布式技術資料合集

    客戶端(ScreenClient):屏幕圖像顯示代理客戶端,用于在設備上顯示其他設備投射過來的屏幕圖像數據。3、OpenHarmony3.1的分布式手寫板1.介紹基于TS擴展的聲明開發
    發表于 04-11 11:50

    OpenHarmony開發之Ability架構

    ][分布式手寫板(eTS)][分布式鑒權(JS)][分布式游戲手柄(eTS)][分布式郵件(eTS)][分布式親子早教系統(eTS)][
    發表于 05-12 15:12

    DAYU200 | 分布式遙控器

    遙控器將手機的輸入能力和電視遙控器遙控能力結合為一體,從而快速便捷操控電視。分布式遙控器的實現基于Op
    發表于 05-25 15:47

    【學習打卡】OpenHarmony分布式任務調度

    之前我們分享過分布式軟總線和分布式數據管理,今天主要說一下OpenHarmony分布式任務調度,分布式任務調度是建立在
    發表于 07-18 17:06

    開發樣例】OpenHarmony分布式購物車

    設計OpenHarmony技術特性eTS UI分布式調度分布式數據管理3.支持OpenHarmony版本OpenHarmony 3.0 LT
    發表于 07-29 14:17

    OpenHarmony 分布式硬件關鍵技術

    的視頻會議;在影音娛樂場景下,能夠輕松地把手機音視頻放到電視和音箱上播放,還可以讓家里的燈光自動跟隨電影和音樂進行變化,實現非常震撼的家庭影院的效果。 期待越來越多的開發者參與OpenHarmony的生態中來,共同研究和探討分布式
    發表于 08-24 17:25

    分布式系統硬件資源池原理和接入實踐

    提供更好的服務體驗。 圖 3 鴻蒙硬件資源池支持各類消費者場景 2.2 開發者場景 對于開發者來說,由于分布式硬件資源池將跨設備硬件調用的復雜度都封裝在了系統底層,跨設備硬件復用本地硬件的 API
    發表于 12-06 10:02

    基于OpenHarmony分布式應用開發框架使用教程

    電子發燒友網站提供《基于OpenHarmony分布式應用開發框架使用教程.zip》資料免費下載
    發表于 04-12 11:19 ?6次下載

    OpenHarmony知識賦能No.29-DAYU200分布式應用開發

    OpenHarmony標準系統北向開發高手。 ? 嘉賓介紹: 徐建國 資深技術專家(江蘇潤開鴻數字科技有限公司) ? 課程內容: 1.OpenHarmony分布式API介紹 a.
    的頭像 發表于 05-04 09:57 ?652次閱讀
    <b class='flag-5'>OpenHarmony</b>知識賦能No.29-DAYU200<b class='flag-5'>分布式</b>應用<b class='flag-5'>開發</b>
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>