NsdServiceInfo 不包含 Android 6.0 上的属性
NsdServiceInfo does not contain attributes on Android 6.0
在一个应该在 Android 6+ 上运行的 Android 应用程序上,我正在尝试使用网络服务发现来检查我的网络上是否有一些设备可用。
基于 this part of the official documentation,我创建了这个小 POC:
class MainActivity : AppCompatActivity() {
companion object {
private const val TAG = "POC"
private const val SERVICE_TYPE = "_http._tcp."
}
private val serviceToResolve = mutableListOf<NsdServiceInfo>()
private var index = 0
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.discover_btn).setOnClickListener {
search()
}
}
private fun search() {
lifecycleScope.launch(Dispatchers.IO) {
val serviceInfo = NsdServiceInfo().apply {
serviceName = "MyServiceTest"
serviceType = SERVICE_TYPE
port = 80
}
val registrationListener = object : NsdManager.RegistrationListener {
override fun onServiceRegistered(NsdServiceInfo: NsdServiceInfo) {}
override fun onRegistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {}
override fun onServiceUnregistered(arg0: NsdServiceInfo) {
}
override fun onUnregistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {}
}
val nsdManager = (getSystemService(Context.NSD_SERVICE) as NsdManager).apply {
registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener)
}
// Instantiate a new DiscoveryListener
val discoveryListener = object : NsdManager.DiscoveryListener {
override fun onDiscoveryStarted(regType: String) {
}
override fun onServiceFound(service: NsdServiceInfo) {
serviceToResolve.add(service)
}
override fun onServiceLost(service: NsdServiceInfo) {}
override fun onDiscoveryStopped(serviceType: String) {}
override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
nsdManager.stopServiceDiscovery(this)
}
override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
nsdManager.stopServiceDiscovery(this)
}
}
nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener)
delay(5000)
resolveService(nsdManager)
}
}
private fun resolveService(nsdManager: NsdManager) {
if (serviceToResolve.size > index) {
nsdManager.resolveService(serviceToResolve[index], object : NsdManager.ResolveListener {
override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
index++
resolveService(nsdManager)
}
override fun onServiceResolved(serviceInfo: NsdServiceInfo?) {
Log.d(TAG, "onServiceResolved : $serviceInfo || ${serviceInfo?.attributes}")
index++
resolveService(nsdManager)
}
})
} else {
Log.d(TAG, "Nothing to resolve")
}
}
}
此代码在 Android 7 到 11 上正常工作。但在 Android 6 上无法正常工作。我可以正确解析服务,但它不包含任何属性日志:
Log.d(TAG, "onServiceResolved : $serviceInfo || ${serviceInfo?.attributes}")
例如,Android 6.0 的结果:
onServiceResolved : name: TJA470 (TJA470-F40103), type: ._http._tcp, host: /10.0.0.177, port: 80 || {}
这里是 Android 11 的结果:
onServiceResolved : name: TJA470 (TJA470-F40103), type: ._http._tcp, host: /10.0.0.177, port: 80, txtRecord: 1device.type=urn:schemas-hager-com:device:tja470:1device.modelName=TJA470
export=Yes$device.modelURL=http://www.hager.comdevice.hostName=TJA470-F40103device.manufacturer=Hagerdevice.ip=10.0.0.1771device.modelDescription=Hager Pilot Configuration+device.manufacturerURL=http://www.hager.com(device.UDN=uuid:M2VSZEVUELAJYECHAJLU1708device.UPC=470,device.serialNumber=M2VSZEVUELAJYECHAJLU1708device.modelNumber=3.1.15'presentationURL=http://TJA470-F40103:80*device.friendlyName=TJA470 (TJA470-F40103) || {device.type=[117, 114, 110, 58, 115, 99, 104, 101, 109, 97, 115, 45, 104, 97, 103, 101, 114, 45, 99, 111, 109, 58, 100, 101, 118, 105, 99, 101, 58, 116, 106, 97, 52, 55, 48, 58, 49], device.modelName=[84, 74, 65, 52, 55, 48], export=[89, 101, 115], device.modelURL=[104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 104, 97, 103, 101, 114, 46, 99, 111, 109], device.hostName=[84, 74, 65, 52, 55, 48, 45, 70, 52, 48, 49, 48, 51], device.manufacturer=[72, 97, 103, 101, 114], device.ip=[49, 48, 46, 48, 46, 48, 46, 49, 55, 55], device.modelDescription=[72, 97, 103, 101, 114, 32, 80, 105, 108, 111, 116, 32, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110], device.manufacturerURL=[104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 104, 97, 103, 101, 114, 46, 99, 111, 109], device.UDN=[117, 117, 105, 100, 58, 77, 50, 86, 83, 90, 69, 86, 85, 69, 76, 65, 74, 89, 69, 67, 72, 65, 74, 76, 85, 49, 55, 48, 56], device.UPC=[52, 55, 48], device.serialNumber=[77, 50, 86, 83, 90, 69, 86, 85, 69, 76, 65, 74, 89, 69, 67, 72, 65, 74, 76, 85, 49, 55, 48, 56], device.modelNumber=[51, 46, 49, 46, 49, 53], presentationURL=[104, 116, 116, 112, 58, 47, 47, 84, 74, 65, 52, 55, 48, 45, 70, 52, 48, 49, 48, 51, 58, 56, 48], device.friendlyName=[84, 74, 65, 52, 55, 48, 32, 40, 84, 74, 65, 52, 55, 48, 45, 70, 52, 48, 49, 48, 51, 41]}
如您所见,这些属性出现在 Android 11 而不是 Android 6.0。这是 Android 6.0 上的 NSD_SERVICE 的问题还是我开发的 POC 的问题?
NsdServiceInfo
class 已添加到 API 16 中 getAttributes
方法已添加到 API 21 中。所以通常一切都应该工作在 Android 6.0 上正确:(
问题不在我的代码中,而是在 Android SDK 中,根据 this ticket。
在 Android 5 和 6 我需要使用像 Jmdns 这样的第三方库。
在一个应该在 Android 6+ 上运行的 Android 应用程序上,我正在尝试使用网络服务发现来检查我的网络上是否有一些设备可用。
基于 this part of the official documentation,我创建了这个小 POC:
class MainActivity : AppCompatActivity() {
companion object {
private const val TAG = "POC"
private const val SERVICE_TYPE = "_http._tcp."
}
private val serviceToResolve = mutableListOf<NsdServiceInfo>()
private var index = 0
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.discover_btn).setOnClickListener {
search()
}
}
private fun search() {
lifecycleScope.launch(Dispatchers.IO) {
val serviceInfo = NsdServiceInfo().apply {
serviceName = "MyServiceTest"
serviceType = SERVICE_TYPE
port = 80
}
val registrationListener = object : NsdManager.RegistrationListener {
override fun onServiceRegistered(NsdServiceInfo: NsdServiceInfo) {}
override fun onRegistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {}
override fun onServiceUnregistered(arg0: NsdServiceInfo) {
}
override fun onUnregistrationFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {}
}
val nsdManager = (getSystemService(Context.NSD_SERVICE) as NsdManager).apply {
registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, registrationListener)
}
// Instantiate a new DiscoveryListener
val discoveryListener = object : NsdManager.DiscoveryListener {
override fun onDiscoveryStarted(regType: String) {
}
override fun onServiceFound(service: NsdServiceInfo) {
serviceToResolve.add(service)
}
override fun onServiceLost(service: NsdServiceInfo) {}
override fun onDiscoveryStopped(serviceType: String) {}
override fun onStartDiscoveryFailed(serviceType: String, errorCode: Int) {
nsdManager.stopServiceDiscovery(this)
}
override fun onStopDiscoveryFailed(serviceType: String, errorCode: Int) {
nsdManager.stopServiceDiscovery(this)
}
}
nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryListener)
delay(5000)
resolveService(nsdManager)
}
}
private fun resolveService(nsdManager: NsdManager) {
if (serviceToResolve.size > index) {
nsdManager.resolveService(serviceToResolve[index], object : NsdManager.ResolveListener {
override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
index++
resolveService(nsdManager)
}
override fun onServiceResolved(serviceInfo: NsdServiceInfo?) {
Log.d(TAG, "onServiceResolved : $serviceInfo || ${serviceInfo?.attributes}")
index++
resolveService(nsdManager)
}
})
} else {
Log.d(TAG, "Nothing to resolve")
}
}
}
此代码在 Android 7 到 11 上正常工作。但在 Android 6 上无法正常工作。我可以正确解析服务,但它不包含任何属性日志:
Log.d(TAG, "onServiceResolved : $serviceInfo || ${serviceInfo?.attributes}")
例如,Android 6.0 的结果:
onServiceResolved : name: TJA470 (TJA470-F40103), type: ._http._tcp, host: /10.0.0.177, port: 80 || {}
这里是 Android 11 的结果:
onServiceResolved : name: TJA470 (TJA470-F40103), type: ._http._tcp, host: /10.0.0.177, port: 80, txtRecord: 1device.type=urn:schemas-hager-com:device:tja470:1device.modelName=TJA470 export=Yes$device.modelURL=http://www.hager.comdevice.hostName=TJA470-F40103device.manufacturer=Hagerdevice.ip=10.0.0.1771device.modelDescription=Hager Pilot Configuration+device.manufacturerURL=http://www.hager.com(device.UDN=uuid:M2VSZEVUELAJYECHAJLU1708device.UPC=470,device.serialNumber=M2VSZEVUELAJYECHAJLU1708device.modelNumber=3.1.15'presentationURL=http://TJA470-F40103:80*device.friendlyName=TJA470 (TJA470-F40103) || {device.type=[117, 114, 110, 58, 115, 99, 104, 101, 109, 97, 115, 45, 104, 97, 103, 101, 114, 45, 99, 111, 109, 58, 100, 101, 118, 105, 99, 101, 58, 116, 106, 97, 52, 55, 48, 58, 49], device.modelName=[84, 74, 65, 52, 55, 48], export=[89, 101, 115], device.modelURL=[104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 104, 97, 103, 101, 114, 46, 99, 111, 109], device.hostName=[84, 74, 65, 52, 55, 48, 45, 70, 52, 48, 49, 48, 51], device.manufacturer=[72, 97, 103, 101, 114], device.ip=[49, 48, 46, 48, 46, 48, 46, 49, 55, 55], device.modelDescription=[72, 97, 103, 101, 114, 32, 80, 105, 108, 111, 116, 32, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110], device.manufacturerURL=[104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 104, 97, 103, 101, 114, 46, 99, 111, 109], device.UDN=[117, 117, 105, 100, 58, 77, 50, 86, 83, 90, 69, 86, 85, 69, 76, 65, 74, 89, 69, 67, 72, 65, 74, 76, 85, 49, 55, 48, 56], device.UPC=[52, 55, 48], device.serialNumber=[77, 50, 86, 83, 90, 69, 86, 85, 69, 76, 65, 74, 89, 69, 67, 72, 65, 74, 76, 85, 49, 55, 48, 56], device.modelNumber=[51, 46, 49, 46, 49, 53], presentationURL=[104, 116, 116, 112, 58, 47, 47, 84, 74, 65, 52, 55, 48, 45, 70, 52, 48, 49, 48, 51, 58, 56, 48], device.friendlyName=[84, 74, 65, 52, 55, 48, 32, 40, 84, 74, 65, 52, 55, 48, 45, 70, 52, 48, 49, 48, 51, 41]}
如您所见,这些属性出现在 Android 11 而不是 Android 6.0。这是 Android 6.0 上的 NSD_SERVICE 的问题还是我开发的 POC 的问题?
NsdServiceInfo
class 已添加到 API 16 中 getAttributes
方法已添加到 API 21 中。所以通常一切都应该工作在 Android 6.0 上正确:(
问题不在我的代码中,而是在 Android SDK 中,根据 this ticket。
在 Android 5 和 6 我需要使用像 Jmdns 这样的第三方库。