在Android开发中,有时候我们需要让一个Activity绑定一个Service,进行两者之间的通信。当Activity绑定成功以后,就可以调用Service中的public(或有对应可见级别)的方法。如果Service想把一些信息反馈给Activity,则需要将Activity的Listener传递给Service,由Service负责调用。
这样的做法是可以实现功能的,但有一些缺憾。
首先,Service需要把被调用的方法做成public的,不利于隐藏实现。
第二,调用显得凌乱,在Activity中调用了Service的方法,或者在Service中调用Activity的方法。
所以,developer文档提供了另外一种方式,使用Messenger。API Demos也给出了实现的示例,但该示例没有给出Service如何回应Activity部分的实现,只是给了一段提示性的说明文档:
https://developer.android.com/guide/components/bound-services.html
Notice that this example does not show how the service can respond to the client. If you want the service to respond, you need to also create a Messenger in the client. When the client receives the onServiceConnected() callback, it sends a Message to the service that includes the client's Messenger in the replyTo parameter of the send() method.
根据这个提示,我做了一些实验,走通了Service回应Activity的流程。
Activity与Service之间的通信,无论是Service向Activity发送消息,还是Activity发送消息,都通过Messenger类,这样,Service和Activity就不需要提供public的方法作为通信接口。
首先创建一个工程,实现了如下功能,有一个Activity,上面有三个Button和一个TextView,点击任何一个button,Activity的send messenger就会向Service发送一个message,这个message的replayTo,是Activity的另外一个Messenger, 叫receive messenger。service收到message以后。进行相应的处理,例如生成一个integer,float,string,把处理结果通过receive messenger发送出去,Activity就会收到这个消息。
下面是完整代码,只有3个Class,其他都是AndroidStudio自动生成的。
MainActivity
public class MainActivity extends AppCompatActivity {
/*
标记是否已经绑定Service。
Marking whether the service has been bound.
*/
private boolean bServiceConnected;
/*
这个Messenger用于向Service发送Message。
This Messenger is used to send message to service.
*/
private Messenger mSendMessenger;
/*
这个Messenger用于接收服务器发送的Message。
This Messenger is used to receive message from service.
*/
private Messenger mReceiveMessenger;
private TextView mMessageText;
/*
处理从Service收到的Message。
Handling Messages received from service.
*/
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MessageSource.MSG_CREATE_FLOAT:
String strI = (String) msg.obj;
mMessageText.setText(strI);
break;
case MessageSource.MSG_CREATE_INT:
String strF = (String) msg.obj;
mMessageText.setText(strF);
break;
case MessageSource.MSG_CREATE_STRING:
String strS = (String) msg.obj;
mMessageText.setText(strS);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMessageText = (TextView) findViewById(R.id.message_from_service);
Button createIntBt = (Button) findViewById(R.id.let_service_create_int);
createIntBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleButtonClick(MessageSource.MSG_CREATE_INT);
}
});
Button createFloatBt = (Button) findViewById(R.id.let_service_create_float);
createFloatBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleButtonClick(MessageSource.MSG_CREATE_FLOAT);
}
});
Button createStringBt = (Button) findViewById(R.id.let_service_create_string);
createStringBt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
handleButtonClick(MessageSource.MSG_CREATE_STRING);
}
});
}
@Override
protected void onResume() {
super.onResume();
if (!bServiceConnected) {
bindService();
}
}
@Override
protected void onPause() {
super.onPause();
unbindService(mServiceConnection);
}
private void handleButtonClick(int type) {
if (bServiceConnected) {
Message msg = new Message();
msg.what = type;
msg.replyTo = mReceiveMessenger;
try {
mSendMessenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
Toast.makeText(this, "Service has not been bound.", Toast.LENGTH_SHORT).show();
}
}
private void bindService() {
Intent intent = new Intent(getApplicationContext(), MainService.class);
bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
bServiceConnected = true;
mSendMessenger = new Messenger(iBinder);
mReceiveMessenger = new Messenger(mHandler);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
bServiceConnected = false;
mSendMessenger = null;
mReceiveMessenger = null;
}
};
}
MainService
public class MainService extends Service {
/*
这个Handler负责接收Activity的Message,收到一个Message时,通过获取Message的replayTo得到一个Messenger实例,
使用这个Messenger向Activity发送Message。
This Handler is in charge of receiving Messages sending from Activity. When it receiving a
Message, get The replayTo which is a Messenger instance from this Message. Using this Messenger
to send Message to Activity.
*/
private Handler mActMsgHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MessageSource.MSG_CREATE_INT:
createAndSendInt(msg.replyTo);
break;
case MessageSource.MSG_CREATE_FLOAT:
createAndSendFloat(msg.replyTo);
break;
case MessageSource.MSG_CREATE_STRING:
createAndSendString(msg.replyTo);
break;
default:
break;
}
}
};
/*
这个Messenger用于向Activity发送Message。
This Messenger is used to send Message to Activity.
*/
private Messenger mSendMessenger = new Messenger(mActMsgHandler);
/*
假设有耗时的操作需要异步进行。
Suppose we have long-running jobs and execute asynchronously.
*/
private Executor mExecutor = Executors.newCachedThreadPool();
public MainService() {
}
@Override
public IBinder onBind(Intent intent) {
return mSendMessenger.getBinder();
}
private void createAndSendInt(final Messenger messenger) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
Random random = new Random();
int ret = random.nextInt();
String str = "Give you a int: " + ret;
send(MessageSource.MSG_CREATE_INT, str, messenger);
}
});
}
private void createAndSendFloat(final Messenger messenger) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
Random random = new Random();
float ret = random.nextFloat();
String str = "Give you a float: " + ret;
send(MessageSource.MSG_CREATE_FLOAT, str, messenger);
}
});
}
private void createAndSendString(final Messenger messenger) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
int len = MessageSource.STRING_SOURCE_ARRAY.length;
Random random = new Random();
int index = random.nextInt(len);
String ret = MessageSource.STRING_SOURCE_ARRAY[index];
String str = "Give you a string: " + ret;
send(MessageSource.MSG_CREATE_STRING, str, messenger);
}
});
}
private void send(int type, String str, Messenger messenger) {
Message msg = new Message();
msg.what = type;
msg.obj = str;
try {
messenger.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
还有一个辅助的Class
MessageSource
public class MessageSource {
public static final int MSG_CREATE_INT = 1;
public static final int MSG_CREATE_FLOAT = 2;
public static final int MSG_CREATE_STRING = 3;
public static final String[] STRING_SOURCE_ARRAY = new String[]{"Awake from dreams",
"I find the locked tower high",
"Sober from wine", "I see the curtain hanging low",
"As last year spring grief seems to grow",
"Amid the falling blooms alone stand I",
"In the fine rain a pair of swallows fly",
"I still remember when I first saw pretty Ping",
"In silken dress embroidered with two hearts in a ring",
"Revealing lovesickness by touching pipa’s string",
"The moon shines bright just as last year",
"It did see her like a cloud disappear"};
}
应用截图和操作说明,当点击 CREATE A INTEGER按钮时,Activity就会向Service发送一个Message。
Service收到这个Message以后,根据Message的what,产生了一个Integer,然后把这个integer拼接到一个字符串后面。
创建一个Message,然后用收到的Message的replayTo,发送出去。Activity就收到了Service发来的Message,然后更新TextView里面的内容。