96SEO 2026-02-20 04:58 0
设备连接同一无线网络#xff0c;安装分布式手写板应用。

进入应用#xff0c;点击允许使用多设备协同#xff0c;点击主页上查询…介绍
本篇Codelab使用设备管理及分布式键值数据库能力实现多设备之间手写板应用拉起及同步书写内容的功能。
操作流程
设备连接同一无线网络安装分布式手写板应用。
进入应用点击允许使用多设备协同点击主页上查询设备按钮显示附近设备。
选择设备确认若已建立连接启动对方设备上的手写板应用否则提示建立连接。
输入PIN码建立连接后再次点击查询设备按钮选择设备提交启动对方设备应用。
建立连接前绘制的内容在启动对方设备后同步此时设备上绘制的内容会在另一端同步绘制。
点击撤销按钮两侧设备绘制内容同步撤销。
[设备管理]模块提供分布式设备管理能力。
[分布式键值数据库]分布式键值数据库为应用程序提供不同设备间数据库的分布式协同能力。
本篇Codelab使用了设备管理及分布式键值数据库能力需要手动替换full-SDK并在配置文件module.json5文件requestPermissions属性中添加如下权限
[分布式设备认证组网权限]ohos.permission.ACCESS_SERVICE_DM。
[设备间的数据交换权限]ohos.permission.DISTRIBUTED_DATASYNC。
本篇Codelab部分能力依赖于系统API需下载full-SDK并替换DevEco
Studio自动下载的public-SDK。
本篇Codelab使用的部分API仅系统应用可用需要提升应用等级。
10。
鸿蒙指导参考qr23.cn/AKFP8k点击或者复制转到。
鸿蒙HarmonyOS与OpenHarmony文档籽料mau123789是v直接拿取
开发板类型[润和RK3568开发板]。
OpenHarmony系统4.0
完成本篇Codelab我们首先要完成开发环境的搭建本示例以RK3568开发板为例参照以下步骤进行
[获取OpenHarmony系统版本]标准系统解决方案二进制。
以4.0
Studio的安装和开发环境配置。
开发环境配置完成后请参考[使用工程向导]创建工程模板选择“Empty
本篇Codelab只对核心代码进行讲解对于完整代码我们会在gitee中提供。
主界面由导航栏及绘制区域组成导航栏包含撤回按钮及查询设备按钮。
绘制区域使用Canvas画布组件展示绘制效果。
Index.ets文件完成界面实现使用Column及Row容器组件进行布局。
撤回按钮Image($r(app.media.ic_back)).width($r(app.float.ic_back_width)).height($r(app.float.ic_back_height))...Blank()//
查找设备按钮Image($r(app.media.ic_hop)).width($r(app.float.ic_hop_width)).height($r(app.float.ic_hop_height))...}.width(CommonConstants.FULL_PERCENT).height(CommonConstants.TITLE_HEIGHT)Row()
绘制区域Canvas(this.canvasContext).width(CommonConstants.FULL_PERCENT).height(CommonConstants.FULL_PERCENT)...}....width(CommonConstants.FULL_PERCENT).layoutWeight(CommonConstants.NUMBER_ONE)}.height(CommonConstants.FULL_PERCENT).width(CommonConstants.FULL_PERCENT)}...
创建设备管理器。
设备管理器创建完成后注册设备上线离线监听信任设备上线离线时触发。
执行获取本地设备信息获取信任设备列表初始化展示设备列表等方法。
其中deviceManager类需使用full-SDK。
ohos.distributedHardware.deviceManager;class
创建设备管理器deviceManager.createDeviceManager(CommonConstants.BUNDLE_NAME,(error,
注册信任设备上线离线监听this.registerDeviceStateListener();//
获取本地设备信息this.getLocalDeviceInfo();//
获取信任设备列表this.getTrustedDeviceList();//
初始化展示设备列表this.initDeviceList();resolve(value);});}
{Logger.error(RemoteDeviceModel,createDeviceManager
error${JSON.stringify(error)});}});}...
}注册设备状态监听。
已验证设备上线或有新设备验证通过时状态类型为ONLINE将设备添加至信任设备列表。
设备离线时状态类型为OFFLINE将设备从信任列表中移除。
注册设备状态改变监听registerDeviceStateListener():
注册监听this.myDeviceManager.on(deviceStateChange,
deviceManager.DeviceStateChangeAction.ONLINE:
{this.deviceStateChangeActionOnline(data.device);break;}//
deviceManager.DeviceStateChangeAction.OFFLINE:
{this.deviceStateChangeActionOffline(data.device);break;}...}});}
{Logger.error(RemoteDeviceModel,registerDeviceStateListener
error${JSON.stringify(error)});}}//
设备上线加入信任列表及展示列表deviceStateChangeActionOnline(device:
{this.trustedDeviceList[this.trustedDeviceList.length]
device;this.addToDeviceList(device);}//
设备下线将设备移出信任列表和展示列表deviceStateChangeActionOffline(device:
(this.trustedDeviceList[i].networkId
{list.push(this.trustedDeviceList[i]);continue;}}this.deleteFromDeviceList(device);this.trustedDeviceList
点击主界面的查询设备按钮执行发现设备方法注册设备发现监听任务同时拉起弹窗展示设备列表。
当弹窗关闭时执行停止发现设备方法注销监听任务。
{Logger.info(RemoteDeviceModel,
exist${JSON.stringify(data)});return;}}this.discoverList[this.discoverList.length]
data.device;this.addToDeviceList(data.device);}startDeviceDiscovery():
注册发现设备监听this.myDeviceManager.on(deviceFound,
处理发现的设备this.deviceFound(data);});...let
CommonConstants.SUBSCRIBE_MODE,medium:
CommonConstants.SUBSCRIBE_MEDIUM,freq:
CommonConstants.SUBSCRIBE_FREQ,isSameAccount:
CommonConstants.SUBSCRIBE_CAPABILITY};//
发现周边设备this.myDeviceManager.startDeviceDiscovery(info);}
{Logger.error(RemoteDeviceModel,startDeviceDiscovery
error${JSON.stringify(error)});}}//
停止发现设备this.myDeviceManager.stopDeviceDiscovery(this.subscribeId);//
注销监听任务this.myDeviceManager.off(deviceFound);this.myDeviceManager.off(discoverFail);}
{Logger.error(RemoteDeviceModel,stopDeviceDiscovery
error${JSON.stringify(error)});}}...
若设备在信任设备列表执行startAbility()方法启动连接设备上的应用将当前的绘制信息作为参数发送至连接设备。
若设备不是信任设备执行authenticateDevice()方法启动验证。
此时连接设备提示是否接受接收连接后连接设备展示PIN码本地设备输入PIN码确认后连接成功。
再次点击查询设备按钮选择已连接设备点击确认启动连接设备上的应用。
设备验证authenticateDevice(context:
common.UIAbilityContext,device:
deviceManager.DeviceInfo,positionList:
this.trustedDeviceList.filter((item:
执行设备认证启动验证相关弹窗接受信任显示PIN码输入PIN码等this.myDeviceManager.authenticateDevice(device,
{Logger.error(RemoteDeviceModel,authenticateDevice
error${JSON.stringify(error)});}}//
启动连接设备上的应用startAbility(context:
启动连接设备上的应用context.startAbility(wantValue).then(()
{Logger.info(RemoteDeviceModel,
wantValue${JSON.stringify(wantValue)});}).catch((error:
{Logger.error(RemoteDeviceModel,
error${JSON.stringify(error)});})}...
程序关闭时注销设备状态监听任务并释放DeviceManager实例。
注销监听任务unregisterDeviceListCallback():
注销设备状态监听this.myDeviceManager.off(deviceStateChange);//
释放DeviceManager实例this.myDeviceManager.release();}
{Logger.error(RemoteDeviceModel,unregisterDeviceListCallback
error${JSON.stringify(err)});}}...
Canvas组件区域监听触摸事件按照按下、移动、抬起等触摸事件记录绘制的起点、中间点以及终点。
触摸事件触发时使用CanvasRenderingContext2D对象的绘制方法根据位置信息进行绘制。
绘制结束后将当前位置信息列表存入分布式键值数据库。
{Canvas(this.canvasContext)...}.onTouch((event:
{this.onTouchEvent(event);})...}...}//
{this.canvasContext.beginPath();this.canvasContext.lineWidth
CommonConstants.CANVAS_LINE_WIDTH;this.canvasContext.lineJoin
CommonConstants.CANVAS_LINE_JOIN;this.canvasContext.moveTo(positionX,
{this.canvasContext.lineTo(positionX,
positionY);this.pushData(false,
{this.canvasContext.lineTo(positionX,
positionY);this.canvasContext.stroke();this.pushData(false,
{break;}}}pushData(isFirstPosition:
存入位置信息列表this.positionList.push(position);if
当前位置为终点时将位置信息列表存入分布式键值数据库this.kvStoreModel.put(CommonConstants.CHANGE_POSITION,
JSON.stringify(this.positionList));}}...
}点击撤销按钮时从位置列表中后序遍历移除位置信息直到找到轨迹的初始位置完成移除上一次绘制的轨迹。
移除完成后将位置信息列表存入分布式键值数据库中。
执行redraw()方法清空画板上的内容遍历位置信息列表重新绘制。
{...LocalStorageProp(positionList)
撤销按钮Image($r(app.media.ic_back)).width($r(app.float.ic_back_width)).height($r(app.float.ic_back_height)).margin({
CommonConstants.ICON_MARGIN_LEFT
{this.goBack();})...}.width(CommonConstants.FULL_PERCENT).height(CommonConstants.TITLE_HEIGHT)...}...redraw():
删除画布内的绘制内容this.canvasContext.clearRect(0,
使用当前记录的位置信息重新绘制this.positionList.forEach((position)
{this.canvasContext.beginPath();this.canvasContext.lineWidth
CommonConstants.CANVAS_LINE_WIDTH;this.canvasContext.lineJoin
CommonConstants.CANVAS_LINE_JOIN;this.canvasContext.moveTo(position.positionX,
{this.canvasContext.lineTo(position.positionX,
{this.canvasContext.stroke();}}});}//
{break;}}this.redraw();this.kvStoreModel.put(CommonConstants.CHANGE_POSITION,
JSON.stringify(this.positionList));}...
使用分布式键值数据库需申请数据交换权限ohos.permission.DISTRIBUTED_DATASYNC。
应用启动时创建分布式键值数据库设置数据库数据改变监听。
数据改变时执行回调获取插入或更新数据列表遍历列表匹配位置信息列表的设置key更新位置列表后重新绘制。
KvStoreModel();...aboutToAppear()
{...this.createKVStore();}...createKVStore():
创建分布式键值数据库this.kvStoreModel.createKvStore(this.context,
distributedKVStore.ChangeNotification)
使用分布式键值数据库内的内容重置位置信息列表this.positionList
data.updateEntries;entries.forEach((entry:
(CommonConstants.CHANGE_POSITION
位置信息列表更新后重新绘制this.redraw();}});});}...
}创建分布式键值数据库。
设置数据库类型为KVStoreType.SINGLE_VERSION单版本数据库其他配置参考[创建数据库配置信息]。
创建数据库成功后调用enableSync()方法开启同步调用setDataChangeListener()方法订阅数据变更通知。
distributedKVStore.SingleKVStore;...createKvStore(context:
common.UIAbilityContext,callback:
distributedKVStore.ChangeNotification)
创建一个KVManager对象实例用于管理数据库对象this.kvManager
distributedKVStore.createKVManager(config);}
{Logger.error(KvStoreModel,createKvStore
err${JSON.stringify(error)});return;}//
distributedKVStore.KVStoreType.SINGLE_VERSION...};//
获取分布式键值数据库this.kvManager.getKVStore(CommonConstants.KVSTORE_ID,
distributedKVStore.SingleKVStore)
开启同步this.kvStore.enableSync(true).then(()
{Logger.error(KvStoreModel,createKvStore
error${JSON.stringify(error)});});this.setDataChangeListener(callback);}).catch((error:
{Logger.error(getKVStore,createKvStore
error${JSON.stringify(error)});})}...
}订阅数据变更通知。
创建分布式键值数据库设置数据变更订阅订阅类型为全部当更新数据集或插入数据集大于0时执行传入的callback()方法。
distributedKVStore.SingleKVStore;...setDataChangeListener(callback:
distributedKVStore.ChangeNotification)
订阅数据变更通知this.kvStore.on(dataChange,
distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL,(data:
distributedKVStore.ChangeNotification)
{Logger.error(KvStoreModel,setDataChangeListener
err${JSON.stringify(error)});}}...
KvStoreModel();...aboutToDisappear()
{this.kvStoreModel.removeDataChangeListener();}...
distributedKVStore.SingleKVStore;...removeDataChangeListener():
取消数据改变监听this.kvStore.off(dataChange);}
{Logger.error(KvStoreModel,removeDataChangeListener
err${JSON.stringify(error)});}}...
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback