为什么我不能从同一个对象两次绑定到我的前台服务?

Why can't I bind to my foreground service twice from the same object?

我在应用程序 A 中有一个对象实现了 IServiceConnection,它绑定到另一个应用程序(应用程序 B)中的前景 Service

public class MyServiceConnection : Java.Lang.Object, IServiceConnection
{
    private IBinder _binder;
    private TaskCompletionSource<bool> _connectTcs;

    public MyServiceConnection()
    {
        BeginConnect();
    }

    public void BeginConnect() => ConnectAsync().ContinueWith(EndConnect);

    public Task<bool> ConnectAsync(CancellationToken ct = default)
    {
        if (_connectTcs?.IsCompleted ?? true)
        {
            _connectTcs = new TaskCompletionSource<bool>();
            ct.Register(() => _connectTcs.TrySetCanceled(ct));

            var package = "com.sample.appb";
            var componentName = new Componentname(package, $"{package}.ServiceInB");

            var service = new Intent().SetComponent(componentName);
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
            {
                Application.Context.StartForegroundService(service);
            }
            else
            {
                Application.Context.StartService(service);
            }

            Application.Context.BindService(service, this, Bind.AutoCreate);
        }

        return await _connectTcs;
    }

    private void EndConnect(Task task)
    {
        // handle task result
    }

    public void OnServiceConnected(ComponentName name, IBinder service)
    {
        _binder = service;
    }

    public void OnServiceDisconnected(ComponentName name)
    {
        _binder = null;
    }

    // methods that are called on the service
}

创建对象后,我绑定到 Service 并成功。当应用程序 B 崩溃或我在应用程序 B 上调用 am force-stop 时,会调用 OnServiceDisconnected(),这是预期的。我通过再次连接处理丢失的连接,但是在第二个连接上 OnServiceConnected() 从未被调用,所以我从来没有得到我的 IBinder 对象来调用方法。如果我重新启动应用程序 A,我可以再次执行单个绑定。如何在 运行 时间内多次正确获取 Service 活页夹?

为了解决这个问题,我将原始对象拆分为两个对象:一个继承自 IServiceConnection 并保存来自服务的 IBinder,另一个保存这些对象的实例。当持有者需要连接时,它首先处理 IServiceConnection 的任何持有实例,然后用新实例调用 Context.BindService()。当 holder 需要断开连接时,它调用 Context.UnbindService(),然后处置 IServiceConnection 实例。