HarmonyOS Sample 之 Pasteboard 分布式粘貼板
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
一、介紹
HarmonyOS提供系統(tǒng)剪貼板服務的操作接口,支持用戶程序從系統(tǒng)剪貼板中讀取、寫入和查詢剪貼板數(shù)據(jù),以及添加、移除系統(tǒng)剪貼板數(shù)據(jù)變化的回調(diào)。
設備內(nèi):
用戶通過系統(tǒng)剪貼板服務,可實現(xiàn)應用之間的簡單數(shù)據(jù)傳遞。例如:在應用A中復制的數(shù)據(jù),可以在應用B中粘貼,反之亦可。
設備間:
在分布式粘貼板場景中,粘貼的數(shù)據(jù)可以跨設備寫入。例如,設備A上的應用程序使用系統(tǒng)粘貼板接口將從設備A復制的數(shù)據(jù)通過IDL接口存儲到設備B的系統(tǒng)粘貼板中。如果數(shù)據(jù)允許,設備B上的應用程序可以讀取并粘貼系統(tǒng)粘貼板中的復制數(shù)據(jù)。實現(xiàn)設備之間粘貼板的分布式協(xié)同。
基于以上理解,實現(xiàn)一個分布式粘貼板應用程序,應用程序分為客戶端(copy)和服務端(paste)兩部分,通過idl實現(xiàn)數(shù)據(jù)傳遞。
客戶端負責數(shù)據(jù)采集,服務端負責數(shù)據(jù)的展示和應用,客戶端和服務端可以安裝在同一臺設備中,也可以安裝在不同的設備中,服務端也可以按照在多臺設備中,服務端通過分布式數(shù)據(jù)庫實現(xiàn)粘貼板數(shù)據(jù)的自動同步。
二、效果展示


三、搭建環(huán)境
安裝DevEco Studio,詳情請參考DevEco Studio下載。
設置DevEco Studio開發(fā)環(huán)境,DevEco Studio開發(fā)環(huán)境需要依賴于網(wǎng)絡環(huán)境,需要連接上網(wǎng)絡才能確保工具的正常使用,可以根據(jù)如下兩種情況來配置開發(fā)環(huán)境:
如果可以直接訪問Internet,只需進行下載HarmonyOS SDK操作。
如果網(wǎng)絡不能直接訪問Internet,需要通過代理服務器才可以訪問,請參考配置開發(fā)環(huán)境。
下載源碼后,使用DevEco Studio 打開項目,模擬器運行即可。
真機運行需要將config.json中的buddleName修改為自己的,如果沒有請到AGC上進行配置,參見 使用模擬器進行調(diào)試 。
四、項目結(jié)構(gòu)


五、代碼講解
5.1 系統(tǒng)粘貼板基礎功能介紹
系統(tǒng)粘貼板對象介紹
1.SystemPasteboard //系統(tǒng)粘貼板對象,定義系統(tǒng)粘貼板操作,包括復制、粘貼和設置粘貼板內(nèi)容更改的偵聽器。
2.PasteData//表示粘貼板上的粘貼數(shù)據(jù)。
3.PasteData.DataProperty //該類定義了系統(tǒng)粘貼板上 PasteData 的屬性,包括時間戳、MIME 類型和其他屬性數(shù)據(jù)。
4.PasteData.Record//該類將單個粘貼的數(shù)據(jù)定義為 Record,它可以是純文本、HTML 文本、URI 和意圖。 PasteData 對象包含一個或多個記錄。
客戶端(copy)CopyAbilitySlice.java
獲取系統(tǒng)粘貼板,監(jiān)聽粘貼板數(shù)據(jù)變化
- /**
- * 獲取系統(tǒng)粘貼板
- * 監(jiān)聽粘貼板數(shù)據(jù)變化
- */
- private void initPasteboard() {
- HiLog.debug(LABEL, "initPasteboard");
- //獲取系統(tǒng)粘貼板對象
- pasteboard = SystemPasteboard.getSystemPasteboard(this);
- //監(jiān)聽粘貼板數(shù)據(jù)變化
- pasteboard.addPasteDataChangedListener(() -> {
- if (pasteboard.hasPasteData()) {
- sync_text = getPasteData();
- HiLog.debug(LABEL, "%{public}s", "pasteStr:" + sync_text);
- }
- });
- }
獲取粘貼板內(nèi)容
- /**
- * 獲取粘貼板記錄
- *
- * @return
- */
- private String getPasteData() {
- HiLog.debug(LABEL, "getPasteData");
- String result = "";
- //粘貼板數(shù)據(jù)對象
- PasteData pasteData = pasteboard.getPasteData();
- if (pasteData == null) {
- return result;
- }
- PasteData.DataProperty dataProperty = pasteData.getProperty();
- //
- boolean hasHtml = dataProperty.hasMimeType(PasteData.MIMETYPE_TEXT_HTML);
- boolean hasText = dataProperty.hasMimeType(PasteData.MIMETYPE_TEXT_PLAIN);
- //數(shù)據(jù)格式類型
- if (hasHtml || hasText) {
- for (int i = 0; i < pasteData.getRecordCount(); i++) {
- //粘貼板數(shù)據(jù)記錄
- PasteData.Record record = pasteData.getRecordAt(i);
- //不同類型獲取方式不同
- String mimeType = record.getMimeType();
- //HTML文本
- if (mimeType.equals(PasteData.MIMETYPE_TEXT_HTML)) {
- result = record.getHtmlText();
- //純文本
- } else if (mimeType.equals(PasteData.MIMETYPE_TEXT_PLAIN)) {
- result = record.getPlainText().toString();
- //
- } else {
- HiLog.info(LABEL, "%{public}s", "getPasteData mimeType :" + mimeType);
- }
- }
- }
- return result;
- }
設置文本到粘貼板中
- /**
- * 設置文本到粘貼板
- *
- * @param component
- */
- private void setTextToPaste(Component component) {
- HiLog.info(LABEL, "setTextToPaste");
- if (pasteboard != null) {
- String text = syncText.getText();
- if (text.isEmpty()) {
- showTips(this, "請?zhí)顚憙?nèi)容");
- return;
- }
- //把記錄添加到粘貼板
- PasteData pasteData= PasteData.creatPlainTextData(text);
- //設置文本到粘貼板
- pasteboard.setPasteData(pasteData);
- showTips(this, "復制成功");
- HiLog.info(LABEL, "setTextToPaste succeeded");
- }
- }
清空粘貼板
- /**
- * 清空粘貼板
- *
- * @param component
- */
- private void clearPasteboard(Component component) {
- if (pasteboard != null) {
- pasteboard.clear();
- showTips(this, "Clear succeeded");
- }
- }
5.2 分布式粘貼板應用構(gòu)建思路介紹

選擇遠端連接設備
本實例是通過新增加一個DevicesSelectAbility來實現(xiàn)的。
- private void showDevicesDialog() {
- Intent intent = new Intent();
- //打開選擇設備的Ability頁面DevicesSelectAbility
- Operation operation =
- new Intent.OperationBuilder()
- .withDeviceId("")
- .withBundleName(getBundleName())
- .withAbilityName(DevicesSelectAbility.class)
- .build();
- intent.setOperation(operation);
- //攜帶一個設備選擇請求標識,打開設備選擇頁面(DevicesSelectAbility) TODO
- startAbilityForResult(intent, Constants.PRESENT_SELECT_DEVICES_REQUEST_CODE);
- }
- /**
- * 打開設備選擇Ability后,選擇連接的設備執(zhí)行setResult后觸發(fā)
- *
- * @param requestCode
- * @param resultCode
- * @param resultIntent
- */
- @Override
- protected void onAbilityResult(int requestCode, int resultCode, Intent resultIntent) {
- HiLog.debug(LABEL, "onAbilityResult");
- if (requestCode == Constants.PRESENT_SELECT_DEVICES_REQUEST_CODE && resultIntent != null) {
- //獲取用戶選擇的設備
- String devicesId = resultIntent.getStringParam(Constants.PARAM_DEVICE_ID);
- //連接粘貼板服務端
- connectService(devicesId);
- return;
- }
- }
連接粘貼板服務端ServiceAbility服務
idl文件放在ohos.samples.pasteboard.paste目錄下,Gradl窗口,執(zhí)行compileDebugIdl 后,系統(tǒng)生成代理對象。
- interface ohos.samples.pasteboard.paste.ISharePasteAgent {
- /*
- * 設置系統(tǒng)粘貼板
- */
- void setSystemPaste([in] String param);
- }
連接服務端ServiceAbility,如果組網(wǎng)中沒有其他設備就連接本地的服務端。
連接成功后,初始化idl的SharePasteAgentProxy代理,用于下一步的同步數(shù)據(jù)。
- //idl共享粘貼板代理
- private SharePasteAgentProxy remoteAgentProxy;
- /**
- * 連接粘貼板服務中心
- */
- private void connectService(String deviceId) {
- HiLog.debug(LABEL, "%{public}s", "connectService");
- if (!isConnect) {
- boolean isConnectRemote = deviceId != null;
- //三元表達式,判斷連接本地還是遠端Service
- Intent intent = isConnectRemote
- ? getRemoteServiceIntent(REMOTE_BUNDLE, REMOTE_SERVICE, deviceId)
- : getLocalServiceIntent(REMOTE_BUNDLE, REMOTE_SERVICE);
- HiLog.debug(LABEL, "%{public}s", "intent:" + intent);
- //連接 Service
- connectAbility(intent, new IAbilityConnection() {
- @Override
- public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) {
- //發(fā)個通知,Service 連接成功了
- eventHandler.sendEvent(EVENT_ABILITY_CONNECT_DONE);
- //初始化代理
- remoteAgentProxy = new SharePasteAgentProxy(iRemoteObject);
- HiLog.debug(LABEL, "%{public}s", "remoteAgentProxy:" + remoteAgentProxy);
- }
- @Override
- public void onAbilityDisconnectDone(ElementName elementName, int resultCode) {
- //發(fā)個通知,Service 斷開連接了,主動斷開不會執(zhí)行,關閉服務端會執(zhí)行
- eventHandler.sendEvent(EVENT_ABILITY_DISCONNECT_DONE);
- }
- });
- }
- }
- /**
- * 獲取遠端粘貼板服務中心
- *
- * @param bundleName
- * @param serviceName
- * @return
- */
- private Intent getRemoteServiceIntent(String bundleName, String serviceName, String deviceId) {
- HiLog.debug(LABEL, "%{public}s", "getRemoteServiceIntent");
- Operation operation = new Intent.OperationBuilder()
- .withDeviceId(deviceId)
- .withBundleName(bundleName)
- .withAbilityName(serviceName)
- //重要
- .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)
- .build();
- Intent intent = new Intent();
- intent.setOperation(operation);
- return intent;
- }
- /**
- * 獲取本地粘貼板服務中心
- *
- * @param bundleName
- * @param serviceName
- * @return
- */
- private Intent getLocalServiceIntent(String bundleName, String serviceName) {
- HiLog.debug(LABEL, "%{public}s", "getLocalServiceIntent");
- Operation operation = new Intent.OperationBuilder().withDeviceId("")
- .withBundleName(bundleName)
- .withAbilityName(serviceName)
- .build();
- Intent intent = new Intent();
- intent.setOperation(operation);
- return intent;
- }
同步數(shù)據(jù)到服務端
- /**
- * 同步粘貼板記錄到粘貼板服務中心
- *
- * @param component
- */
- private void syncData(Component component) {
- HiLog.debug(LABEL, "sync_text:" + sync_text);
- if (!sync_text.isEmpty()) {
- if (isConnect && remoteAgentProxy != null) {
- //調(diào)用服務端IPC方法
- try {
- remoteAgentProxy.setSystemPaste(sync_text);
- //更換文本
- syncText.setText(getRandomText());
- sync_text = "";
- showTips(this, "同步成功");
- } catch (RemoteException remoteException) {
- remoteException.printStackTrace();
- }
- } else {
- showTips(this, "正在連接設備");
- }
- } else {
- showTips(this, "點擊復制到粘貼板");
- }
- }
隨機生成粘貼文本
- /**
- * 隨機文本,模擬數(shù)據(jù)
- *
- * @return
- */
- public String getRandomText() {
- List<String> list = Arrays.asList(
- "快馬加鞭未下鞍,離天三尺三",
- "我自橫刀向天笑,去留肝膽兩昆侖",
- "飛流直下三千尺,疑是銀河落九天",
- "君子求諸己,小人求諸人",
- "吾日三省吾身:為人謀而不忠乎?與朋友交而不信乎?傳不習乎?");
- int random = new SecureRandom().nextInt(list.size());
- return list.get(random);
- }
服務端(paste)ServiceAbility.java
設置粘貼板服務
idl文件放在ohos.samples.pasteboard.paste目錄下,Gradl窗口,執(zhí)行compileDebugIdl 后,系統(tǒng)生成代理對象,idl提供了setSystemPaste接口供遠端調(diào)用。
- interface ohos.samples.pasteboard.paste.ISharePasteAgent {
- /*
- * 設置系統(tǒng)粘貼板
- */
- void setSystemPaste([in] String param);
- }
- //idl的服務端實現(xiàn),
- SharePasteAgentStub sharePasteAgentStub = new SharePasteAgentStub(DESCRIPTOR) {
- @Override
- public void setSystemPaste(String param) {
- HiLog.info(LABEL, "%{public}s", "param:" + param);
- //插入數(shù)據(jù)庫
- ItemChild itemChild = new ItemChild();
- String currentTime = DateUtils.getCurrentDate("yyMMdd HH:mm:ss");
- itemChild.setWriteTime(currentTime);
- itemChild.setWriteContent(param);
- itemChild.setIndex(String.valueOf(UUID.randomUUID()));
- //默認添加到未分類
- itemChild.setTagName(Const.CATEGORY_TAG_UNCATEGOORIZED);
- //添加粘貼板記錄到分布式數(shù)據(jù)庫
- kvManagerUtils.addItemChild(itemChild);
- }
- };
- @Override
- protected IRemoteObject onConnect(Intent intent) {
- HiLog.info(LABEL, "%{public}s", "ServiceAbility onConnect");
- return sharePasteAgentStub;
- }
- **初始化數(shù)據(jù)庫**
- ```java
- //初始化數(shù)據(jù)庫工具
- kvManagerUtils = KvManagerUtils.getInstance(this);
- //初始化數(shù)據(jù)庫管理對象
- kvManagerUtils.initDbManager(eventHandler);
- //初始化數(shù)據(jù)庫數(shù)據(jù)按鈕
- Image initDb = (Image) findComponentById(ResourceTable.Id_init_db);
- initDb.setClickedListener(component -> {
- //默認選中“未定義”標簽
- current_select_category_index = 0;
- //初始化數(shù)據(jù)庫數(shù)據(jù)
- kvManagerUtils.initDbData();
- showTip("初始化完成");
- });
初始化數(shù)據(jù)列表
- /**
- * 從分布式數(shù)據(jù)庫中查詢數(shù)據(jù)
- */
- public void queryData() {
- HiLog.debug(LABEL, "queryData");
- try {
- //加載選中類別下的數(shù)據(jù)列表
- initItemChild(kvManagerUtils.queryDataByTag(CategoryData.tagList.get(current_select_category_index)));
- } catch (KvStoreException exception) {
- HiLog.info(LABEL, "the value must be String");
- }
- }
- /**
- * 初始化選中標簽的子項列表
- *
- * @param itemChildList itemChildList, the bean of itemChild
- */
- private void initItemChild(List<ItemChild> itemChildList) {
- HiLog.debug(LABEL, "initItemChild:" + itemChildList);
- if (itemChildList == null) {
- return;
- }
- //清空組件
- itemChildLayout.removeAllComponents();
- // Create itemChild
- for (ItemChild itemChild : itemChildList) {
- //獲取子項類別所在的組件
- Component childComponent =
- LayoutScatter.getInstance(this).parse(ResourceTable.Layout_paste_record_per, null, false);
- //寫入時間
- Text writeTime = (Text) childComponent.findComponentById(ResourceTable.Id_writeTime);
- writeTime.setText(itemChild.getWriteTime());
- //粘貼板內(nèi)容
- Text writeContent = (Text) childComponent.findComponentById(ResourceTable.Id_writeContent);
- writeContent.setText(itemChild.getWriteContent());
- //復制按鈕
- Text copy = (Text) childComponent.findComponentById(ResourceTable.Id_itemChildPerCopy);
- //復制按鈕的監(jiān)聽事件
- copy.setClickedListener(component -> {
- //復制內(nèi)容到粘貼板
- pasteboard.setPasteData(PasteData.creatPlainTextData(itemChild.getWriteContent()));
- showTip("已復制到粘貼板");
- });
- //收藏按鈕
- Text favorite = (Text) childComponent.findComponentById(ResourceTable.Id_itemChildPerFavorite);
- //收藏按鈕的監(jiān)聽事件
- favorite.setClickedListener(component -> {
- //修改標簽微已收藏
- itemChild.setTagName(Const.CATEGORY_TAG_FAVORITED);
- //保存數(shù)據(jù)
- kvManagerUtils.addItemChild(itemChild);
- showTip("已加入到收藏中");
- });
- /**************just for test********************/
- //復選框
- Checkbox noteId = (Checkbox) childComponent.findComponentById(ResourceTable.Id_noteId);
- //子項列表的點擊事件
- childComponent.setClickedListener(component -> {
- if (noteId.getVisibility() == Component.VISIBLE) {
- noteId.setChecked(!noteId.isChecked());
- }
- });
- //子項列表的長按事件,長按顯示復選框
- childComponent.setLongClickedListener(component -> {
- //checkbox顯示
- noteId.setVisibility(Component.VISIBLE);
- //設置復選框樣式,以及其他文本組件的縮進
- Element element = ElementScatter.getInstance(getContext()).parse(ResourceTable.Graphic_check_box_checked);
- noteId.setBackground(element);
- noteId.setChecked(true);
- writeTime.setMarginLeft(80);
- writeContent.setMarginLeft(80);
- });
- //復選框的狀態(tài)變化監(jiān)聽事件,state表示是否被選中
- noteId.setCheckedStateChangedListener((component, state) -> {
- // 狀態(tài)改變的邏輯
- Element element;
- if (state) {
- //設置選中的樣式
- element = ElementScatter.getInstance(getContext())
- .parse(ResourceTable.Graphic_check_box_checked);
- } else {
- //設置未選中的樣式
- element = ElementScatter.getInstance(getContext())
- .parse(ResourceTable.Graphic_check_box_uncheck);
- }
- noteId.setBackground(element);
- });
- /**************just for test********************/
- //添加子項列表組件到布局
- itemChildLayout.addComponent(childComponent);
- }
- }
標簽分類顯示
- //初始化列表列表的點擊的監(jiān)聽事件
- categoryList.setItemClickedListener(
- (listContainer, component, index, l1) -> {
- //點的就是當前類別
- if (categoryListProvider.getSelectIndex() == index) {
- return;
- }
- //切換類別索引
- categoryListProvider.setSelectIndex(index);
- //設置選中的標簽索引
- current_select_category_index = index;
- //獲取當前選中的標簽名稱
- String tagName = CategoryData.tagList.get(index);
- //從數(shù)據(jù)庫中查詢標簽子項列表
- initItemChild(kvManagerUtils.queryDataByTagAndKewWord(searchTextField.getText(), tagName));
- //通知數(shù)據(jù)更新
- categoryListProvider.notifyDataChanged();
- //滾動條到最頂部
- itemListScroll.fluentScrollYTo(0);
- });
搜索粘貼記錄
- //搜索key監(jiān)聽事件
- searchTextField.setKeyEventListener(
- (component, keyEvent) -> {
- if (keyEvent.isKeyDown() && keyEvent.getKeyCode() == KeyEvent.KEY_ENTER) {
- //獲取當前選中的標簽名稱
- String tagName = CategoryData.tagList.get(current_select_category_index);
- List<ItemChild> itemChildList = kvManagerUtils.queryDataByTagAndKewWord(searchTextField.getText(), tagName);
- //從數(shù)據(jù)庫中查詢標簽子項列表
- initItemChild(itemChildList);
- //通知數(shù)據(jù)更新
- categoryListProvider.notifyDataChanged();
- //滾動條到最頂部
- itemListScroll.fluentScrollYTo(0);
- }
- return false;
- });
分布式數(shù)據(jù)庫工具KvManagerUtils.java
數(shù)據(jù)變化通知
提供了分布式數(shù)據(jù)庫管理工具KvManagerUtils.java,數(shù)據(jù)庫操作都集中在這里了。
為了在數(shù)據(jù)庫數(shù)據(jù)發(fā)生變化時能及時更新頁面顯示,頁面在初始化數(shù)據(jù)庫時,傳遞eventHandler對象,這樣在數(shù)據(jù)庫變化是可以通知到頁面。
- /**
- * 訂閱數(shù)據(jù)庫更改通知
- * @param singleKvStore Data operation
- */
- private void subscribeDb(SingleKvStore singleKvStore) {
- HiLog.info(LABEL, "subscribeDb");
- //數(shù)據(jù)庫觀察者客戶端
- KvStoreObserver kvStoreObserverClient = new KvStoreObserverClient();
- //訂閱遠程數(shù)據(jù)更改
- singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_REMOTE, kvStoreObserverClient);
- }
- /**
- * 自定義分布式數(shù)據(jù)庫觀察者客戶端
- * 數(shù)據(jù)發(fā)生變化時觸發(fā)對應函數(shù)
- * Receive database messages
- */
- private class KvStoreObserverClient implements KvStoreObserver {
- @Override
- public void onChange(ChangeNotification notification) {
- HiLog.error(LABEL, "onChange");
- eventHandler.sendEvent(Const.DB_CHANGE_MESS);
- }
- }
數(shù)據(jù)自動同步
默認開啟自動同步
- /**
- * Initializing Database Management
- * 初始化數(shù)據(jù)庫管理員
- */
- public void initDbManager(EventHandler eventHandler) {
- this.eventHandler = eventHandler;
- HiLog.info(LABEL, "initDbManager");
- if (singleKvStore == null || kvManager == null) {
- HiLog.info(LABEL, "initDbData");
- //創(chuàng)建數(shù)據(jù)庫管理員
- kvManager = createManager();
- //創(chuàng)建數(shù)據(jù)庫
- singleKvStore = createDb(kvManager);
- subscribeDb(singleKvStore);
- }
- }
- /**
- * Create a distributed database manager instance
- * 創(chuàng)建數(shù)據(jù)庫管理員
- *
- * @return database manager
- */
- private KvManager createManager() {
- HiLog.info(LABEL, "createManager");
- KvManager manager = null;
- try {
- //
- KvManagerConfig config = new KvManagerConfig(context);
- manager = KvManagerFactory.getInstance().createKvManager(config);
- } catch (KvStoreException exception) {
- HiLog.error(LABEL, "some exception happen");
- }
- return manager;
- }
- /**
- * Creating a Single-Version Distributed Database
- * 創(chuàng)建數(shù)據(jù)庫
- *
- * @param kvManager Database management
- * @return SingleKvStore
- */
- private SingleKvStore createDb(KvManager kvManager) {
- HiLog.info(LABEL, "createDb");
- SingleKvStore kvStore = null;
- try {
- Options options = new Options();
- //單版本數(shù)據(jù)庫,不加密,沒有可用的 KvStore 數(shù)據(jù)庫就創(chuàng)建
- //單版本分布式數(shù)據(jù)庫,默認開啟組網(wǎng)設備間自動同步功能,
- //如果應用對性能比較敏感建議設置關閉自動同步功能setAutoSync(false),主動調(diào)用sync接口同步。
- options.setCreateIfMissing(true)
- .setEncrypt(false)
- .setKvStoreType(KvStoreType.SINGLE_VERSION);
- //創(chuàng)建數(shù)據(jù)庫
- kvStore = kvManager.getKvStore(options, STORE_ID);
- } catch (KvStoreException exception) {
- HiLog.error(LABEL, "some exception happen");
- }
- return kvStore;
- }
權(quán)限config.json
- "reqPermissions": [
- {
- "name": "ohos.permission.DISTRIBUTED_DATASYNC",
- "reason": "同步粘貼板數(shù)據(jù)",
- "usedScene": {
- "when": "inuse",
- "ability": [
- "ohos.samples.pasteboard.paste.MainAbility",
- "ohos.samples.pasteboard.paste.ServiceAbility"
- ]
- }
- },
- {
- "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
- },
- {
- "name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
- }
- ]
六、思考總結(jié)
1.粘貼板板傳遞數(shù)據(jù)可能會存在安全問題,需要注意,要根據(jù)具體場景來使用。
設備內(nèi)每次傳輸?shù)恼迟N數(shù)據(jù)大小不能超過 800 KB。每次設備間傳輸?shù)臄?shù)據(jù)不能超過64KB,且數(shù)據(jù)必須為文本格式。
2.idl的使用,在上述案例中,客戶端(copy) 和 服務端(paste) 項目idl下內(nèi)容完全一致即可。


七、完整代碼
附件可以直接下載
https://harmonyos.51cto.com/resource/1489
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)