Mic*_*rov 10 java service client android bind
我在远程进程中有一个android服务,可以有来自不同客户端的多个绑定.我的问题是,当特定绑定客户端意外断开连接时(即客户端崩溃),如何通知服务?我无法使用onUnbind(),因为只有在所有客户端断开连接后才会调用它.
public class MyService extends Service {
final Messenger mServiceMessenger = new Messenger(new IncomingHandler());
@Override
public IBinder onBind(Intent intent) {
return mServiceMessenger.getBinder();
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
// Handling messages logic...
}
}
}
Run Code Online (Sandbox Code Playgroud)
这可以通过机制来完成Binder.linkToDeath()- 您必须要求每个客户端发送new Binder()他们发起的对象,然后链接到他们(您的客户端)的死亡。我将解释如何使用AIDL文件执行此操作。
(你可以选择任何android IPC机制,只要你可以将Binder对象从你的客户端传递到你的服务)
代码示例 -
.AIDL 在文件内部- 创建一个方法将IBinder对象从客户端传递到服务
void registerProcessDeath(in IBinder clientDeathListener, String packageName);
Run Code Online (Sandbox Code Playgroud)
在客户端- 初始化一个新对象并通过 AIDL 接口将其传递给您的服务。
public void onServiceConnected(ComponentName className, IBinder service) {
mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
//Call the registerProcessDeath method from the AIDL file and pass
//the new Binder object and the client's package name
mIMyAidlInterface.registerProcessDeath(new Binder(),getPackageName());
}
Run Code Online (Sandbox Code Playgroud)
在服务端——
1. 获取客户的Binder并注册到他的linkToDeath(). 2.使用helper类通过android的IBinder.DeathRecipient类
来处理所有客户端
public class MyService extends Service {
//Helper class to handle all client's deaths.
private volatile ClientsDeathWatcher mClientsList;
@Override
public IBinder onBind(Intent intent) {
mClientsList = new ClientsDeathWatcher();
return mStub;
}
private final IMyAidlInterface.Stub mStub = new IMyAidlInterface.Stub() {
@Override
public void registerProcessDeath(IBinder cb, String packageName){
boolean isRegistered = mClientsList.register(cb , packageName);
}
};
}
//This is thread-safe helper class to handle all
//the client death related tasks.
//All you care abut is the clientDeath() method.
public class ClientsDeathWatcher {
private ArrayMap<String, DeathCallBack> mCallbacks = new ArrayMap<>();
private final class DeathCallBack implements IBinder.DeathRecipient {
private String pn;
private IBinder mBinder;
DeathCallBack(String packageName,IBinder binder) {
pn = packageName;
mBinder = binder;
}
public void binderDied() {
synchronized (mCallbacks) {
mBinder.unlinkToDeath(this,0);
clientDeath(pn);
}
}
}
//To be called only from thread-safe functions
private void clientDeath(String packageName) {
mCallbacks.remove(packageName);
//Do your stuff here.
//$$$$$$$$$
}
public boolean register(IBinder token, String packageName) {
synchronized (mCallbacks) {
try {
if (!mCallbacks.containsKey(packageName)) {
DeathCallBack mDeathCallBack = new DeathCallBack(packageName,token);
mCallbacks.put(packageName, mDeathCallBack);
//This is where the magic happens
token.linkToDeath(mDeathCallBack, 0);
}
return true;
} catch (RemoteException e) {
e.printStackTrace();
return false;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用您拥有的 IncomingHandler 处理程序,并从客户端发送一条消息,表明在调用 unbindService(serviceConnection) 之前它将被解除绑定,保留信使(客户端)的数组列表,并在收到消息时添加/删除。
您还可以尝试发送虚拟消息,如果收到 RemoteException 则意味着远程客户端已死亡。
检查这个例子http://developer.android.com/reference/android/app/Service.html
提炼:
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
mClients.add(msg.replyTo);
break;
case MSG_UNREGISTER_CLIENT:
mClients.remove(msg.replyTo);
break;
case MSG_SET_VALUE:
mValue = msg.arg1;
for (int i=mClients.size()-1; i>=0; i--) {
try {
mClients.get(i).send(Message.obtain(null,
MSG_SET_VALUE, mValue, 0));
} catch (RemoteException e) {
// The client is dead. Remove it from the list;
// we are going through the list from back to front
// so this is safe to do inside the loop.
mClients.remove(i);
}
}
break;
default:
super.handleMessage(msg);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2775 次 |
| 最近记录: |