

# IVS 广播 SDK：令牌交换 \| 实时直播功能
<a name="broadcast-mobile-token-exchange"></a>

通过令牌交换，您可以升级或降级参与者令牌功能以及更新广播 SDK 中的令牌属性，而无需参与者重新连接。这对于联合主持等场景非常实用，即参与者可以首先使用仅限订阅的功能，以后再需要发布功能的场景。

移动和网络广播 SDK 均支持令牌交换。当参与者交换令牌时，服务器端合成会实时检测到更新后的属性，并自动调整布局——例如重新分配主画面位置、重新排序参与者，或将参与者移入画中画叠加层——整个过程无需重新连接。

限制：令牌交换仅支持在服务器上使用[密钥对](https://docs.aws.amazon.com//ivs/latest/RealTimeUserGuide/getting-started-distribute-tokens.html#getting-started-distribute-tokens-self-signed)创建的令牌，不支持通过 [CreateParticipantToken API](https://docs.aws.amazon.com/ivs/latest/RealTimeAPIReference/API_CreateParticipantToken.html) 创建的令牌。

## 交换令牌
<a name="broadcast-mobile-token-exchange-exchanging-tokens"></a>

交换令牌的过程十分简单：在 `Stage`/`IVSStage` 对象上调用 `exchangeToken` API 并提供新令牌即可。如果新令牌的 `capabilities` 与原令牌不同，则会立即评估新令牌的功能。例如，假设原令牌没有 `publish` 功能而新令牌有，则会调用用于发布的舞台策略函数，从而让主机应用程序决定是要使用该新功能立即发布，还是等待。此过程也适用于已移除的功能：如果原令牌具有 `publish` 功能而新令牌没有，则参与者无需调用用于发布的舞台策略函数即可立即取消发布。

交换令牌时，原令牌和新令牌中以下有效载荷字段的值必须相同：
+ `topic`
+ `resource`
+ `jti`
+ `whip_url`
+ `events_url`

这些字段是不可变的。修改不可变字段的令牌交换会导致 SDK 立即拒绝该交换。

其余字段是可以更改的，包括：
+ `attributes`
+ `capabilities`
+ `user`
+ `_id`
+ `iat`
+ `exp`

### iOS
<a name="broadcast-mobile-token-exchange-exchanging-tokens-ios"></a>



```
let stage = try IVSStage(token: originalToken, strategy: self)
stage.join()
stage.exchangeToken(newToken)
```

### Android
<a name="broadcast-mobile-token-exchange-exchanging-tokens-android"></a>



```
val stage = Stage(context, originalToken, strategy)
stage.join()
stage.exchangeToken(newToken)
```

### Web
<a name="broadcast-web-token-exchange-exchanging-tokens"></a>



```
const stage = new Stage(originalToken, strategy);
await stage.join();
await stage.exchangeToken(newToken);
```

## 接收更新
<a name="broadcast-mobile-token-exchange-receiving-updates"></a>

`StageRenderer`/`IVSStageRenderer` 中的某个函数收到有关通过交换令牌来更新其 `userId` 或 `attributes` 的远程参与者已发布的更新。尚未发布的远程参与者如果最终发布，则将通过现有的 `onParticipantJoined`/`participantDidJoin` renderer 函数公开更新后的`userId` 和 `attributes`。

### iOS
<a name="broadcast-mobile-token-exchange-receiving-updates-ios"></a>



```
class MyStageRenderer: NSObject, IVSStageRenderer {
    func stage(_ stage: IVSStage, participantMetadataDidUpdate participant: IVSParticipantInfo) {
        // participant will be a new IVSParticipantInfo instance with updated properties.
    }
}
```

### Android
<a name="broadcast-mobile-token-exchange-receiving-updates-android"></a>



```
private val stageRenderer = object : StageRenderer {
    override fun onParticipantMetadataUpdated(stage: Stage, participantInfo: ParticipantInfo) {
        // participantInfo will be a new ParticipantInfo instance with updated properties.
    }
}
```

### Web
<a name="broadcast-web-token-exchange-receiving-updates"></a>



```
stage.on(StageEvents.STAGE_PARTICIPANT_METADATA_CHANGED, (participantInfo: StageParticipantInfo) => { 
    // participantInfo properties will be updated with the changed properties 
    }
);
```

## 更新可见性
<a name="broadcast-mobile-token-exchange-visibility"></a>

当参与者通过交换令牌以更新其 `userId` 或 `attributes` 时，这些更改的可见性取决于其当前的发布状态：
+ **如果参与者*尚未*发布：**该更新将以静默方式处理。如果最终发布，则所有 SDK 都将通过初始发布事件收到更新后的 `userId` 和 `attributes`。
+ **如果参与者已经*在*发布中：**对于使用移动 SDK v1.37.0\+、Web SDK 以及服务器端合成的参与者，更新将立即广播。使用早期版本的移动 SDK 的参与者，在取消发布并重新发布前不会看到该更改。

下表澄清了支持矩阵：


| 参与者状态 | 观察者：移动 SDK v1.37.0\+、Web SDK、服务器端合成  | 观察者：早期版本的移动 SDK | 
| --- | --- | --- | 
| 尚未发布（然后开始） | ✅ 可见（通过参与者加入的事件在发布时可见） | ✅ 可见（通过参与者加入的事件在发布时可见） | 
| 已发布（从未重新发布） | ✅ 可见（通过参与者元数据更新事件立即可见） | ❌ 不可见 | 
| 已发布（取消发布并重新发布） | ✅ 可见（通过参与者元数据更新事件立即可见） | ⚠️ 最终可见（通过参与者加入的事件在重新发布时可见） | 