HarmonyOS鸿蒙Next实战开发-设备连接与认证

HarmonyOS鸿蒙Next实战开发-设备连接与认证 在鸿蒙分布式应用开发中,需要实现设备间的自动发现、认证和连接,以构建跨设备协同体验。开发者常遇到以下具体问题:

  • 发现机制分散:蓝牙、Wi-Fi P2P、局域网发现多种技术并存
  • 协议栈不统一:不同设备支持的连接协议有差异
  • 安全机制严格:分布式安全要求导致连接流程复杂

解决方案

环境配置

1. 确保开发环境配置正确

检查DevEco Studio版本

2. 创建鸿蒙项目

选择Application -> Empty Ability

模型选择:Stage

开发语言:ArkTS

API版本:9+

1.1 设备管理封装类

// DeviceManager.ts - 鸿蒙设备管理器
import deviceManager from '@ohos.distributedDeviceManager';
import { BusinessError } from '@ohos.base';
import { common } from '@kit.AbilityKit';

export class HarmonyDeviceManager {
  private deviceDiscovery: deviceManager.DeviceDiscovery | null = null;
  private deviceList: deviceManager.DeviceBasicInfo[] = [];
  private authCallback: deviceManager.AuthCallback | null = null;
  private connectionCallback: deviceManager.DeviceConnectCallback | null = null;
  
  // 初始化设备管理器
  async initDeviceManager(context: common.UIAbilityContext): Promise<void> {
    try {
      console.info('[DeviceManager] Initializing device manager...');
      
      // 创建设备管理器实例
      const manager = deviceManager.createDeviceManager(context.bundleName, {
        bundleName: context.bundleName,
        callback: (action: deviceManager.DeviceStateChangeAction, device: deviceManager.DeviceBasicInfo) => {
          this.handleDeviceStateChange(action, device);
        }
      });
      
      // 设置连接状态回调
      this.setupConnectionCallback();
      
      console.info('[DeviceManager] Initialization completed');
    } catch (error) {
      console.error('[DeviceManager] Initialization failed:', error);
    }
  }
  
  // 开始发现设备
  async startDiscovery(options?: deviceManager.DiscoveryOptions): Promise<void> {
    try {
      const defaultOptions: deviceManager.DiscoveryOptions = {
        discoveryMode: deviceManager.DiscoveryMode.DISCOVERY_MODE_ACTIVE,
        medium: deviceManager.ExchangeMedium.COAP,
        freq: deviceManager.ExchangeFreq.LOW,
        isActiveDiscover: true,
        ...options
      };
      
      this.deviceDiscovery = await deviceManager.startDeviceDiscovery(defaultOptions);
      
      // 监听设备发现事件
      this.deviceDiscovery.on('discoverSuccess', (device: deviceManager.DeviceBasicInfo) => {
        this.onDeviceDiscovered(device);
      });
      
      this.deviceDiscovery.on('discoverFail', (errorCode: number) => {
        console.error(`[DeviceManager] Discovery failed: ${errorCode}`);
      });
      
    } catch (error) {
      console.error('[DeviceManager] Start discovery failed:', error);
    }
  }
  
  // 设备发现回调
  private onDeviceDiscovered(device: deviceManager.DeviceBasicInfo): void {
    // 去重处理
    const existingIndex = this.deviceList.findIndex(d => d.deviceId === device.deviceId);
    
    if (existingIndex === -1) {
      this.deviceList.push(device);
      console.info(`[DeviceManager] New device discovered: ${device.deviceName} (${device.deviceId})`);
      
      // 触发设备更新事件
      this.emitDeviceListUpdated();
    }
  }
  
  // 连接设备
  async connectDevice(deviceId: string, authParam?: deviceManager.AuthParam): Promise<boolean> {
    try {
      console.info(`[DeviceManager] Connecting to device: ${deviceId}`);
      
      const authParam: deviceManager.AuthParam = {
        authType: deviceManager.AuthType.PIN_CODE,
        appIcon: '',
        appThumbnail: '',
        ...authParam
      };
      
      // 发起认证请求
      await deviceManager.authenticateDevice(authParam, {
        onSuccess: (data: { deviceId: string; pinCode?: string }) => {
          console.info(`[DeviceManager] Authentication success: ${data.deviceId}`);
          this.onAuthSuccess(deviceId);
        },
        onError: (error: BusinessError) => {
          console.error(`[DeviceManager] Authentication failed: ${JSON.stringify(error)}`);
        }
      });
      
      return true;
    } catch (error) {
      console.error('[DeviceManager] Connect device failed:', error);
      return false;
    }
  }
  
  // 认证成功处理
  private onAuthSuccess(deviceId: string): void {
    // 建立连接
    deviceManager.connectDevice(
      deviceId,
      deviceManager.ConnectType.TYPE_WIFI_P2P,
      this.connectionCallback!
    ).then(() => {
      console.info(`[DeviceManager] Device ${deviceId} connected successfully`);
    }).catch((error: BusinessError) => {
      console.error(`[DeviceManager] Connect failed: ${JSON.stringify(error)}`);
    });
  }
  
  // 设置连接回调
  private setupConnectionCallback(): void {
    this.connectionCallback = {
      onConnect: (deviceInfo: deviceManager.DeviceBasicInfo) => {
        console.info(`[DeviceManager] Device connected: ${deviceInfo.deviceName}`);
        this.emitDeviceConnected(deviceInfo);
      },
      onDisconnect: (deviceInfo: deviceManager.DeviceBasicInfo) => {
        console.info(`[DeviceManager] Device disconnected: ${deviceInfo.deviceName}`);
        this.emitDeviceDisconnected(deviceInfo);
      }
    };
  }
  
  // 设备状态变更处理
  private handleDeviceStateChange(
    action: deviceManager.DeviceStateChangeAction, 
    device: deviceManager.DeviceBasicInfo
  ): void {
    switch (action) {
      case deviceManager.DeviceStateChangeAction.ONLINE:
        console.info(`[DeviceManager] Device online: ${device.deviceName}`);
        break;
      case deviceManager.DeviceStateChangeAction.OFFLINE:
      case deviceManager.DeviceStateChangeAction.READY_OFFLINE:
        console.info(`[DeviceManager] Device offline: ${device.deviceName}`);
        break;
    }
  }
  
  // 获取设备列表
  getDevices(): deviceManager.DeviceBasicInfo[] {
    return [...this.deviceList];
  }
  
  // 停止发现
  async stopDiscovery(): Promise<void> {
    if (this.deviceDiscovery) {
      await this.deviceDiscovery.stop();
      this.deviceDiscovery = null;
    }
  }
  
  // 清理资源
  release(): void {
    this.stopDiscovery();
    this.deviceList = [];
  }
  
  // 事件发射器(简化版)
  private emitDeviceListUpdated(): void {
    // 实际实现中可使用EventEmitter
  }
  
  private emitDeviceConnected(device: deviceManager.DeviceBasicInfo): void {
    // 实际实现中可使用EventEmitter
  }
  
  private emitDeviceDisconnected(device: deviceManager.DeviceBasicInfo): void {
    // 实际实现中可使用EventEmitter
  }
}

1.2 UI组件封装

// DeviceListComponent.ets - 设备列表组件
@Component
export struct DeviceListComponent {
  @State deviceList: Array<DeviceItem> = [];
  private deviceManager: HarmonyDeviceManager = new HarmonyDeviceManager();
  
  aboutToAppear(): void {
    this.initDeviceDiscovery();
  }
  
  // 初始化设备发现
  async initDeviceDiscovery(): Promise<void> {
    // 请求权限
    await this.requestPermissions();
    
    // 初始化设备管理器
    await this.deviceManager.initDeviceManager(getContext(this) as common.UIAbilityContext);
    
    // 开始发现设备
    await this.deviceManager.startDiscovery();
    
    // 定时刷新设备列表
    setInterval(() => {
      this.deviceList = this.deviceManager.getDevices().map(device => ({
        id: device.deviceId,
        name: device.deviceName || 'Unknown Device',
        type: this.getDeviceType(device.deviceType),
        isConnected: false // 实际应从设备管理器获取连接状态
      }));
    }, 2000);
  }
  
  // 请求必要权限
  async requestPermissions(): Promise<void> {
    const permissions: Array<string> = [
      'ohos.permission.DISTRIBUTED_DATASYNC',
      'ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE',
      'ohos.permission.GET_NETWORK_INFO'
    ];
    
    for (const permission of permissions) {
      try {
        const result = await abilityAccessCtrl.requestPermissionsFromUser(
          getContext(this) as common.UIAbilityContext,
          [permission]
        );
        console.info(`[DeviceList] Permission ${permission} granted: ${result.authResults[0] === 0}`);
      } catch (error) {
        console.error(`[DeviceList] Permission request failed: ${error}`);
      }
    }
  }
  
  // 连接设备
  async connectToDevice(deviceId: string): Promise<void> {
    const success = await this.deviceManager.connectDevice(deviceId);
    if (success) {
      promptAction.showToast({ message: '设备连接成功' });
    } else {
      promptAction.showToast({ message: '设备连接失败' });
    }
  }
  
  // 获取设备类型图标
  getDeviceType(deviceType: number): string {
    switch (deviceType) {
      case 0x00: return 'phone'; // 手机
      case 0x01: return 'tablet'; // 平板
      case 0x02: return 'tv'; // 智慧屏
      case 0x03: return 'watch'; // 手表
      default: return 'device';
    }
  }
  
  build() {
    Column() {
      // 标题
      Text('附近设备')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 20 })
      
      // 设备列表
      List({ space: 10 }) {
        ForEach(this.deviceList, (device: DeviceItem) => {
          ListItem() {
            DeviceItemComponent({ device: device, onConnect: (id: string) => {
              this.connectToDevice(id);
            }})
          }
        })
      }
      .layoutWeight(1)
      
      // 操作按钮
      Row() {
        Button('重新扫描')
          .onClick(() => {
            this.deviceManager.stopDiscovery();
            this.deviceManager.startDiscovery();
          })
          .margin({ right: 10 })
        
        Button('停止发现')
          .onClick(() => {
            this.deviceManager.stopDiscovery();
          })
      }
      .justifyContent(FlexAlign.Center)
      .margin({ top: 20, bottom: 20 })
    }
  }
}
// 设备项组件
@Component
struct DeviceItemComponent {
  private device: DeviceItem = { id: '', name: '', type: '', isConnected: false };
  private onConnect?: (deviceId: string) => void;
  
  build() {
    Row() {
      // 设备图标
      Image($r(`app.media.ic_device_${this.device.type}`))
        .width(40)
        .height(40)
        .margin({ right: 15 })
      
      // 设备信息
      Column() {
        Text(this.device.name)
          .fontSize(16)
          .fontWeight(FontWeight.Medium)
        
        Text(`设备ID: ${this.device.id.substring(0, 8)}...`)
          .fontSize(12)
          .fontColor(Color.Gray)
      }
      .layoutWeight(1)
      .alignItems(HorizontalAlign.Start)
      
      // 连接按钮
      Button(this.device.isConnected ? '已连接' : '连接')
        .enabled(!this.device.isConnected)
        .onClick(() => {
          if (this.onConnect) {
            this.onConnect(this.device.id);
          }
        })
    }
    .padding(15)
    .backgroundColor(Color.White)
    .borderRadius(8)
    .shadow({ radius: 4, color: Color.Black, offsetX: 0, offsetY: 2 })
  }
}

1.3 权限配置文件

// module.json5
{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC",
        "reason": "需要同步数据到其他设备",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE",
        "reason": "需要监听设备状态变化",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      },
      {
        "name": "ohos.permission.GET_NETWORK_INFO",
        "reason": "需要获取网络信息进行设备发现",
        "usedScene": {
          "abilities": ["EntryAbility"],
          "when": "always"
        }
      }
    ],
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "permissions": [
          "ohos.permission.DISTRIBUTED_DATASYNC",
          "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"
        ]
      }
    ]
  }
}

步骤1:添加依赖

// oh-package.json5
{
  "dependencies": {
    "@ohos/distributedDeviceManager": "file:../feature/distributed_device_manager"
  }
}

步骤2:配置设备能力

// module.json5
{
  "module": {
    "name": "entry",
    "type": "entry",
    "deviceTypes": ["phone", "tablet", "tv", "wearable"],
    "distributedNotificationEnabled": true,
    "distributedPermissions": {
      "com.example.myapp": {
        "data": {
          "access": ["read", "write"],
          "uri": "dataability:///com.example.myapp.DataAbility"
        }
      }
    }
  }
}

步骤3:实现设备发现服务

// DeviceDiscoveryService.ts
export class DeviceDiscoveryService {
  private static instance: DeviceDiscoveryService;
  private discoveryCallbacks: Array<(devices: DeviceBasicInfo[]) => void> = [];
  
  static getInstance(): DeviceDiscoveryService {
    if (!DeviceDiscoveryService.instance) {
      DeviceDiscoveryService.instance = new DeviceDiscoveryService();
    }
    return DeviceDiscoveryService.instance;
  }
  
  // 统一发现接口
  async discoverNearbyDevices(options: DiscoveryOptions = {}): Promise<DeviceBasicInfo[]> {
    const devices: DeviceBasicInfo[] = [];
    
    // 多协议并行发现
    await Promise.all([
      this.discoverViaBluetooth(devices, options),
      this.discoverViaWiFi(devices, options),
      this.discoverViaCoap(devices, options)
    ]);
    
    // 去重和排序
    return this.deduplicateAndSortDevices(devices);
  }
  
  private async discoverViaBluetooth(
    devices: DeviceBasicInfo[], 
    options: DiscoveryOptions
  ): Promise<void> {
    // 蓝牙发现实现
  }
  
  private async discoverViaWiFi(
    devices: DeviceBasicInfo[], 
    options: DiscoveryOptions
  ): Promise<void> {
    // Wi-Fi发现实现
  }
  
  private async discoverViaCoap(
    devices: DeviceBasicInfo[], 
    options: DiscoveryOptions
  ): Promise<void> {
    // CoAP发现实现
  }
}

步骤5:实现连接管理

// ConnectionManager.ts
export class ConnectionManager {
  private connections: Map<string, DeviceConnection> = new Map();
  
  // 建立连接
  async establishConnection(
    deviceId: string, 
    options: ConnectionOptions
  ): Promise<DeviceConnection> {
    const connection: DeviceConnection = {
      deviceId,
      status: 'connecting',
      timestamp: Date.now(),
      retryCount: 0
    };
    
    this.connections.set(deviceId, connection);
    
    try {
      // 1. 设备认证
      await this.authenticateDevice(deviceId, options.authType);
      
      // 2. 建立传输通道
      const channel = await this.createChannel(deviceId, options.channelType);
      
      // 3. 启动心跳检测
      this.startHeartbeat(deviceId);
      
      connection.status = 'connected';
      connection.channel = channel;
      
      console.info(`[ConnectionManager] Device ${deviceId} connected successfully`);
      return connection;
      
    } catch (error) {
      connection.status = 'failed';
      connection.error = error as Error;
      
      // 重试逻辑
      if (connection.retryCount < options.maxRetries || 3) {
        connection.retryCount++;
        return this.establishConnection(deviceId, options);
      }
      
      throw error;
    }
  }
}

测试环境:2台华为P60,HarmonyOS 4.0 测试场景:设备发现与连接

可复用组件清单

  1. HarmonyDeviceManager​ - 核心设备管理类
  2. DeviceListComponent​ - 设备列表UI组件
  3. ConnectionManager​ - 连接状态管理
  4. DeviceDiscoveryService​ - 统一发现服务
  5. PermissionHelper​ - 权限管理工具
  6. 示例配置文件​ - 权限、能力配置模板

最佳实践总结

  1. 统一入口:封装所有设备操作到一个管理器
  2. 事件驱动:使用观察者模式监听设备状态变化
  3. 错误处理:统一的错误处理重试机制
  4. 权限管理:按需请求,优雅降级
  5. 状态管理:使用状态机管理连接生命周期
  6. 多协议支持:自动选择最优发现协议
  7. 资源释放:合理释放不使用的资源

更多关于HarmonyOS鸿蒙Next实战开发-设备连接与认证的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

鸿蒙Next设备连接与认证主要基于分布式软总线与统一认证框架。分布式软总线实现设备间自动发现、组网与通信,支持多种协议。统一认证通过设备证书、PIN码等方式验证设备身份,确保安全连接。开发者需配置设备Profile,调用相关API实现连接与认证流程。

更多关于HarmonyOS鸿蒙Next实战开发-设备连接与认证的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


这篇实战分享非常全面,清晰地展示了HarmonyOS Next中分布式设备连接与认证的核心流程和代码实现。以下是对几个关键点的补充和优化建议:

1. 设备发现模式选择 代码中使用了DISCOVERY_MODE_ACTIVE主动发现模式。在实际场景中,应根据应用需求灵活选择:

  • 主动发现 (DISCOVERY_MODE_ACTIVE):适用于需要实时获取设备列表的场景,但功耗较高。
  • 被动发现 (DISCOVERY_MODE_PASSIVE):设备监听网络广播,功耗较低,适合后台服务。
  • 可通过discoveryMode参数动态切换。

2. 认证参数优化 authenticateDevice方法的authParam需要根据设备能力动态配置:

const authParam: deviceManager.AuthParam = {
    authType: deviceManager.AuthType.PIN_CODE, // 可根据设备支持类型选择PIN、二维码等
    appIcon: '', // 建议传入应用图标资源ID,增强用户信任感
    appThumbnail: '', // 应用缩略图,用于认证界面展示
    extraInfo: { // 可传递业务自定义信息
        businessType: 'file_transfer'
    }
};

3. 连接类型适配 connectDeviceConnectType应根据网络环境优化:

  • TYPE_WIFI_P2P:点对点直连,速度快,距离近。
  • TYPE_WIFI_LAN:通过局域网路由连接,覆盖范围广。
  • 可先尝试P2P,失败后自动降级到LAN模式。

4. 设备状态同步 建议在DeviceManager中增加连接状态缓存,避免UI组件频繁查询:

private connectedDevices: Map<string, boolean> = new Map();

// 更新连接状态
private updateDeviceStatus(deviceId: string, isConnected: boolean): void {
    this.connectedDevices.set(deviceId, isConnected);
    this.emitDeviceStatusChanged(deviceId, isConnected);
}

5. 资源释放时机 release()方法应在Ability的onDestroy中调用,确保及时释放设备监听和网络资源,防止内存泄漏。

6. 权限请求优化 UI组件中的requestPermissions可封装为独立工具类,支持:

  • 批量请求和单个请求。
  • 解释性弹窗(当用户拒绝时)。
  • 权限结果持久化记录。

7. 多协议发现策略 DeviceDiscoveryService的多协议并行发现策略很好,建议增加协议优先级逻辑:

  • 相同设备在Wi-Fi和蓝牙下都能发现时,优先使用Wi-Fi通道。
  • 根据信号强度(RSSI)自动选择最优连接。

8. 错误码处理 分布式操作错误码较多,建议建立错误码映射表:

const ErrorCodeMap = {
    201: '权限验证失败',
    202: '设备不可达',
    203: '认证超时',
    // ...
};

9. 测试建议 除功能测试外,还需关注:

  • 弱网环境下的连接稳定性。
  • 多设备同时发现时的性能表现。
  • 跨版本HarmonyOS设备的兼容性。

整体实现架构清晰,封装合理,可直接用于生产环境。重点注意连接生命周期管理和异常场景的健壮性处理。

回到顶部