加速度計読み取りサービスと、サービスを開始/停止し、現在の平均加速度計の大きさを表示するアプリで、同じニーズがありました。
サービス バインディングを使用して、サービスが加速度計の値を含むメッセージをアクティビティに送信できるようにしました。
バインディングの背景については、 http://developer.android.com/guide/components/bound-services.html#Messengerを参照してください。良い例として、API サンプルの MessengerServiceActivities クラスと MessengerService クラスを参照してください。
私は次のことをしました。わかりやすくするために、ありふれた詳細 (競合を避けるための同期など) は省略しています。bind() と StartService() を使用していることに注意してください。bind() は、アクティビティとサービスの間でメッセージを送信するためのものです。StartService() は、アクティビティが終了した後もサービスが実行され続けるようにするためのものです。
基本的に、アクティビティとサービスは互いにメッセージを送信できるメッセンジャーを交換します。アクティビティは、サービス メッセージをサブスクライブするか、サービス メッセージをサブスクライブ解除するために、カスタム メッセージをサービスに送信します。サービスがアクティビティにデータを送信する場合、カスタム メッセージをアクティビティのメッセンジャーに送信します。アクティビティは、このようなメッセージを受信すると、新しい値をユーザーに表示します。
通知の使用を提案した回答では、データを画面に表示する簡単な方法を使用しています。アクティビティにデータを表示する場合 (通知バーではなく)、このより複雑なメッセージ パッシングの回答が必要です。
以下のコード例が長くなって申し訳ありませんが、伝えなければならない詳細がたくさんあります。
私のアクティビティでは、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().
}
}
アクティビティのカスタム メッセージ ハンドラーで:
....
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;
}