Android网络服务发现"超时"?

时间:2014-03-23 03:25:52

标签: android android-nsd

我在Android上使用网络服务发现(NSD)在设备上宣传REST服务器。我的REST服务器包含在android.app.Service的实例中。

onCreate中,我成功启动了REST服务器并注册了我的NSD服务。我可以在网络中的其他设备上看到NSD服务名称(例如 我的服务 )。

在我的onDestroy中,我停止了REST服务器并取消注册了NSD服务。

然而,似乎在开发时,当我推送我的应用程序的新实例(通过Eclipse)时,无法保证将调用服务的onDestroy。这意味着仍然会公布 我的服务 ,下次启动服务时,我最终会使用 我的服务(1) 我的服务(2)

据我所知,NSD会修改服务名称以创建一个唯一的实例。我的问题是:

  1. 如果广告服务不再存在,广告服务的预期超时时间是多少?
  2. 当我推送我的应用的新实例时,有没有办法确保我的onDestroy被调用?这种情况是否与用户在安装我的应用程序更新时可能遇到的情况类似?即,当正在运行的应用程序关闭时,保证会调用onDestroy,以便可以安装该应用程序的新版本吗?
  3. 我的应用程序中是否有办法检测旧注册并将其删除?

2 个答案:

答案 0 :(得分:5)

首先,AOSP问题跟踪器上有一个open issue tracking this problem。提交错误的人可以在所有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并正在正确清理它。您可以通过查看源here来深入了解NsdService日志。

总结一下,我会回复提示中的问题:

  1. 对于4.x没有超时,它会一直保持到重新启动。对于5.x NsdService,当您的应用断开连接时,会关闭NSD服务。
  2. 无法保证调用onDestroy(),更深入的解释here。通过Android Studio进行安装,无需调用即可查看正在运行的应用程序如果通过App Store的更新行为相同或更优雅地关闭正在运行的应用程序,那将会很有趣。
  3. 5.x中没有问题,因为它会立即杀死它们。在4.x中,由于您立即失去注册侦听器,因此无法删除旧注册。

答案 1 :(得分:0)

关于要点2)和3),您可以执行以下操作:

  • 在服务的onCreate()方法中,生成随机数或时间戳并将其保存到本地字段;这将是服务 ID
  • BroadcastReceiver注册自定义Service,它会 对您的自定义 ACTION
  • 做出反应
  • 在每次Service创建时,使用您的自定义 ACTION 和您当前的Service ID 作为额外参数发送广播
  • 对于每个有效Service,将触发注册的BroadcastReceiver;现在将收到的 ID 与当前服务的 ID 进行比较
    • 如果不同,请调用stopSelf()

这样,只有最后一个Service才会活着。