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

Ker*_*rry 19 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当我推送我的应用程序的新实例时,有没有办法确保我被调用?这种情况是否与用户在安装我的应用程序更新时可能遇到的情况类似?ie是否onDestroy保证在正在运行的应用程序关闭时调用,以便可以安装该应用程序的新版本?
  3. 我的应用程序中有没有办法检测旧注册并删除它们?

Tre*_*ers 5

首先,在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
Run Code Online (Sandbox Code Playgroud)

您可以看到既没有onPause()也没有onDestroy()被调用,因此我的应用程序没有为NSD服务进行明确的清理.NsdService正在检测何时终止客户端的AsyncChannel并正在正确清理它.您可以通过查看源得到NsdService日志更深入的了解这里.

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

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


bon*_*nyz 0

针对2)和3)点,您可以执行以下操作:

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

这样一来,只有最后的人Service才能活着。