详细的资料还是在官网看吧这个准确:Android 接口定义语言 (AIDL).
双向通信的话说白了就是在服务端里面设置回调.然后客户端注册回调接口实现双向.同时系统也提供了RemoteCallbackList这个类方便了我们负责维护远程接口列表的繁琐工作,可用于执行从Service到其客户端的回调 .
定义统一的AIDL
package com.message.client;
// Declare any non-default types here with import statements
interface IRemoteCallBackListener {
void onLoginSuccess(String msg);
void onLoginFail(String msg);
void onLogoutSuccess(String msg);
void onLogoutFail(String msg);
}
//----------------------------------------------------------------------------------------------------------------------------------
//注意在aidl文件里面引用包
package com.message.client;
import com.message.client.IRemoteCallBackListener;
interface IRemoteService {
void login(String userName , String passWord , String packageName);
void logout(String packageName);
boolean isLogin();
void registerListener(in IRemoteCallBackListener listener); //注册回调
void unregisterListener(in IRemoteCallBackListener listener); //删除回调
}
Server端
// manifest需要添加的地方
<service
android:name=".GuideServer">
<intent-filter>
<action android:name="com.message.action.GUIDE"/>
</intent-filter>
</service>
public class GuideServer extends Service{
private RemoteCallbackList<IRemoteCallBackListener> mRemoteCallbackList = new RemoteCallbackList<>();
private IRemoteService.Stub mBinder = new IRemoteService.Stub() {
@Override
public void login(final String userName, final String passWord, String packageName) throws RemoteException {
new Thread(new Runnable() {
@Override
public void run() {
//模拟延迟任务
try {
Thread.sleep(2000);
if (userName.equals("huluwa") && passWord.equals("123456")) {
loginSuccessCallback("登录成功: "+userName);
} else {
loginFailCallback("登录失败: "+userName);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public void logout(final String packageName) throws RemoteException {
new Thread(new Runnable() {
@Override
public void run() {
//模拟延迟任务
try {
Thread.sleep(2000);
if(packageName.equals("com.message.client")){
logoutSuccessCallback("退出成功!");
}else{
logoutFailCallback("退出失败!");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public boolean isLogin() throws RemoteException {
return false;
}
@Override
public void registerListener(IRemoteCallBackListener listener) throws RemoteException {
LoginClient loginClient = new LoginClient();
if (listener != null) {
mRemoteCallbackList.register(listener);
try {
//
listener.asBinder().linkToDeath(loginClient, 0);
} catch (RemoteException e) {
Log.d("GuideServer", "XXXListener already died.", e);
}
}
}
@Override
public void unregisterListener(IRemoteCallBackListener listener) throws RemoteException {
if (listener != null) {
mRemoteCallbackList.unregister(listener);
}
}
};
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
private void loginSuccessCallback(String msg) throws RemoteException{
final int N = mRemoteCallbackList.beginBroadcast();
for(int i = 0 ;i < N; i++){
IRemoteCallBackListener broadcastItem = mRemoteCallbackList.getBroadcastItem(i);
if(broadcastItem != null){
try{
broadcastItem.onLogoutSuccess(msg);
}catch (Exception e){
e.printStackTrace();
}
}
mRemoteCallbackList.finishBroadcast();
}
}
private void loginFailCallback(String msg) throws RemoteException{
final int N = mRemoteCallbackList.beginBroadcast();
for(int i = 0 ;i < N; i++){
IRemoteCallBackListener broadcastItem = mRemoteCallbackList.getBroadcastItem(i);
if(broadcastItem != null){
try{
broadcastItem.onLogoutSuccess(msg);
}catch (Exception e){
e.printStackTrace();
}
}
}
mRemoteCallbackList.finishBroadcast();
}
private void logoutSuccessCallback(String msg) throws RemoteException{
final int N = mRemoteCallbackList.beginBroadcast();
for(int i = 0 ;i < N; i++){
IRemoteCallBackListener broadcastItem = mRemoteCallbackList.getBroadcastItem(i);
if(broadcastItem != null){
try{
broadcastItem.onLogoutSuccess(msg);
}catch (Exception e){
e.printStackTrace();
}
}
mRemoteCallbackList.finishBroadcast();
}
}
private void logoutFailCallback(String msg) throws RemoteException{
final int N = mRemoteCallbackList.beginBroadcast();
for(int i = 0 ;i < N; i++){
IRemoteCallBackListener broadcastItem = mRemoteCallbackList.getBroadcastItem(i);
if(broadcastItem != null){
try{
broadcastItem.onLogoutFail(msg);
}catch (Exception e){
e.printStackTrace();
}
}
mRemoteCallbackList.finishBroadcast();
}
}
//
private class LoginClient implements IBinder.DeathRecipient {
@Override
public void binderDied() {
Log.d("GuideServer", "BinderDied.");
//todo something
}
}
}
Client端
注意客户端的AIDL.
public class MainActivity extends AppCompatActivity {
private TextView tv_style;
private EditText et_accotun;
private EditText et_password;
private Button btn_login;
private Button btn_logout;
private IRemoteService iRemoteService;
boolean isConnect;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
iRemoteService = IRemoteService.Stub.asInterface(iBinder);
tv_style.setText("当前状态:\n连接成功");
isConnect = true;
try {
iRemoteService.registerListener(iRemoteCallBackListener);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
tv_style.setText("当前状态:\n连接断开");
isConnect = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_style = findViewById(R.id.tv_style);
et_accotun = findViewById(R.id.et_accotun);
et_password = findViewById(R.id.et_password);
btn_login = findViewById(R.id.btn_login);
btn_logout = findViewById(R.id.btn_logout);
Intent intent = new Intent();
intent.setAction("com.message.action.GUIDE");
intent.setPackage("com.message.server");
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(isConnect){
try {
Log.e("TAG","btn_login");
iRemoteService.login(String.valueOf(et_accotun.getText()),String.valueOf(et_password.getText()) , getPackageName());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
btn_logout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(isConnect){
try {
iRemoteService.logout(getPackageName());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
try {
iRemoteService.unregisterListener(iRemoteCallBackListener);
} catch (RemoteException e) {
e.printStackTrace();
}
unbindService(serviceConnection);
}
private IRemoteCallBackListener iRemoteCallBackListener = new IRemoteCallBackListener.Stub() {
@Override
public void onLoginSuccess(final String msg) throws RemoteException {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_style.setText("当前状态:\n连接成功\n"+msg);
}
});
Toast.makeText(MainActivity.this,"客户端登录成功回调====" + msg,Toast.LENGTH_LONG).show();
}
@Override
public void onLoginFail(final String msg) throws RemoteException {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_style.setText("当前状态:\n连接成功\n"+msg);
Toast.makeText(MainActivity.this,"客户端登录失败回调====" + msg,Toast.LENGTH_LONG).show();
}
});
}
@Override
public void onLogoutSuccess(final String msg) throws RemoteException {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_style.setText("当前状态:\n连接成功\n"+msg);
Toast.makeText(MainActivity.this,"客户端登出成功回调====" + msg,Toast.LENGTH_LONG).show();
}
});
}
@Override
public void onLogoutFail(final String msg) throws RemoteException {
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_style.setText("当前状态:\n连接成功\n"+msg);
Toast.makeText(MainActivity.this,"客户端登出失败回调====" + msg,Toast.LENGTH_LONG).show();
}
});
}
};
结果如下:
关于监听客户端死亡的回调我们使用DeathRecipient这个类就可以了.
参考了这篇文章,做个备份加深理解.