鸿蒙跨端指南针:多设备实时同步方向数据 原创

进修的泡芙
发布于 2025-6-18 21:38
浏览
0收藏

鸿蒙跨端指南针:多设备实时同步方向数据

本文将基于HarmonyOS 5的传感器能力和分布式技术,实现一个支持多设备同步的指南针应用,能够在不同设备间实时同步设备方向数据。

技术架构
传感器层:使用方向传感器获取设备方向数据

数据处理层:计算并转换传感器数据为指南针角度

分布式同步层:通过分布式数据管理实现多设备数据同步

UI展示层:动态展示指南针方向和同步状态

完整代码实现
方向数据模型定义

// model/DirectionData.ts
export class DirectionData {
deviceId: string = ‘’; // 设备ID
azimuth: number = 0; // 方位角(0-360度)
pitch: number = 0; // 俯仰角(-180到180度)
roll: number = 0; // 滚动角(-90到90度)
timestamp: number = 0; // 时间戳
isPrimary: boolean = false; // 是否为主设备

constructor(data?: Partial<DirectionData>) {
if (data) {
Object.assign(this, data);
if (!this.timestamp) {
this.timestamp = Date.now();
}

}

传感器服务实现

// service/SensorService.ts
import sensor from ‘@ohos.sensor’;
import { DirectionData } from ‘…/model/DirectionData’;

export class SensorService {
private sensorId: number | null = null;
private callback: (data: DirectionData) => void;
private deviceId: string = ‘’;

constructor(callback: (data: DirectionData) => void, deviceId: string) {
this.callback = callback;
this.deviceId = deviceId;
// 开始监听方向传感器

startListening() {
try {
this.sensorId = sensor.on(sensor.SensorId.ORIENTATION, (data) => {
const directionData = new DirectionData({
deviceId: this.deviceId,
azimuth: data.azimuth,
pitch: data.pitch,
roll: data.roll
});
this.callback(directionData);
}, { interval: 100 }); // 100ms更新一次
catch (err) {

  console.error('启动传感器失败:', err);

}

// 停止监听
stopListening() {
if (this.sensorId !== null) {
sensor.off(sensor.SensorId.ORIENTATION, this.sensorId);
this.sensorId = null;
}

分布式方向同步服务

// service/DirectionSyncService.ts
import distributedData from ‘@ohos.data.distributedData’;
import deviceInfo from ‘@ohos.deviceInfo’;
import { DirectionData } from ‘…/model/DirectionData’;

const STORE_ID = ‘direction_sync_store’;
const DIRECTION_KEY = ‘current_direction’;

export class DirectionSyncService {
private kvManager: distributedData.KVManager;
private kvStore: distributedData.SingleKVStore;
private localDeviceId: string = deviceInfo.deviceId;
private isPrimaryDevice: boolean = false;

// 初始化分布式数据存储
async initialize() {
const config = {
bundleName: ‘com.example.compass’,
userInfo: {
userId: ‘compass_user’,
userType: distributedData.UserType.SAME_USER_ID
};

this.kvManager = distributedData.createKVManager(config);
const options = {
  createIfMissing: true,
  encrypt: false,
  backup: false,
  autoSync: true,
  kvStoreType: distributedData.KVStoreType.SINGLE_VERSION
};

this.kvStore = await this.kvManager.getKVStore(STORE_ID, options);

// 订阅数据变更
this.kvStore.on('dataChange', distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
  this.handleDataChange(data);
});

// 处理数据变更

private handleDataChange(data: distributedData.ChangeNotification) {
if (data.insertEntries.length > 0 && data.insertEntries[0].key === DIRECTION_KEY) {
const newDirection = JSON.parse(data.insertEntries[0].value.value);
AppStorage.setOrCreate(‘currentDirection’, new DirectionData(newDirection));
}

// 同步方向数据
async syncDirectionData(direction: DirectionData) {
direction.deviceId = this.localDeviceId;
direction.isPrimary = this.isPrimaryDevice;
await this.kvStore.put(DIRECTION_KEY, JSON.stringify(direction));
// 设置当前设备为主设备

setAsPrimaryDevice(isPrimary: boolean) {
this.isPrimaryDevice = isPrimary;
// 获取当前设备ID

getLocalDeviceId(): string {
return this.localDeviceId;
}

指南针页面实现

// pages/CompassPage.ets
import { SensorService } from ‘…/service/SensorService’;
import { DirectionSyncService } from ‘…/service/DirectionSyncService’;
import { DirectionData } from ‘…/model/DirectionData’;

@Entry
@Component
struct CompassPage {
private sensorService: SensorService;
private syncService: DirectionSyncService = new DirectionSyncService();
@StorageLink(‘currentDirection’) currentDirection: DirectionData = new DirectionData();
@State isSynced: boolean = false;
@State isPrimary: boolean = false;

async aboutToAppear() {
await this.syncService.initialize();
this.isSynced = true;

// 初始化传感器服务
this.sensorService = new SensorService(
  (data) => this.handleDirectionChange(data),
  this.syncService.getLocalDeviceId()
);

// 开始监听传感器
this.sensorService.startListening();

onPageHide() {

// 停止监听传感器
this.sensorService.stopListening();

build() {

Column() {
  // 指南针标题
  Text('指南针')
    .fontSize(24)
    .fontWeight(FontWeight.Bold)
    .margin({ top: 20, bottom: 20 })
  
  // 指南针主体
  Stack() {
    // 指南针底盘
    Image($r('app.media.compass_bg'))
      .width(300)
      .height(300)
    
    // 指南针指针(根据方位角旋转)
    Image($r('app.media.compass_needle'))
      .width(280)
      .height(280)
      .rotate({ angle: -this.currentDirection.azimuth })

.margin({ bottom: 30 })

  // 方向信息
  Column() {
    Text(方位角: ${this.currentDirection.azimuth.toFixed(1)}°)
      .fontSize(18)
      .margin({ bottom: 8 })
    
    Text(俯仰角: ${this.currentDirection.pitch.toFixed(1)}°)
      .fontSize(16)
      .margin({ bottom: 8 })
      .fontColor('#666666')
    
    Text(滚动角: ${this.currentDirection.roll.toFixed(1)}°)
      .fontSize(16)
      .margin({ bottom: 8 })
      .fontColor('#666666')

.margin({ bottom: 30 })

  // 设备角色控制
  Row() {
    Text(this.isPrimary ? '主设备' : '从设备')
      .fontSize(16)
      .layoutWeight(1)
    
    Toggle({ type: ToggleType.Switch, isOn: this.isPrimary })
      .onChange((isOn: boolean) => {
        this.isPrimary = isOn;
        this.syncService.setAsPrimaryDevice(isOn);
      })

.width(‘80%’)

  .margin({ bottom: 20 })

  // 同步状态
  Row() {
    Circle()
      .width(10)
      .height(10)
      .fill(this.isSynced ? '#4CAF50' : '#F44336')
      .margin({ right: 5 })
    
    Text(this.isSynced ? '已同步' : '同步中...')
      .fontSize(14)
      .fontColor('#666666')

// 数据来源提示

  if (this.currentDirection.deviceId && 
      this.currentDirection.deviceId !== this.syncService.getLocalDeviceId()) {
    Text(数据来源: ${this.currentDirection.deviceId})
      .fontSize(12)
      .fontColor('#888888')
      .margin({ top: 20 })

}

.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)

// 处理方向变化

private handleDirectionChange(data: DirectionData) {
// 只有主设备才同步数据,或者当前设备是主设备
if (this.isPrimary || !this.currentDirection.isPrimary) {
this.currentDirection = data;
this.syncService.syncDirectionData(data);
}

资源文件配置

// resources/base/profile/abilities.json
“abilities”: [

“name”: “CompassAbility”,

  "type": "page",
  "backgroundModes": ["sensor"],
  "permissions": [
    "ohos.permission.ACCELEROMETER",
    "ohos.permission.GYROSCOPE",
    "ohos.permission.DISTRIBUTED_DATASYNC"

}

}

实现原理详解
传感器数据获取:

使用@ohos.sensor模块监听设备方向传感器

获取方位角(azimuth)、俯仰角(pitch)和滚动角(roll)

设置合适的采样间隔(如100ms)
数据同步机制:

主设备负责同步方向数据到分布式数据库

从设备接收数据并更新本地UI

冲突解决策略:主设备数据优先
UI动态展示:

使用rotate属性实现指南针指针旋转

显示详细的角度数值

标识数据来源设备
权限管理:

申请加速度计和陀螺仪权限

申请分布式数据同步权限

扩展功能建议
方向校准功能:

  // 添加校准功能

async calibrateCompass() {
const result = await sensor.calibrate(sensor.SensorId.ORIENTATION);
if (result === sensor.CalibrationResult.SUCCESS) {
prompt.showToast({ message: ‘校准成功’, duration: 2000 });
}

方向历史记录:

  // 记录方向历史

async recordDirectionHistory(data: DirectionData) {
const historyKey = ‘direction_history’;
const history = await preferences.get(historyKey, []);
history.push({
azimuth: data.azimuth,
timestamp: data.timestamp
});
await preferences.put(historyKey, history.slice(-100)); // 保留最近100条记录

多设备方向对比:

  // 比较多设备方向差异

function compareDeviceDirections(device1: DirectionData, device2: DirectionData) {
const diff = Math.abs(device1.azimuth - device2.azimuth);
return Math.min(diff, 360 - diff); // 考虑360度循环

总结

本文展示了如何利用HarmonyOS的传感器和分布式能力构建一个多设备同步的指南针应用。通过方向传感器获取精确的设备方向数据,再通过分布式数据管理实现多设备间的实时同步,为用户提供了协同工作的指南针工具。

这种架构不仅适用于指南针应用,也可以扩展到水平仪、姿态检测等需要实时传感器数据同步的场景。合理利用鸿蒙的分布式能力,可以大大增强多设备协同应用的实用性和用户体验。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐