安卓网络服务发现“超时”是什么意思?

20
我正在Android上使用网络服务发现(NSD)来广告设备上的REST服务器。我的REST服务器被包装在android.app.Service实例中。
onCreate中,我成功启动了REST服务器并注册了我的NSD服务。我可以在网络中的其他设备上看到NSD服务名称(例如My Service)。
在我的onDestroy中,我停止了REST服务器并注销了NSD服务。
然而,在开发过程中,当我通过Eclipse推送新的应用程序实例时,无法保证服务的onDestroy将被调用。这意味着My Service仍然被广告,下一次服务启动时,我会得到My Service(1)My Service(2)等。
我了解NSD将修改服务名称以创建唯一实例。我的问题是:
  1. 如果不再存在,广告服务被删除的预期超时时间是多长?
  2. 是否有一种方法可以确保我的onDestroy在我推送新的应用程序实例时被调用?这种情况是否类似于用户安装我的应用程序更新所经历的情况?即onDestroy是否保证在关闭运行中的应用程序以便安装该应用程序的新版本时被调用?
  3. 是否有一种方法在我的应用程序中检测旧的注册并将其删除?

如果你想确保 onDestroy 方法被调用,可以尝试使用 stopService 方法。 - Philip Liberato
@Philip 我当前的解决方法是有一个按钮,我可以按下停止服务,然后重新安装应用程序。但是,如果我可以得到问题1和3的答案,那么当我发布该应用程序时,我会感觉更好。就此而言,问题2(推送新的应用程序实例)是否相关/类似于通过Google Play推送更新?即,如果/当用户更新版本,服务的onDestroy是否有可能不被调用? - Kerry
1
嗯,如果您满足问题2的条件,那么问题1和3似乎就不是问题了。 - Philip Liberato
1
我也遇到了同样的问题。你找到解决方法了吗? - Anil Maddala
OnDestory可能会被调用,也可能不会被调用,无法确保。您可以尝试使用关闭挂钩来解决一些问题。但是,这也不能保证100%:http://developer.android.com/reference/java/lang/Runtime.html - JohanShogun
Android中不会触发运行时关闭挂钩。我已经测试了onDestroy,它只能在30%的情况下工作。我的另一个想法是有一个通知告诉用户停止服务,并且即使活动被关闭,服务也可以在后台运行。 - Dave Chen
2个回答

6
首先,在AOSP问题跟踪器上有一个追踪此问题的开放问题。提交错误的人可以在所有Android 4.x版本中重现此问题,但未测试5.x。
术语简要说明:
- NsdManager - Android应用程序与之交互以注册其NSD服务并发现其他NSD服务的类。NsdManager实际上只是建立与NsdService的异步连接的外壳。 - 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日志。
总结一下,我将回答提示中的问题:
  1. 对于4.x版本,没有超时时间,它会一直保持到重新启动。对于5.x版本,NsdService会在您的应用程序断开连接时关闭NSD服务。
  2. 无法保证调用onDestroy(),更深入的解释在这里。通过Android Studio安装可能会在不调用该方法的情况下杀死正在运行的应用程序。有趣的是,看看通过应用商店的更新是否以同样的方式或更优雅地关闭正在运行的应用程序。
  3. 在5.x中不存在这个问题,因为它会立即终止它们。在4.x中,由于您立即失去注册侦听器,所以没有办法删除旧的注册。

正是我所需要的。我一直在想为什么我必须重新启动设备才能让NSD工作(在我的测试中)。我很高兴5.x解决了这个问题,但遗憾的是除了使用onPause/onResume(作为最后的手段)之外,真的没有其他办法。 - Dave Chen

0
关于第2)和3)点,您可以执行以下操作:
  • 在您的服务的onCreate()方法中,生成一个随机数或时间戳并将其保存到本地字段中;这将是服务的ID
  • 在您的Service中注册一个自定义BroadcastReceiver,它将响应您的自定义ACTION
  • 在每个Service创建时,发送带有您的自定义ACTION和当前Service ID作为额外参数的广播
  • 对于每个活动的Service,注册的BroadcastReceiver将被触发;现在将接收到的ID与当前服务的ID进行比较
    • 如果它们不同,则调用stopSelf()

通过这种方式,只有最后一个Service会保持活动状态。


你不能在活动结束后注销服务,因为你需要服务监听器。我猜你可以将服务ID设置为时间戳,然后使用最大的ID连接到服务。 - Dave Chen
@DaveChen 一个服务可以在任何时候停止自己(在这种情况下,当它接收到广播时)。活动不重要。 - bonnyz
@DaveChen,我认为在提示中对“服务”这个术语的使用存在一些混淆。我的理解是,当应用程序更新时,Android服务总是被关闭,但它的onDestroy()方法并不总是被调用。这会导致NSD服务“泄漏”。 - Trevor Carothers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接