目录

Distributed Device Management Development

Introduction

As users own an increasing number of different types of terminal devices, distributed services allow one device to use the capabilities of other devices as an extension of its own capabilities so that devices can collaborate to complete complex service scenarios.

Distributed device management serves as the entry to distributed services and provides unified management of nearby trusted and untrusted devices in distributed service scenarios.

Distributed device management provides the following four capabilities:

[h2]Working Principles

As the entry to distributed services, device management requires the application to actively initiate binding to discovered devices in the corresponding service scenario to establish a trusted relationship. After the service ends, the application decides whether to remove the binding relationship. The application itself controls whether the trusted relationship between devices is released.

[h2]Constraints

To use device management capabilities, the user must ensure that the devices are connected to the same LAN or that Bluetooth is enabled. Otherwise, the capability is unavailable.

Device information is sensitive user data. Therefore, even if the devices are already connected to the same LAN or Bluetooth is enabled, the application must still request the data synchronization permission from the user before obtaining device information. Only after the user grants the permission does the system provide device management capabilities to the application.

Requesting Permissions

[h2]Scenario

Before using distributed device management capabilities, the application must check whether it has obtained user authorization to access distributed data synchronization information. If authorization has not been granted, the application can request the required permission from the user.

ohos.permission.DISTRIBUTED_DATASYNC: permission for distributed data synchronization

To use device management capabilities, you must request this permission and obtain user authorization.

[h2]How to Develop

This topic applies to the Stage model.

  1. Declare the ohos.permission.DISTRIBUTED_DATASYNC permission in the module.json5 configuration file.

    {
      "module" : {
        "requestPermissions":[
          {
            "name" : "ohos.permission.DISTRIBUTED_DATASYNC",
            "reason": "$string:distributed_permission",
            "usedScene": {
              "abilities": [
                "MainAbility"
              ],
              "when": "inuse"
            }
          }
        ]
      }
    }
  2. Import the abilityAccessCtrl module to obtain the permission request capability.

    import { abilityAccessCtrl } from '@kit.AbilityKit';
  3. Authorization for distributed data synchronization is granted in user_grant mode. Therefore, call requestPermissionsFromUser9+ to request authorization from the user through a dynamic dialog box.

    let atManager = abilityAccessCtrl.createAtManager();
    atManager.requestPermissionsFromUser(context, ['ohos.permission.DISTRIBUTED_DATASYNC'])
      .then(async (data) => {
        logger.info(`data: ${JSON.stringify(data)}`);
        // ...
      })
      .catch((err: BusinessError) => {
        logger.error(`requestPermissionsFromUser error: ${JSON.stringify(err)}`);
      });

Discovering Devices

[h2]Scenario

Developers can call the device discovery APIs to obtain nearby available devices.

[h2]Available APIs

startDiscovering(discoverParam: {[key: string]: Object;} , filterOptions?: {[key: string]: Object;} ): void;

Discovers devices on the same LAN or with Bluetooth enabled. For details, see startDiscovering.

[h2]How to Develop

  1. Request the distributed data synchronization permission.

  2. Import the distributedDeviceManager module, which provides all device management APIs.

    import { distributedDeviceManager } from '@kit.DistributedServiceKit';
  3. Import the BusinessError module, which provides the error codes thrown by the APIs in the distributedDeviceManager module.

    import { BusinessError } from '@kit.BasicServicesKit';
  4. Create a device management instance, which serves as the entry for calling distributed device management APIs.

    async createDeviceManager(): Promise<void> {
      if (typeof (this.deviceManager) != 'undefined') {
        return;
      }
    
      logger.info('[DeviceManager.RemoteDeviceModel] deviceManager.createDeviceManager begin');
      try {
        let dmInstance = distributedDeviceManager.createDeviceManager('com.samples.devicemanager');
        this.deviceManager = dmInstance
        // ...
        logger.info(`[DeviceManager.RemoteDeviceModel] createDeviceManager callback returned,
        value= ${JSON.stringify(this.deviceManager)}`);
      } catch (err) {
        let error: BusinessError = err as BusinessError;
        logger.error(`[DeviceManager.RemoteDeviceModel] createDeviceManager throw error,
        error=${error} message=${error.message}`);
      }
      logger.info('[DeviceManager.RemoteDeviceModel] distributedDeviceManager.createDeviceManager end');
    }
  5. Register callbacks for device discovery and call the discovery API to discover nearby devices. Discovery lasts for 2 minutes. After 2 minutes, discovery stops automatically. Up to 99 devices can be discovered.

    startDeviceDiscovery(): void {
      if (typeof (this.deviceManager) == 'undefined') {
        logger.error('[DeviceManager.RemoteDeviceModel] deviceManager has not initialized');
        this.showErrMsg('deviceManager has not initialized');
        return;
      }
      let self = this;
      try {
        this.deviceManager.on('discoverSuccess', (data) => {
          if (data == null) {
            return;
          }
          logger.info('[DeviceManager.RemoteDeviceModel] deviceFound data=' + JSON.stringify(data));
          self.deviceFound(data);
        })
        this.deviceManager.on('discoverFailure', (data) => {
          logger.info('[DeviceManager.RemoteDeviceModel] discoverFail data=' + JSON.stringify(data));
        })
        // ...
        let discoverParam: Record<string, number> = {
          'discoverTargetType': 1
        };
        let filterOptions: Record<string, number> = this.getFilterOptions();
        logger.info('[DeviceManager.RemoteDeviceModel] startDeviceDiscovery filterOptions = ' + JSON.stringify(filterOptions));
        if (Object.entries(filterOptions).length == 0) {
          this.deviceManager.startDiscovering(discoverParam);
        } else {
          this.deviceManager.startDiscovering(discoverParam, filterOptions);
        }
      } catch (err) {
        let e: BusinessError = err as BusinessError;
        logger.error('[DeviceManager.RemoteDeviceModel] startDeviceDiscovery failed err: ' + e.toString());
      }
    }
  6. When discovery ends or the page exits, call the API for stopping discovery to release the discovery listeners.

    stopDeviceDiscovery(): void {
      if (typeof (this.deviceManager) == 'undefined') {
        logger.error('[DeviceManager.RemoteDeviceModel] deviceManager has not initialized');
        this.showErrMsg('deviceManager has not initialized');
        return;
      }
      logger.info('[DeviceManager.RemoteDeviceModel] stopDeviceDiscovery');
      try {
        this.deviceManager.stopDiscovering();
        this.deviceManager.off('discoverSuccess');
        this.deviceManager.off('discoverFailure');
      } catch (e) {
        logger.error('[DeviceManager.RemoteDeviceModel] stopDeviceDiscovery failed err: ' + e.toString());
      }
    }

Binding a Device

[h2]Scenario

After discovering nearby untrusted devices, developers can establish a trusted relationship by using the binding API.

[h2]Available APIs

bindTarget(deviceId: string, bindParam: {[key: string]: Object;} , callback: AsyncCallback<{deviceId: string;}>): void;

Binds a device. For details, see bindTarget.

[h2]How to Develop

  1. Request the distributed data synchronization permission.

  2. Discover nearby untrusted devices.

  3. Select the untrusted device ID and initiate device binding.

    authenticateDevice(device: distributedDeviceManager.DeviceBasicInfo): void {
      logger.info('[DeviceManager.RemoteDeviceModel] authenticateDevice ' + JSON.stringify(device));
      if (typeof (this.deviceManager) == 'undefined') {
        logger.error('[DeviceManager.RemoteDeviceModel] deviceManager has not initialized');
        this.showErrMsg('deviceManager has not initialized');
        return;
      }
    
      for (let i = 0; i < this.discoverList.length; i++) {
        if (this.discoverList[i].deviceId != device.deviceId) {
          continue;
        }
    
        let bindParam: Record<string, number | string> = {
          'bindLevel': 3,
          'bindType': 1, // PIN-based authentication
          'targetPkgName': 'ohos.samples.etsdevicemanager',
          'appName': 'DeviceManager',
        };
        try {
          this.deviceManager.bindTarget(device.deviceId, bindParam, (err: BusinessError, data: Object) => {
            if (err) {
              logger.error('[DeviceManager.RemoteDeviceModel] authenticateDevice error:' + JSON.stringify(err));
              return;
            }
            logger.info('[DeviceManager.RemoteDeviceModel] authenticateDevice succeed:' + JSON.stringify(data));
          })
        } catch (err) {
          let e: BusinessError = err as BusinessError;
          logger.error('[DeviceManager.RemoteDeviceModel] authenticateDevice failed err: ' + e.toString());
        }
      }
    }

Querying Device Information

[h2]Scenario

After a trusted relationship is established between devices, the device information query API can be used to obtain all nearby devices that are online and trusted.

[h2]Available APIs

getAvailableDeviceListSync(): Array<DeviceBasicInfo>;

Queries device information. For details, see getAvailableDeviceListSync.

[h2]How to Develop

  1. Request the distributed data synchronization permission.

  2. Discover nearby untrusted devices.

  3. Establish a trusted relationship between devices.

  4. Query nearby devices that are online and trusted.

    getTrustedDeviceList(): void {
      if (typeof (this.deviceManager) == 'undefined') {
        logger.error('[DeviceManager.RemoteDeviceModel] deviceManager has not initialized');
        this.showErrMsg('deviceManager has not initialized');
        return;
      }
    
      logger.info('[DeviceManager.RemoteDeviceModel] getTrustedDeviceList begin');
      try {
        this.trustedDeviceList = this.deviceManager.getAvailableDeviceListSync();
        // ...
      } catch (error) {
        logger.error(`[DeviceManager.RemoteDeviceModel] getTrustedDeviceList error: ${error}`);
        this.showErrMsg('getTrustedDeviceList failed');
      }
    }

Listening for Device Online/Offline Status

[h2]Scenario

When a nearby trusted device becomes available, the service receives an online notification. When the device becomes unavailable, the service receives an offline notification.

[h2]Available APIs

on(type: 'deviceStateChange', callback: Callback<{ action: DeviceStateChange; device: DeviceBasicInfo; }>): void;

Listens for device online and offline status. For details, see on('deviceStateChange').

[h2]How to Develop

  1. Request the distributed data synchronization permission.

  2. Import the distributedDeviceManager module, which provides all device management APIs.

    import { distributedDeviceManager } from '@kit.DistributedServiceKit';
  3. Import the BusinessError module, which provides the error codes thrown by the APIs in the distributedDeviceManager module.

    import { BusinessError } from '@kit.BasicServicesKit';
  4. Create a device management instance, which serves as the entry for calling distributed device management APIs, and register callbacks for device online and offline events.

    registerDeviceStateListener(): void {
      logger.info('[DeviceManager.RemoteDeviceModel] registerDeviceStateListener');
      if (typeof (this.deviceManager) == 'undefined') {
        logger.error('[DeviceManager.RemoteDeviceModel] deviceManager has not initialized');
        this.showErrMsg('deviceManager has not initialized');
        return;
      }
    
      // ...
      try {
        this.deviceManager.on('deviceStateChange', (data: dataType) => {
          if (data == null) {
            return;
          }
          logger.info('[DeviceManager.RemoteDeviceModel] deviceStateChange data=' + JSON.stringify(data));
          switch (data.action) {
            case distributedDeviceManager.DeviceStateChange.AVAILABLE:
              logger.info('[DeviceManager.RemoteDeviceModel] deviceStateChange ONLINE');
              // ...
              break;
            case distributedDeviceManager.DeviceStateChange.UNAVAILABLE:
              logger.info('[DeviceManager.RemoteDeviceModel] deviceStateChange OFFLINE');
              // ...
              break;
            default:
              break;
          }
        })
      } catch(err) {
        let e: BusinessError = err as BusinessError;
        logger.error('[DeviceManager.RemoteDeviceModel] deviceStateChange failed err: ' + e.toString());
      }
    }