
本文详解如何通过 retrofit 构建符合 sony ircc 协议的 soap xml post 请求,包括自定义 header、手动构造 xml 请求体、配置 okhttpclient 与 retrofit,并处理无 json 响应体的原始 http 交互。
本文详解如何通过 retrofit 构建符合 sony ircc 协议的 soap xml post 请求,包括自定义 header、手动构造 xml 请求体、配置 okhttpclient 与 retrofit,并处理无 json 响应体的原始 http 交互。
在 Android 开发中,调用索尼电视的 IRCC(Infrared Remote Control Command)服务需严格遵循其 SOAP over HTTP 协议规范:使用 POST /sony/ircc 端点、携带 X-Auth-PSK 预共享密钥、设置 Content-Type: text/xml; charset=UTF-8、SOAPACTION 头,并提交标准 SOAP 1.1 包裹的 XML 请求体。Retrofit 默认面向 JSON,但可通过灵活配置支持纯 XML 请求——关键在于绕过自动序列化,手动构造 RequestBody,并禁用对响应体的反序列化依赖。
✅ 正确配置 Retrofit 客户端(支持 XML 请求 + 自定义 Header)
首先,构建带必要拦截器的 OkHttpClient:
val okHttpClient = OkHttpClient.Builder()
.addInterceptor { chain ->
val request = chain.request()
.newBuilder()
.header("Host", "192.168.0.1") // 显式指定 Host(重要!)
.header("Accept", "*/*")
.header("Content-Type", "text/xml; charset=UTF-8")
.header("SOAPACTION", "urn:schemas-sony-com:service:IRCC:1#X_SendIRCC")
.header("X-Auth-PSK", "1234") // 替换为实际 PSK
.header("Connection", "Keep-Alive")
.build()
chain.proceed(request)
}
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
})
.build()⚠️ 注意:Host 头必须显式设置(Retrofit 会覆盖默认 Host),否则索尼设备可能拒绝请求;X-Auth-PSK 值需与电视 Web UI 中配置的预共享密钥一致。
接着,初始化 Retrofit 实例——不添加 GsonConverterFactory(因响应体通常为空或为 XML,且无需解析),改用 ScalarsConverterFactory 或直接返回 Response<ResponseBody>:
val retrofit = Retrofit.Builder()
.baseUrl("http://192.168.0.1/sony/") // 注意末尾斜杠,与 @POST 路径拼接后为 /sony/ircc
.client(okHttpClient)
.addConverterFactory(ScalarsConverterFactory.create()) // 支持 String/ResponseBody
.build()
interface ApiServices {
@POST("ircc")
suspend fun sendIrccCommand(@Body xmlBody: RequestBody): Response<ResponseBody>
}✅ 构造合规 SOAP XML 请求体
使用 Kotlin 字符串模板生成严格对齐的 SOAP envelope(注意换行与命名空间):
fun buildSoapRequest(irccCode: String): RequestBody {
val xml = """<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<s:Body>
<u:X_SendIRCC xmlns:u="urn:schemas-sony-com:service:IRCC:1">
<IRCCCode>$irccCode</IRCCCode>
</u:X_SendIRCC>
</s:Body>
</s:Envelope>""".trimIndent()
return xml.toRequestBody("text/xml; charset=utf-8".toMediaType())
}✅ 推荐使用 trimIndent() 保持代码可读性,同时避免首行缩进污染 XML;toMediaType() 确保 Content-Type 与请求头一致。
✅ 发起请求并处理响应
调用示例(协程作用域内):
private suspend fun sendRemoteCommand(irccCode: String) {
try {
val api = retrofit.create(ApiServices::class.java)
val requestBody = buildSoapRequest(irccCode)
val response = api.sendIrccCommand(requestBody)
if (response.isSuccessful) {
// 索尼 IRCC 成功响应通常返回 HTTP 200 + 空体(或简单 XML),无需解析
Log.d("IRCC", "Command sent successfully: ${response.code()}")
} else {
Log.e("IRCC", "Error: ${response.code()} ${response.message()}")
// 检查 response.errorBody()?.string() 获取错误详情(如 500 错误时的 SOAP Fault)
}
} catch (e: Exception) {
Log.e("IRCC", "Network error", e)
}
}? 关键注意事项总结
- IP 地址与端口:确保目标电视开启“远程访问”且在同一局域网;默认端口为 80(HTTP),非 HTTPS。
- PSK 安全性:X-Auth-PSK 是明文传输,请勿在公网暴露;开发阶段建议硬编码,生产环境应加密存储。
- 响应处理:Sony IRCC 接口不返回结构化数据,Response<ResponseBody> 已足够;若需解析 SOAP Fault,可用 response.errorBody()?.string() 提取 XML 错误信息。
- 超时配置:建议为 OkHttpClient 添加连接/读取超时(如 .connectTimeout(10, TimeUnit.SECONDS)),避免阻塞主线程。
- 权限声明:AndroidManifest.xml 中务必添加 <uses-permission android:name="android.permission.INTERNET" />。
通过以上配置,你即可稳定、可靠地向索尼电视发送红外指令——这是实现智能家居遥控、自动化场景的核心通信基础。

















