此外Service+Binder机制也可以实现很好的通信,但这种通信过于繁琐和过于侵入式,导致耦合问题非常严重。如下代码是使用Binder机制的中一种方式。
一、暴露接口方式
服务端
public class MyService extends Service {
private final String tag = "MyService";
@Override
public IBinder onBind(Intent intent)
{
Log.d(tag, "onBind");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(tag, "onUnbind");
return super.onUnbind(intent);
}
@Override
public void onCreate()
{
Log.d(tag, "onCreate");
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
Log.d(tag, "onStart");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(tag, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(tag, "onDestroy");
super.onDestroy();
}
public class MyBinder extends Binder
{
MyService getService()
{
return MyService.this;
}
}
}
客户端
public class MyServiceConnection implements ServiceConnection
{
private Service mService = null;
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
Log.d("ServiceClient", "绑定解除");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = ((MyService.MyBinder) service).getService();
Log.d("ServiceClient", "绑定成功");
}
}
二、Binder 原生通信
服务端实现
/**
* Created by Jay on 2015/8/18 0018.
*/
public class IPCService extends Service {
private static final String DESCRIPTOR = "IPCService";
private final String[] names = { "B神", "艹神", "基神", "J神", "翔神" };
private MyBinder mBinder = new MyBinder();
private class MyBinder extends Binder {
@Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
case 0x001: {
data.enforceInterface(DESCRIPTOR);
int num = data.readInt();
reply.writeNoException();
reply.writeString(names[num]);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
可以看到onTransact有四个参数
code , data ,replay , flags
- code 是一个整形的唯一标识,用于区分执行哪个方法,客户端会传递此参数,告诉服务端执行哪个方法;
- data客户端传递过来的参数;
- replay服务器返回回去的值;
- flags标明是否有返回值,0为有(双向),1为没有(单向)。
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText edit_num;
private Button btn_query;
private TextView txt_result;
private IBinder mIBinder;
private ServiceConnection PersonConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mIBinder = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIBinder = service;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindViews();
// 绑定远程Service
Intent service = new Intent("android.intent.action.IPCService");
service.setPackage("com.jay.ipcserver");
bindService(service, PersonConnection, BIND_AUTO_CREATE);
btn_query.setOnClickListener(this);
}
private void bindViews() {
edit_num = (EditText) findViewById(R.id.edit_num);
btn_query = (Button) findViewById(R.id.btn_query);
txt_result = (TextView) findViewById(R.id.txt_result);
}
@Override
public void onClick(View v) {
int num = Integer.parseInt(edit_num.getText().toString());
if (mIBinder == null) {
Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();
} else {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
String _result = null;
try {
_data.writeInterfaceToken("IPCService");
_data.writeInt(num);
mIBinder.transact(0x001, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
txt_result.setText(_result);
edit_num.setText("");
} catch (RemoteException e) {
e.printStackTrace();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
}