远程服务拒绝绑定权限

17

我有一个远程服务,外部应用程序可以绑定到它上面。在某些情况下,我可能会拒绝绑定请求。根据文档

返回与服务通信的通道。如果客户端无法绑定到服务,则可以返回null。

@Override
public IBinder onBind(final Intent intent) {
    return null;
}

返回 null 的确不会返回一个 IBinder 对象,因此会阻止连接,但是调用应用程序并不能正确地接收到这个“信息”。

boolean bound = context.bindService(intent, serviceConnection, flagsHere);
无论从服务返回 null 还是其他值,该方法始终返回 true 吗?
根据文档
返回值 - 如果你已经成功绑定到服务,则返回 true;如果连接未建立,将返回 false,因此您将无法收到服务对象。
我曾认为从onBind返回 null 会导致 bindService 返回 false。做出假设从来不是一个好主意...
但是,返回 null 确实会阻止ServiceConnection实例化调用,但这样做的后果是在onServiceConnected中没有检查 binder 是否实际上为 null 的选项。
因此,我的问题是 - 应用程序如何“知道”绑定请求已被拒绝? 另外,如果我决定即时拒绝对onRebind(之前已从onUnbind返回 true)的请求,则似乎无法覆盖此行为:
@Override
public void onRebind(final Intent intent) {

    if (shouldAllowRebind(intent)) {
        super.onRebind(intent);
    } else {
        // ?
    }
}

我希望有人能为我解惑。先行致谢。


4
bindService() 的返回值已经成为一个问题已经有一段时间了。 “应用程序如何‘知道’绑定请求是否被拒绝?”——可能是因为它的 ServiceConnection 没有被调用,也就是没有执行 onServiceConnected() 方法。 - CommonsWare
感谢@CommonsWare,我希望你能看到这个问题!由于bindService()返回了true,应用程序被留在'limbo'状态中,期望ServiceConnection调用onServiceConnected()。由于它没有(由于行为不当),您是否建议监视线程等待几秒钟,然后检查一个布尔标识符是否已发出方法调用的信号?否则,将使用的上下文标记为null,并希望GC会将其整理干净?我担心Android会认为应用程序已绑定到服务并将其保留在内存中。 - brandall
你会建议一个监视线程,等待几秒钟,然后检查布尔标识符是否已经发出方法调用的信号吗?个人而言,我会尝试以其他方式解决整个问题(例如,拒绝绑定器的单个API调用),而不是尝试拒绝绑定。在这种实现中,使用某些东西来实现超时(例如,View上的postDelayed())可能是您最好的选择。否则,将使用的上下文标记为null并希望GC将其清理干净?抱歉,我没有理解这部分内容。 - CommonsWare
@CommonsWare 谢谢。在绑定请求之前拒绝可能在某些情况下不可行,我不会详细解释原因。我担心Android会认为应用程序已绑定到服务并将其保存在内存中 - 我只保持了对使用的上下文的弱引用 - 我需要了解是否该上下文仍与服务相关联。我会进行调查。我可能过于考虑了那一部分。 - brandall
1个回答

7
您可能需要创建一个解决方案。这里有两个选项:
  • 如果请求被拒绝,则返回没有任何功能的Binder,然后客户端必须检查是否存在所需功能。
  • 始终返回相同的Binder,但让每个方法在不允许调用时抛出Exception(例如SecurityException)。 (这也是@CommonsWare在评论中提出的建议)
我个人更喜欢第二种方法,因为它更具灵活性。 (例如允许每次调用的许可/拒绝,解决重新绑定后拒绝内容的问题等)。

谢谢您的回答 - 您能在代码中引用 bindService 不会同步创建 Service 的位置吗?对于 您确定 onServiceConnected 没有被调用吗?,您百分之百确定这对您没有发生过吗?我会更正我的问题措辞,我认为 invoked 可能是更好的术语,而不是 instantiated - brandall
最简单的方法是查看onBind调用的来源:它来自于Handler。正如您可能知道的那样,Handlers主要用于异步(进程间)通信。http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/app/ActivityThread.java#1391 - F43nd1r
你的回答第一段完全是错误的。如果添加简单的断点,你会发现 bindService 正在等待 onBind 的响应,在此之前,无论服务是否正在运行,都会调用 onStartCommand。我不确定你在评论中的意思 - 是指系统将使用 IPC 来通信 onBind 的响应吗? - brandall
断点不是确定不同线程调用顺序的可靠方法,因为线程可能会并行执行(使用多核和虚拟并行化)。但无论如何,这都不会影响结果。无论你称其为预期行为还是解决方法,都不会改变你的代码。 - F43nd1r
请问您能否删除对probably with instanceof的引用 - 它只是一个BinderProxy,所以不起作用,但我想在我即将发布的解决方法中引用您的想法,即如果请求被拒绝,则返回一个没有任何功能的Binder。然后客户端必须检查是否存在所需的功能,如果我不得不纠正您会更好吗?我不会接受您或我的帖子作为答案,因为两者都是处理此问题的一种方式,而不是实际的解决方案或解释。感谢您的建议。 - brandall
显示剩余4条评论

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