我有同样的需求,在一个加速度计读取服务和一个可以启动/停止服务并显示当前平均加速度计幅度的应用程序中。
我使用服务绑定允许服务向活动发送消息,其中包含加速度计值。
有关绑定的背景信息,请参阅http://developer.android.com/guide/components/bound-services.html#Messenger。有关一个很好的示例,请参阅 API 示例的 MessengerServiceActivities 和 MessengerService 类。
我做了以下。为了清楚起见,我省略了平凡的细节(例如同步以避免比赛)。请注意,我使用了 bind() 和 StartService()。bind() 用于在 Activity 和 Service 之间发送消息;StartService() 是这样服务在活动退出后继续运行。
基本上,Activity 和 Service 交换 Messenger,允许彼此向对方发送消息。Activity 向服务发送自定义消息,以便订阅服务消息或取消订阅服务消息。当 Service 要向 Activity 发送数据时,它会向 Activity 的 Messenger 发送自定义消息。Activity 收到这样的消息后,会向用户显示新值。
建议使用通知的答案使用一种简单的方法将数据显示到屏幕上。如果您想在 Activity 中显示数据(相对于通知栏),则需要这种更复杂的消息传递答案。
对于以下示例代码的长度,我深表歉意,但有很多必要的细节需要传达。
在我的 Activity 中,名为 AccelServiceControl:
private FromServiceHandler handler; // My custom class for Handling Messages from my Service.
private Messenger fromService; // For receiving messages from our Service
...
public void onCreate(Bundle savedInstanceState) {
...
handler = new FromServiceHandler(this);
fromService = new Messenger(handler);
...
}
protected void onResume() {
...
// While we're in the foreground, we want to be bound to our service.
// onServiceConnected() will return the IBinder we'll use to communicate back and forth.
bindService(new Intent(this, AccelService.class), this, Context.BIND_AUTO_CREATE);
}
protected void onPause() {
...
// Note: By itself, this doesn't stop the Service from sending messages to us.
// We need to send a custom Unsubscribe Message to stop getting messages from the Service.
unbindService(this);
}
public void onClick(View v) {
// Send a custom intent to start or stop our Service.
if (buttonStart == v) {
startService(new Intent(AccelService.ACTION_START));
} else if (buttonStop == v) {
startService(new Intent(AccelService.ACTION_STOP));
}
...
}
public void onServiceConnected(ComponentName name, IBinder service) {
...
// Ask our Service to send us updates.
toService = new Messenger(service);
Message msg = Message.obtain(null, FromClientHandler.MSG_SUBSCRIBE); // our custom Subscribe message
msg.replyTo = fromService;
try {
toService.send(msg);
} catch (RemoteException e) {
// Failed because the Service has died.
// We handle this in onServiceDisconnected().
}
}
在 Activity 的自定义消息处理程序中:
....
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ACCEL_UPDATE:
...
Bundle bundle = msg.getData();
double accelValue = bundle.getDouble(ACCEL_UPDATE_VALUE);
...then display the new accelValue in, for example, a TextView.
...
}
}
在名为 AccelService 的服务中:
...
private Messenger fromClient; // For receiving messages from our Client(s).
private FromClientHandler handler; // needed just for unlinking at in onDestroy().
// Since we have only one Client, we store only one Activity's Messenger
private Messenger subscribedMessenger;
public void onCreate() {
...
handler = new FromClientHandler(this);
fromClient = new Messenger(handler);
}
public void onDestroy() {
// Unlink ourselves from our Handler, so the Garbage Collector can get rid of us. That's a topic in itself.
handler.unlink();
....
}
public int onStartCommand(Intent intent, int flags, int startId) {
...
int returnValue = START_NOT_STICKY;
String action = intent.getAction();
if (ACTION_START.equals(action)) {
doActionStart();
returnValue = START_STICKY;
} else if (ACTION_STOP.equals(action)) {
...
// Our Service is done
stopSelf();
}
...
return returnValue;
}
public IBinder onBind(Intent intent) {
// Hand back a way to send messages to us.
return fromClient.getBinder();
}
...when we want to send data to the Activity:
Message msg = Message.obtain(null, FromServiceHandler.MSG_ACCEL_UPDATE);
Bundle bundle = new Bundle();
bundle.putDouble(FromServiceHandler.ACCEL_UPDATE_VALUE, avgAccel);
msg.setData(bundle);
try {
subscribedMessenger.send(msg);
} catch (RemoteException e) {
// Failed because the Client has unbound.
subscribedMessenger = null;
}