一、客户端 DeadObjectException 概述
- 如果客户端意外结束,服务端此时尝试回调客户端,会抛出 DeadObjectException 异常
二、客户端 DeadObjectException 观察记录
1、Callback
- IPlayerCallback.aidl,这里是位于 src/main/java/com/my/common 包下
package com.my.common;
interface IPlayerCallback {
void onSongChanged(String songName);
void onPlayStateChanged(boolean isPlaying);
}
2、AIDL
- IMyAidlInterface.aidl,这里是位于 src/main/java/com/my/common 包下
package com.my.common;
import com.my.common.IPlayerCallback;
interface IMyAidlInterface {
void play();
void pause();
void registerCallback(IPlayerCallback callback);
void unregisterCallback();
}
3、Server
private IPlayerCallback callback;
private String songName;
private boolean isPlaying = false;
private final IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
@Override
public void play() throws RemoteException {
if (isPlaying) {
Log.i(TAG, "play: already playing");
return;
}
isPlaying = true;
if (callback == null) {
Log.i(TAG, "play: callback is null");
return;
}
callback.onPlayStateChanged(isPlaying);
if (songName == null) {
songName = "Server Song";
callback.onSongChanged(songName);
}
}
@Override
public void pause() throws RemoteException {
if (!isPlaying) {
Log.i(TAG, "pause: not playing");
return;
}
isPlaying = false;
if (callback == null) {
Log.i(TAG, "pause: callback is null");
return;
}
callback.onPlayStateChanged(isPlaying);
}
@Override
public void registerCallback(IPlayerCallback callback) throws RemoteException {
ServerService.this.callback = callback;
}
@Override
public void unregisterCallback() throws RemoteException {
ServerService.this.callback = null;
}
};
try {
myAidlInterface.play();
} catch (RemoteException e) {
e.printStackTrace();
}
try {
myAidlInterface.pause();
} catch (RemoteException e) {
e.printStackTrace();
}
4、Client
try {
myAidlInterface.play();
Log.i(TAG, "play method success");
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "play method error: " + e.getMessage());
}
try {
myAidlInterface.pause();
Log.i(TAG, "pause method success");
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "pause method error: " + e.getMessage());
}
try {
myAidlInterface.registerCallback(new IPlayerCallback.Stub() {
@Override
public void onSongChanged(String songName) throws RemoteException {
Log.i(TAG, "now thread: " + Thread.currentThread().getName());
Log.i(TAG, "onSongChanged: " + songName);
}
@Override
public void onPlayStateChanged(boolean isPlaying) throws RemoteException {
Log.i(TAG, "now thread: " + Thread.currentThread().getName());
Log.i(TAG, "onPlayStateChanged: " + isPlaying);
}
});
Log.i(TAG, "registerCallback method success");
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "registerCallback method error: " + e.getMessage());
}
try {
myAidlInterface.unregisterCallback();
Log.i(TAG, "unregisterCallback method success");
} catch (RemoteException e) {
e.printStackTrace();
Log.e(TAG, "unregisterCallback method error: " + e.getMessage());
}
5、Test
(1)Test 1
服务连接成功
registerCallback method success
now thread: main
onPlayStateChanged: true
now thread: main
onSongChanged: Server Song
play method success
服务连接成功
onPlayStateChanged: false
结束 Client
Server:调用 play,输出结果如下
android.os.DeadObjectException
(2)Test 2
服务连接成功
registerCallback method success
now thread: main
onPlayStateChanged: true
now thread: main
onSongChanged: Server Song
play method success
结束 Client
Server:调用 bindService,输出结果如下
服务连接成功
pause: not playing
play: callback is null
6、小结
Test 1 测试小结:如果客户端意外结束,服务端此时尝试回调客户端,会抛出 DeadObjectException 异常
Test 2 测试小结:出现了两个不同的 Service 实例
三、通过 onCreate 验证
1、Server
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate: " + this);
}
2、Test
(1)Test 1
onCreate: com.my.server.service.ServerService@e3e25df
服务连接成功
registerCallback method success
now thread: main
onPlayStateChanged: true
now thread: main
onSongChanged: Server Song
play method success
服务连接成功
onPlayStateChanged: false
结束 Client
Server:调用 play,输出结果如下
android.os.DeadObjectException
(2)Test 2
onCreate: com.my.server.service.ServerService@7e74c7e
服务连接成功
registerCallback method success
now thread: main
onPlayStateChanged: true
now thread: main
onSongChanged: Server Song
play method success
结束 Client
Server:调用 bindService,输出结果如下
onCreate: com.my.server.service.ServerService@c2244cf
服务连接成功
pause: not playing
play: callback is null
四、客户端死亡回调
1、基本介绍
在注册客户端回调时,可以获取客户端的 Binder 对象,调用 Binder 对象的 linkToDeath 方法,注册死亡回调,监听客户端是否挂了
当客户端挂了,服务端会收到 binderDied 回调,调用 Binder 对象的 unlinkToDeath 方法,注销死亡回调,同时,将客户端回调设置为 null
2、演示
(1)Server
@Override
public void registerCallback(IPlayerCallback callback) throws RemoteException {
ServerService.this.callback = callback;
IBinder b = callback.asBinder();
IBinder.DeathRecipient dr = new DeathRecipient() {
@Override
public void binderDied() {
Log.i(TAG, "binderDied");
b.unlinkToDeath(this, 0);
ServerService.this.callback = null;
}
};
b.linkToDeath(dr, 0);
}
(2)Test
服务连接成功
registerCallback method success
now thread: main
onPlayStateChanged: true
now thread: main
onSongChanged: Server Song
play method success
服务连接成功
onPlayStateChanged: false
binderDied
play: callback is null


