监听设备上下线（C/C++）
==============

#### 功能介绍

Game Controller Kit提供设备上下线事件监听和查询在线设备信息的功能。注册监听事件后，设备拔插时可获取实时回调通知，同时支持查询当前所有在线设备的具体信息。

#### 业务流程

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/8f/v3/LaxuuZQ2SBCBHvqPDnrPsg/zh-cn_image_0000002633849728.png?HW-CC-KV=V1&HW-CC-Date=20260709T132617Z&HW-CC-Expire=86400&HW-CC-Sign=A2FF3A04C210B949C6F41881397B944880E320CA614F5B585CD00F1708108B1E)

1.  玩家启动游戏。
    
2.  游戏调用OH\_GameDevice\_RegisterDeviceMonitor接口注册设备状态变化事件监听。
    
3.  玩家插拔设备。
    
4.  终端系统将设备状态变化通知Game Controller Kit。
    
5.  Game Controller Kit向游戏反馈设备状态变化。
    
6.  游戏调用OH\_GameDevice\_GetAllDeviceInfos接口向Game Controller Kit查询所有在线的游戏设备信息。
    
7.  Game Controller Kit从终端系统获取所有在线的游戏设备信息。
    
8.  如果不再需要订阅，游戏可以调用OH\_GameDevice\_UnregisterDeviceMonitor接口取消设备状态变化事件监听。
    

#### 接口说明

接口详细介绍请参考[API参考](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-game-controller)。

| 接口名 | 描述 |
| :-- | :-- |
| GameController\_ErrorCode OH\_GameDevice\_RegisterDeviceMonitor (GameDevice\_DeviceMonitorCallback deviceMonitorCallback) | 注册设备状态变化事件的监听回调。 |
| GameController\_ErrorCode OH\_GameDevice\_UnregisterDeviceMonitor (void) | 取消注册设备状态变化事件的监听回调。 |
| GameController\_ErrorCode OH\_GameDevice\_GetAllDeviceInfos (GameDevice\_AllDeviceInfos \*\*allDeviceInfos) | 获取所有在线设备的信息。 |

#### 开发步骤

#### \[h2\]链接动态库

target\_link\_libraries(entry PUBLIC libohgame\_controller.z.so)

#### \[h2\]导入模块

#include <GameControllerKit/game\_device.h>

#### \[h2\]注册设备上下线监听

调用OH\_GameDevice\_RegisterDeviceMonitor接口注册设备状态变化监听，获取设备上下线的回调通知。

napi\_value DeviceApi::RegisterDeviceMonitor(napi\_env env, napi\_callback\_info info) {
    napi\_value result;
    GameController\_ErrorCode errorCode = OH\_GameDevice\_RegisterDeviceMonitor(DeviceApi::OnDeviceChanged);
    if (errorCode != GameController\_ErrorCode::GAME\_CONTROLLER\_SUCCESS) {
        OH\_LOG\_ERROR(LOG\_APP, "RegisterDeviceMonitor Failed, %{public}d", errorCode);
        napi\_create\_double(env, errorCode, &result);
        return result;
    }
    OH\_LOG\_INFO(LOG\_APP, "RegisterDeviceMonitor Success");
    napi\_create\_double(env, 0, &result);
    return result;
}

void DeviceApi::OnDeviceChanged(const struct GameDevice\_DeviceEvent \*deviceEvent) {
    GameDevice\_StatusChangedType type;
    OH\_GameDevice\_DeviceEvent\_GetChangedType(deviceEvent, &type);
    GameDevice\_DeviceInfo \*deviceInfo;
    OH\_GameDevice\_DeviceEvent\_GetDeviceInfo(deviceEvent, &deviceInfo);
    std::string temp = GetDeviceInfoStringForPrint(deviceInfo);
    Log::GetInstance()->PrintLog("OnDeviceChanged type\[" + std::to\_string(type) + "\] DeviceInfo" + temp);
    OH\_LOG\_INFO(LOG\_APP, "OnDeviceChanged type:%{public}d DeviceInfo:%{public}s", type, temp.c\_str());
    OH\_GameDevice\_DestroyDeviceInfo(&deviceInfo);
}

#### \[h2\]取消注册设备上下线监听

如果不再需要订阅，可以调用OH\_GameDevice\_UnregisterDeviceMonitor接口取消设备状态变化事件的监听。

napi\_value DeviceApi::UnregisterDeviceMonitor(napi\_env env, napi\_callback\_info info) {
    napi\_value result;
    GameController\_ErrorCode errorCode = OH\_GameDevice\_UnregisterDeviceMonitor();
    if (errorCode != GameController\_ErrorCode::GAME\_CONTROLLER\_SUCCESS) {
        OH\_LOG\_ERROR(LOG\_APP, "UnregisterDeviceMonitor Failed, %{public}d", errorCode);
        napi\_create\_double(env, errorCode, &result);
        return result;
    }
    OH\_LOG\_INFO(LOG\_APP, "UnregisterDeviceMonitor Success");
    napi\_create\_double(env, 0, &result);
    return result;
}

#### \[h2\]查询所有在线设备

调用OH\_GameDevice\_GetAllDeviceInfos接口，查询所有在线游戏设备的信息。

GameController\_ErrorCode DeviceApi::DoQueryAllDeviceInfos() {
    GameDevice\_AllDeviceInfos \*gameDevice\_AllDeviceInfos;
    // 查询所有在线设备
    GameController\_ErrorCode errorCode = OH\_GameDevice\_GetAllDeviceInfos(&gameDevice\_AllDeviceInfos);
    if (errorCode != GameController\_ErrorCode::GAME\_CONTROLLER\_SUCCESS) {
        OH\_LOG\_ERROR(LOG\_APP, "GetAllDeviceInfos Failed, %{public}d", errorCode);
        return errorCode;
    }
    // 依次获取设备信息
    int count;
    OH\_GameDevice\_AllDeviceInfos\_GetCount(gameDevice\_AllDeviceInfos, &count);
    Log::GetInstance()->PrintLog("GetAllDeviceInfos Success, the count is " + std::to\_string(count));
    for (int idx = 0; idx < count; idx++) {
        GameDevice\_DeviceInfo \*deviceInfo;
        errorCode = OH\_GameDevice\_AllDeviceInfos\_GetDeviceInfo(gameDevice\_AllDeviceInfos, idx, &deviceInfo);
        if (errorCode != GameController\_ErrorCode::GAME\_CONTROLLER\_SUCCESS) {
            OH\_LOG\_ERROR(LOG\_APP, "OH\_GameDevice\_AllDeviceInfos\_GetDeviceInfo Failed, %{public}d", errorCode);
            return errorCode;
        }
        std::string temp = GetDeviceInfoStringForPrint(deviceInfo);
        Log::GetInstance()->PrintLog("AllDeviceInfos\[" + std::to\_string(idx) + "\]" + temp);
        OH\_LOG\_INFO(LOG\_APP, "AllDeviceInfos\[%{public}d\] DeviceInfo: %{public}s", idx, temp.c\_str());
        OH\_GameDevice\_DestroyDeviceInfo(&deviceInfo);
    }
    // 销毁指向设备查询结果的指针
    OH\_GameDevice\_DestroyAllDeviceInfos(&gameDevice\_AllDeviceInfos);
    OH\_LOG\_INFO(LOG\_APP, "GetAllDeviceInfos Success");
    return errorCode;
}

std::string DeviceApi::GetDeviceInfoStringForPrint(GameDevice\_DeviceInfo \*deviceInfo) {
    std::string log;
    char \*deviceId = NULL;
    OH\_GameDevice\_DeviceInfo\_GetDeviceId(deviceInfo, &deviceId);
    log.append("deviceId:").append(deviceId);
    free(deviceId);
    char \*name = NULL;
    OH\_GameDevice\_DeviceInfo\_GetName(deviceInfo, &name);
    log.append(",name:").append(name);
    free(name);
    int product;
    OH\_GameDevice\_DeviceInfo\_GetProduct(deviceInfo, &product);
    log.append(",product:").append(std::to\_string(product));
    int version;
    OH\_GameDevice\_DeviceInfo\_GetVersion(deviceInfo, &version);
    log.append(",version:").append(std::to\_string(version));
    char \*physicalAddress = NULL;
    OH\_GameDevice\_DeviceInfo\_GetPhysicalAddress(deviceInfo, &physicalAddress);
    log.append(",physicalAddress:").append(physicalAddress);
    free(physicalAddress);
    GameDevice\_DeviceType type;
    OH\_GameDevice\_DeviceInfo\_GetDeviceType(deviceInfo, &type);
    log.append(",type:").append(std::to\_string(type));
    return log;
}