/* * Copyright 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.android.apps.mytracks.services; import com.google.android.apps.mytracks.util.TrackRecordingServiceConnectionUtils; import com.google.android.maps.mytracks.BuildConfig; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.RemoteException; import android.util.Log; /** * Wrapper for the track recording service. This handles service * start/bind/unbind/stop. The service must be started before it can be bound. * Returns the service if it is started and bound. * * @author Rodrigo Damazio */ public class TrackRecordingServiceConnection { private static final String TAG = TrackRecordingServiceConnection.class.getSimpleName(); private final DeathRecipient deathRecipient = new DeathRecipient() { @Override public void binderDied() { Log.d(TAG, "Service died."); setTrackRecordingService(null); } }; private final ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder service) { Log.i(TAG, "Connected to the service."); try { service.linkToDeath(deathRecipient, 0); } catch (RemoteException e) { Log.e(TAG, "Failed to bind a death recipient.", e); } setTrackRecordingService(ITrackRecordingService.Stub.asInterface(service)); } @Override public void onServiceDisconnected(ComponentName className) { Log.i(TAG, "Disconnected from the service."); setTrackRecordingService(null); } }; private final Context context; private final Runnable callback; private ITrackRecordingService trackRecordingService; /** * Constructor. * * @param context the context * @param callback the callback to invoke when the service binding changes */ public TrackRecordingServiceConnection(Context context, Runnable callback) { this.context = context; this.callback = callback; } /** * Starts and binds the service. */ public void startAndBind() { bindService(true); } /** * Binds the service if it is started. */ public void bindIfStarted() { bindService(false); } /** * Unbinds and stops the service. */ public void unbindAndStop() { unbind(); context.stopService(new Intent(context, TrackRecordingService.class)); } /** * Unbinds the service (but leave it running). */ public void unbind() { try { context.unbindService(serviceConnection); } catch (IllegalArgumentException e) { // Means not bound to the service. OK to ignore. } setTrackRecordingService(null); } /** * Gets the track recording service if bound. Returns null otherwise */ public ITrackRecordingService getServiceIfBound() { if (trackRecordingService != null && !trackRecordingService.asBinder().isBinderAlive()) { setTrackRecordingService(null); return null; } return trackRecordingService; } /** * Binds the service if it is started. * * @param startIfNeeded start the service if needed */ private void bindService(boolean startIfNeeded) { if (trackRecordingService != null) { // Service is already started and bound. return; } if (!startIfNeeded && !TrackRecordingServiceConnectionUtils.isRecordingServiceRunning(context)) { Log.d(TAG, "Service is not started. Not binding it."); return; } if (startIfNeeded) { Log.i(TAG, "Starting the service."); context.startService(new Intent(context, TrackRecordingService.class)); } Log.i(TAG, "Binding the service."); int flags = BuildConfig.DEBUG ? Context.BIND_DEBUG_UNBIND : 0; context.bindService(new Intent(context, TrackRecordingService.class), serviceConnection, flags); } /** * Sets the trackRecordingService. * * @param value the value */ private void setTrackRecordingService(ITrackRecordingService value) { trackRecordingService = value; if (callback != null) { callback.run(); } } }