为什么我不能从同一个对象两次绑定到我的前台服务?
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
实例。
我在应用程序 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
实例。