我在 Android 上使用网络服务发现 (NSD) 来宣传设备上的 REST 服务器。我的 REST 服务器包含在 android.app.Service 的实例中.
在onCreate
中,我成功启动了REST服务器并注册了我的NSD服务。我可以在我的网络中的其他设备上看到 NSD 服务名称(例如 我的服务)。
在我的 onDestroy
中,我停止了 REST 服务器并取消注册 NSD 服务。
但是,似乎在开发过程中,当我推送我的应用程序的新实例(通过 Eclipse)时,并不能保证会调用服务的 onDestroy
。这意味着 My Service 仍在广告中,下次服务启动时,我以 My Service (1) 结束、我的服务 (2) 等
我了解 NSD 将修改服务名称以创建唯一实例。我的问题是:
- 如果广告服务不再存在,预计将其删除的超时时间是多少?
- 有没有办法确保在我推送我的应用程序的新实例时调用我的
onDestroy
?这种情况是否类似于用户安装我的应用程序更新时可能遇到的情况?也就是说,当正在运行的应用程序关闭时,是否保证会调用onDestroy
以便可以安装该应用程序的新版本? - 我的应用中是否有办法检测旧注册并将其删除?
最佳答案
首先,有一个open issue tracking this problem在 AOSP 问题跟踪器上。提交错误的人可以在所有 Android 4.x 版本中重现,但没有使用 5.x 进行测试。
术语的简要说明:
- NsdManager - Android 应用程序与之交互的类,用于注册其 NSD 服务并发现其他 NSD 服务。 NsdManager 实际上只是一个与 NsdService 建立异步连接的 shell。
- NsdService(com.android.server.NsdService) - 隐藏的 Android 系统服务,可以有来自多个客户端的连接。负责创建和管理 NSD 服务以及将事件传回客户端应用程序的所有繁重工作和簿记工作。
- NSD 服务 - NsdService 代表您创建的服务,用于宣传您的应用在网络上的存在。
我刚刚用 5.1 测试了这个问题,并且问题已得到修复(从源代码看来,该修复已进入 5.0)。我创建了一个简单的应用程序,它只注册一个 NsdService 并在发生任何值得注意的事情时记录下来,包括生命周期事件 onCreate、onResume、onPause 和 onDestroy。通过重新启动、启动我的应用程序,然后通过 Android Studio 重新安装,我得到了以下日志。
W/SimpleNsdActivity(14379): onCreate
D/NsdService( 3516): startMDnsDaemon
D/NsdService( 3516): New client listening to asynchronous messages
D/NsdService( 3516): New client, channel: com.android.internal.util.AsyncChannel
@3c114a11 messenger: android.os.Messenger@3213e776
D/NsdService( 3516): Register service
D/NsdService( 3516): registerService: 2 name: NsdTest, type: _http._tcp., host:
null, port: 1349
W/SimpleNsdActivity(14379): onResume
D/NsdService( 3516): Register 1 2
W/SimpleNsdActivity(14379): onServiceRegistered as NsdTest
D/NsdService( 3516): SERVICE_REGISTERED Raw: 606 2 "NsdTest"
D/NsdService( 3516): Client disconnected
D/NsdService( 3516): Terminating client-ID 1 global-ID 2 type 393225
D/NsdService( 3516): unregisterService: 2
D/NsdService( 3516): stopMDnsDaemon
W/SimpleNsdActivity(15729): onCreate
D/NsdService( 3516): startMDnsDaemon
D/NsdService( 3516): New client listening to asynchronous messages
D/NsdService( 3516): New client, channel: com.android.internal.util.AsyncChannel
@38bace07 messenger: android.os.Messenger@26d8cd5d
D/NsdService( 3516): Register service
D/NsdService( 3516): registerService: 3 name: NsdTest, type: _http._tcp., host:
null, port: 1349
D/NsdService( 3516): Register 1 3
W/SimpleNsdActivity(15729): onResume
D/NsdService( 3516): SERVICE_REGISTERED Raw: 606 3 "NsdTest"
W/SimpleNsdActivity(15729): onServiceRegistered as NsdTest
您可以看到 onPause()
和 onDestroy()
都没有被调用,因此我的应用程序没有对 NSD 服务进行显式清理。 NsdService 正在检测客户端的 AsyncChannel 何时终止并正确清理它。看源码可以更深入的了解NsdService的日志here .
总结一下,我会回答提示中的问题:
- 对于 4.x,没有超时,它会一直保持到重新启动。对于 5.x,NsdService 会在您的应用断开连接时关闭 NSD 服务。
- 没有办法保证onDestroy()被调用,更深的解释here .通过 Android Studio 安装会在不调用它的情况下杀死正在运行的应用程序。看看通过 App Store 进行的更新是否以相同的方式或更优雅地关闭正在运行的应用程序会很有趣。
- 在 5.x 中不是问题,因为它会立即杀死它们。在 4.x 中,无法删除旧注册,因为您会立即失去注册监听器。
关于Android 网络服务发现 "timeout"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22586686/