API目录
- KY_registerSDKListener - 注册IOTC回调
- KY_unRegisterSDKListener - 注销IOTC回调
- KY_receiveBindInfo - Nebula绑定结果回调
- KY_DeviceStatus - 指定通道的连线状态回调
- KY_UpdateDecodedImage - 视频解码画面更新回调
- KY_DecodeVideoFramInfo - 视频帧信息回调
- KY_ReceiveFrameData - 视频帧数据回调
- KY_ReceiveAudioData - 音频帧数据回调
- KY_DidReceiveIOCtrlWithUid - Command回复数据回调
- KY_DidReceiveNebulaCtrlWithUid - Nebula Command回复回调
- KY_DownloadUploadOutput - 文件上传下载进度回调
回调接口模块介绍
回调接口是TUTK P2P SDK针对Android平台提供的核心回调集,用于接收设备绑定状态、连线状态、音视频数据、指令回复、文件传输进度等关键事件通知,是APP与设备之间异步通信的核心方式。所有回调需先通过KY_registerSDKListener注册监听后才能生效。
KY_registerSDKListener
功能描述:注册IOTC回调,是接收所有SDK回调事件的前提,需在使用其他回调接口前调用。
接口定义
public boolean KY_registerSDKListener(InterfaceCtrl.KY_SDKListener listener);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| listener | InterfaceCtrl.KY_SDKListener | SDK回调监听器对象,需实现所有回调方法 |
回调说明
无额外回调,注册结果通过接口返回值直接返回
返回码
- true: 注册成功
- false: 注册失败
代码示例
// 实现SDK回调监听器
InterfaceCtrl.KY_SDKListener sdkListener = new InterfaceCtrl.KY_SDKListener() {
@Override
public void KY_receiveBindInfo(String uid, String credential, int KYDeviceState, int errorCode) {
// 处理绑定结果回调
}
@Override
public void KY_DeviceStatus(String uid, int channel, int state) {
// 处理设备状态回调
}
// 实现其他回调方法...
};
// 注册SDK回调
boolean isRegistered = InterfaceCtrl.KY_registerSDKListener(sdkListener);
if (isRegistered) {
Log.d("TUTK", "SDK回调注册成功");
} else {
Log.d("TUTK", "SDK回调注册失败");
}
KY_unRegisterSDKListener
功能描述:注销IOTC回调,停止接收所有SDK回调事件,建议在页面销毁或不再需要回调时调用。
接口定义
public boolean KY_unRegisterSDKListener(InterfaceCtrl.KY_SDKListener listener);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| listener | InterfaceCtrl.KY_SDKListener | 已注册的SDK回调监听器对象 |
回调说明
无额外回调,注销结果通过接口返回值直接返回
返回码
- true: 注销成功
- false: 注销失败
代码示例
// 注销SDK回调
boolean isUnregistered = InterfaceCtrl.KY_unRegisterSDKListener(sdkListener);
if (isUnregistered) {
Log.d("TUTK", "SDK回调注销成功");
} else {
Log.d("TUTK", "SDK回调注销失败");
}
KY_receiveBindInfo
功能描述:Nebula绑定结果回调。当调用 KY_nebulaStartBind 进行设备绑定时,此接口会回调绑定结果。
接口定义
void KY_receiveBindInfo(String uid, String credential, int KYDeviceState, int errorCode);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前设备的uid |
| credential | string | 绑定设备产生的credential |
| KYDeviceState | int | 绑定状态 |
| errorCode | int | P2P SDK错误码 |
回调说明
绑定操作完成后自动触发此回调,无需主动调用
返回码
错误码参考TUTK P2P SDK官方错误码文档,0表示绑定成功
代码示例
@Override
public void KY_receiveBindInfo(String uid, String credential, int KYDeviceState, int errorCode) {
if (errorCode == 0) {
Log.d("TUTK", "设备绑定成功,UID: " + uid + ", credential: " + credential);
// 保存绑定凭证,用于后续设备连接
saveCredential(uid, credential);
} else {
Log.e("TUTK", "设备绑定失败,错误码: " + errorCode);
// 处理绑定失败逻辑
handleBindError(errorCode);
}
}
KY_DeviceStatus
功能描述:指定通道的连线状态回调。当调用 KY_Connect 进行连线并出图成功时,此接口会回调设备连线状态。
接口定义
void KY_DeviceStatus(String uid, int channel, int state);
状态码说明
KY_STATE_CONNECTING = 1: 连接中KY_STATE_CONNECTED = 2: 已连接KY_STATE_DISCONNECTED = 3: 已断开KY_STATE_UNKNOWN_DEVICE = 4: 未知设备KY_STATE_WRONG_PASSWORD = 5: 密码错误KY_STATE_TIMEOUT = 6: 超时KY_STATE_UNSUPPORTED = 7: 不支持KY_STATE_CONNECT_FAILED = 8: 连接失败KY_STATE_UNKNOWN_LICENSE = 9: 未知授权KY_STATE_SLEEP = 10: 设备休眠KY_STATE_DEVICE_MAX_SESSION = 11: 设备连接数已满KY_STATE_POOR_NETWORK_SIGNAL = 12: 网络信号差KY_STATE_WRONG_AUTH_KEY = 13: 认证密钥错误KY_STATE_SELF_DISCONNECT = 14: 主动断开
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前设备的uid |
| channel | int | 设备连线的channel,默认为0 |
| state | int | 设备连线状态码,参考上方状态码说明 |
代码示例
@Override
public void KY_DeviceStatus(String uid, int channel, int state) {
switch (state) {
case 1: // KY_STATE_CONNECTING
Log.d("TUTK", "设备" + uid + "正在连接中...");
break;
case 2: // KY_STATE_CONNECTED
Log.d("TUTK", "设备" + uid + "连接成功");
// 连接成功,开始出图或其他操作
startPreview(uid);
break;
case 3: // KY_STATE_DISCONNECTED
Log.d("TUTK", "设备" + uid + "连接已断开");
// 处理断开连接逻辑
stopPreview(uid);
break;
default:
Log.e("TUTK", "设备" + uid + "连接失败,状态码: " + state);
// 处理连接失败逻辑
showConnectError(state);
break;
}
}
KY_UpdateDecodedImage
功能描述:视频解码画面更新回调。当视频流解码出一帧新图像时触发此回调,用于同步视频帧更新状态。
接口定义
void KY_UpdateDecodedImage(String uid, int channel, long timestamp);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前设备的uid |
| channel | int | 设备连线的channel,默认为0 |
| timestamp | long | 当前数据的时间戳 |
回调说明
视频解码过程中实时触发,每解码一帧图像就会回调一次
代码示例
@Override
public void KY_UpdateDecodedImage(String uid, int channel, long timestamp) {
Log.d("TUTK", "设备" + uid + "视频帧更新,时间戳: " + timestamp);
// 更新视频显示画面
updateVideoView(uid, channel);
// 统计帧率
calculateFps(uid, timestamp);
}
KY_DecodeVideoFramInfo
功能描述:视频帧信息回调。提供当前视频流的详细参数,包括分辨率、帧率、码率、解码方式等关键信息。
接口定义
void KY_DecodeVideoFramInfo(String uid, int channel, int connectMode, int videoWidth, int videoHeight, int videoFPS, int bps, int onlineNm, int frameCount, int incompleteFrameCount, boolean isHwDecode, int sessionID, int avChannelIndex, int cmdNum, int cmdReturn);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前设备的uid |
| channel | int | 设备连线的channel,默认为0 |
| connectMode | int | 连线模式 (-1:NONE, 0:P2P, 1:RELAY, 2:LAN) |
| videoWidth | int | 视频宽 |
| videoHeight | int | 视频高 |
| videoFPS | int | 帧率 (fps) |
| bps | int | 音视频码率 (bps) |
| onlineNm | int | 在线人数 |
| frameCount | int | 接收帧数 |
| incompleteFrameCount | int | 丢帧数或不完整帧数 |
| isHwDecode | boolean | 是否是硬件解码 |
| sessionID | int | 连线返回的session号 |
| avChannelIndex | int | 开启通道返回的av通道 |
| cmdNum | int | command指令类型值 |
| cmdReturn | int | command指令返回值 |
回调说明
视频连接成功后周期性触发,用于监控视频流质量和参数
代码示例
@Override
public void KY_DecodeVideoFramInfo(String uid, int channel, int connectMode,
int videoWidth, int videoHeight, int videoFPS,
int bps, int onlineNm, int frameCount,
int incompleteFrameCount, boolean isHwDecode,
int sessionID, int avChannelIndex, int cmdNum, int cmdReturn) {
// 打印视频流信息
Log.d("TUTK", String.format(
"设备%s视频信息:分辨率%dx%d,帧率%dfps,码率%dbps,解码方式:%s",
uid, videoWidth, videoHeight, videoFPS, bps,
isHwDecode ? "硬件解码" : "软件解码"
));
// 计算丢帧率
float lossRate = frameCount > 0 ? (float)incompleteFrameCount / frameCount * 100 : 0;
Log.d("TUTK", "丢帧率: " + String.format("%.2f", lossRate) + "%");
// 根据连线模式做特殊处理
String connectModeStr = getConnectModeString(connectMode);
Log.d("TUTK", "连线模式: " + connectModeStr);
}
// 转换连线模式为字符串
private String getConnectModeString(int mode) {
switch (mode) {
case -1: return "NONE";
case 0: return "P2P";
case 1: return "RELAY";
case 2: return "LAN";
default: return "UNKNOWN";
}
}
KY_ReceiveFrameData
功能描述:获取当前设备指定通道解码后的视频帧数据回调,可用于自定义视频渲染或处理。
接口定义
void KY_ReceiveFrameData(String uid, int channel, AVFrame avFrame);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前设备的uid |
| channel | int | 设备连线的channel,默认为0 |
| avFrame | AVFrame | 包含视频数据(如YUV)和帧信息的对象 |
回调说明
视频解码后实时回调原始视频帧数据,适用于自定义渲染、截图、录制等场景
代码示例
@Override
public void KY_ReceiveFrameData(String uid, int channel, AVFrame avFrame) {
if (avFrame == null) {
return;
}
// 获取YUV数据
byte[] yData = avFrame.y;
byte[] uData = avFrame.u;
byte[] vData = avFrame.v;
// 获取帧信息
int width = avFrame.width;
int height = avFrame.height;
long timestamp = avFrame.timestamp;
// 自定义渲染YUV数据到SurfaceView
renderYUVData(yData, uData, vData, width, height);
// 可选:保存视频帧为图片
if (needCaptureFrame) {
saveFrameToImage(avFrame, uid);
needCaptureFrame = false;
}
}
KY_ReceiveAudioData
功能描述:获取当前设备指定通道接收的音频帧裸流数据及帧信息回调。当调用 KY_StartListen 进行监听时,此接口会回调音频数据。
接口定义
void KY_ReceiveAudioData(String uid, int channel, AVFrame avFrame);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前设备的uid |
| channel | int | 设备连线的channel,默认为0 |
| avFrame | AVFrame | 包含音频数据(如PCM)和帧信息的对象 |
回调说明
调用KY_StartListen开启监听后实时回调音频PCM数据,需自行处理音频播放
代码示例
// 音频播放器初始化
private AudioTrack audioTrack;
@Override
public void KY_ReceiveAudioData(String uid, int channel, AVFrame avFrame) {
if (avFrame == null || avFrame.data == null) {
return;
}
// 获取PCM音频数据
byte[] pcmData = avFrame.data;
int sampleRate = avFrame.sampleRate; // 采样率,如8000, 16000等
int channels = avFrame.channels; // 声道数,1:单声道,2:立体声
int bitDepth = avFrame.bitDepth; // 位深,通常为16
// 初始化音频播放器
if (audioTrack == null || !audioTrack.isPlaying()) {
initAudioTrack(sampleRate, channels, bitDepth);
}
// 播放PCM音频数据
if (audioTrack != null && audioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
audioTrack.write(pcmData, 0, pcmData.length);
}
}
// 初始化AudioTrack
private void initAudioTrack(int sampleRate, int channels, int bitDepth) {
int channelConfig = channels == 1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO;
int audioFormat = bitDepth == 16 ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
int bufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat);
audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
sampleRate,
channelConfig,
audioFormat,
bufferSize * 2,
AudioTrack.MODE_STREAM
);
audioTrack.play();
}
KY_DidReceiveIOCtrlWithUid
功能描述:获取设备回复Command的数据信息回调。当调用 KY_SendIOCtrlToChannel 发送Command时,此接口会回调设备的回复数据。
接口定义
void KY_DidReceiveIOCtrlWithUid(String uid, int channel, int type, byte[] data, int dataSize);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前接收Command的uid |
| channel | int | 设备连线的channel,默认为0 |
| type | int | command指令值 |
| data | byte[] | command对应指令的结构体数据 |
| dataSize | int | command对应指令的结构体数据长度 |
回调说明
发送Command指令后,设备回复时触发此回调,需根据指令类型解析二进制数据
代码示例
@Override
public void KY_DidReceiveIOCtrlWithUid(String uid, int channel, int type, byte[] data, int dataSize) {
Log.d("TUTK", "收到设备" + uid + "的Command回复,指令类型: " + type);
// 根据指令类型解析数据
switch (type) {
case CMD_GET_DEVICE_INFO: // 假设这是获取设备信息的指令类型
// 解析设备信息结构体
DeviceInfo info = parseDeviceInfo(data, dataSize);
Log.d("TUTK", "设备名称: " + info.deviceName + ", 固件版本: " + info.firmwareVersion);
break;
case CMD_GET_SD_CARD_INFO: // 获取SD卡信息
SDCardInfo sdInfo = parseSDCardInfo(data, dataSize);
Log.d("TUTK", "SD卡容量: " + sdInfo.totalSize + "MB, 可用: " + sdInfo.freeSize + "MB");
break;
default:
// 其他指令类型解析
Log.d("TUTK", "未处理的指令类型: " + type);
break;
}
}
// 示例:解析设备信息
private DeviceInfo parseDeviceInfo(byte[] data, int dataSize) {
DeviceInfo info = new DeviceInfo();
if (data != null && dataSize > 0) {
// 按结构体格式解析二进制数据
// 示例:假设前32字节是设备名称,接下来4字节是固件版本号
ByteBuffer buffer = ByteBuffer.wrap(data);
buffer.order(ByteOrder.LITTLE_ENDIAN);
byte[] nameBytes = new byte[32];
buffer.get(nameBytes);
info.deviceName = new String(nameBytes).trim();
info.firmwareVersion = buffer.getInt();
}
return info;
}
KY_DidReceiveNebulaCtrlWithUid
功能描述:获取设备回复Nebula Command的数据信息回调。当调用 KY_nebulaSendData 发送Nebula Command时,此接口会回调设备的回复数据。
接口定义
void KY_DidReceiveNebulaCtrlWithUid(String uid, int channel, String jsonRequest, String jsonResponse);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| uid | string | 当前接收Command的uid |
| channel | int | 设备连线的channel,默认为0 |
| jsonRequest | string | 发送的nebula command指令 (JSON格式) |
| jsonResponse | string | 设备返回的nebula command响应 (JSON格式) |
回调说明
发送Nebula Command后,设备回复时触发此回调,JSON格式数据易于解析和处理
代码示例
@Override
public void KY_DidReceiveNebulaCtrlWithUid(String uid, int channel, String jsonRequest, String jsonResponse) {
Log.d("TUTK", "设备" + uid + "Nebula指令回复:");
Log.d("TUTK", "请求: " + jsonRequest);
Log.d("TUTK", "响应: " + jsonResponse);
try {
// 解析JSON响应
JSONObject response = new JSONObject(jsonResponse);
// 获取响应状态
int code = response.optInt("code", -1);
String msg = response.optString("msg", "");
if (code == 0) {
// 指令执行成功
Log.d("TUTK", "Nebula指令执行成功");
// 根据不同指令解析数据
JSONObject request = new JSONObject(jsonRequest);
String cmd = request.optString("cmd");
if ("device_info".equals(cmd)) {
// 解析设备信息
JSONObject data = response.optJSONObject("data");
String deviceModel = data.optString("model");
String firmwareVer = data.optString("firmware_version");
Log.d("TUTK", "设备型号: " + deviceModel + ", 固件版本: " + firmwareVer);
} else if ("wifi_config".equals(cmd)) {
// 解析WiFi配置结果
boolean success = response.optBoolean("success");
Log.d("TUTK", "WiFi配置" + (success ? "成功" : "失败"));
}
} else {
// 指令执行失败
Log.e("TUTK", "Nebula指令执行失败:" + msg + " (错误码: " + code + ")");
}
} catch (JSONException e) {
Log.e("TUTK", "JSON解析失败", e);
}
}
KY_DownloadUploadOutput
功能描述:文件上传、下载进度回调。
- 连线成功之后,当调用 KY_startDownload 开始文件下载后,回调下载进度。
- 连线成功之后,当调用 KY_startUpload 开始文件上传后,回调上传进度。
接口定义
void KY_DownloadUploadOutput(Camera camera, int channel, String filePath, int progress, int loadType, int p2pCode);
参数说明
| 参数 | 类型 | 说明 |
|---|---|---|
| camera | Camera | 绑定的camera对象 |
| channel | int | 通道号 |
| filePath | string | 文件完整沙盒路径 |
| progress | int | 上传/下载进度 (0-100) |
| loadType | int | 下载或上传类型 (AVIOCTRLDEFs.FILETransferType_Download / AVIOCTRLDEFs.FILETransferType_Upload) |
| p2pCode | int | P2P SDK返回值 (0通常表示成功) |
回调说明
文件传输过程中周期性触发,进度达到100表示传输完成;p2pCode非0表示传输失败
代码示例
// 进度条控件
private ProgressDialog progressDialog;
@Override
public void KY_DownloadUploadOutput(Camera camera, int channel, String filePath, int progress, int loadType, int p2pCode) {
String fileName = new File(filePath).getName();
String transferType = loadType == AVIOCTRLDEFs.FILETransferType_Download ? "下载" : "上传";
Log.d("TUTK", String.format("%s文件%s,进度:%d%%,状态码:%d",
fileName, transferType, progress, p2pCode));
// 初始化进度对话框
if (progressDialog == null) {
progressDialog = new ProgressDialog(context);
progressDialog.setTitle(transferType + "文件");
progressDialog.setMessage("正在" + transferType + ":" + fileName);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(false);
progressDialog.show();
}
// 更新进度
progressDialog.setProgress(progress);
// 传输完成或失败
if (progress >= 100 || p2pCode != 0) {
progressDialog.dismiss();
progressDialog = null;
if (p2pCode == 0) {
Toast.makeText(context, fileName + transferType + "完成", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, fileName + transferType + "失败,错误码:" + p2pCode, Toast.LENGTH_SHORT).show();
}
}
}
